]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Build fixes for in-tree and 32/64-bit
authorDJ Delorie <dj@delorie.com>
Fri, 3 Jun 2016 19:26:48 +0000 (15:26 -0400)
committerDJ Delorie <dj@delorie.com>
Thu, 30 Jun 2016 20:13:32 +0000 (16:13 -0400)
Expand the comments in mtrace-ctl.c to better explain how to use
this tracing controller.  The new docs assume the SO is built
and installed.

Build fixed for trace_run.c

Additional build pedantry to let trace_run.c be built with more
warnings/errors turned on.

Build/install trace_run and trace2dat

trace2dat takes dump files from mtrace-ctl.so and turns them into
mmap'able data files for trace_run, which "plays back" the logged
calls.

32-bit compatibility

Redesign tcache macros to account for differences between 64 and
32 bit systems.

malloc/Makefile
malloc/malloc.c
malloc/mtrace-ctl.c
malloc/mtrace.h
malloc/trace_run.c

index 2626a39031defad1b239423d0fea602be5df9c19..30248e47dafe3111aff1885b94dde609b5736970 100644 (file)
@@ -50,6 +50,13 @@ libmemusage-inhibit-o = $(filter-out .os,$(object-suffixes))
 libmtracectl-routines = mtrace-ctl
 libmtracectl-inhibit-o = $(filter-out .os,$(object-suffixes))
 
+others: $(objpfx)trace_run
+install-bin = trace_run
+install-bin-script = trace2dat
+
+$(objpfx)trace_run: $(objpfx)trace_run.o
+       $(LINK.o) -o $@ $(objpfx)trace_run.o -lpthread
+
 $(objpfx)tst-malloc-backtrace: $(shared-thread-library)
 $(objpfx)tst-malloc-thread-exit: $(shared-thread-library)
 $(objpfx)tst-malloc-thread-fail: $(shared-thread-library)
@@ -63,7 +70,7 @@ aux := set-freeres thread-freeres
 
 # The Perl script to analyze the output of the mtrace functions.
 ifneq ($(PERL),no)
-install-bin-script = mtrace
+install-bin-script += mtrace
 generated += mtrace
 
 # The Perl script will print addresses and to do this nicely we must know
@@ -82,7 +89,7 @@ ifneq ($(cross-compiling),yes)
 # If the gd library is available we build the `memusagestat' program.
 ifneq ($(LIBGD),no)
 others: $(objpfx)memusage
-install-bin = memusagestat
+install-bin += memusagestat
 install-bin-script += memusage
 generated += memusagestat memusage
 extra-objs += memusagestat.o
@@ -147,6 +154,9 @@ tst-malloc-usable-ENV = MALLOC_CHECK_=3
 
 sLIBdir := $(shell echo $(slibdir) | sed 's,lib\(\|64\)$$,\\\\$$LIB,')
 
+$(objpfx)trace2dat: trace2dat
+       cp $^ $@ && chmod +x $@
+
 $(objpfx)mtrace: mtrace.pl
        rm -f $@.new
        sed -e 's|@PERL@|$(PERL)|' -e 's|@XXX@|$(address-width)|' \
index c020fa2b9865a7099031bde76bfd46cd964f8df5..57aca089fa9b70ab040fb207942152c7f62b6d54 100644 (file)
@@ -1103,7 +1103,7 @@ volatile size_t __malloc_trace_buffer_head = 0;
 static __thread __malloc_trace_buffer_ptr trace_ptr;
 
 static void
-__mtb_trace_entry (uint32_t type, int64_t size, void *ptr1)
+__mtb_trace_entry (uint32_t type, size_t size, void *ptr1)
 {
   size_t head1;
 
@@ -1122,7 +1122,7 @@ __mtb_trace_entry (uint32_t type, int64_t size, void *ptr1)
   trace_ptr->path_m_f_realloc = 0;
   trace_ptr->path = 0;
   trace_ptr->size = size;
-  trace_ptr->ptr1 = (uint64_t) ptr1;
+  trace_ptr->ptr1 = ptr1;
   trace_ptr->ptr2 = 0;
 }
 
@@ -1158,7 +1158,7 @@ __malloc_get_trace_buffer (size_t *bufcount, size_t *bufhead)
 
 #define __MTB_TRACE_SET(var,value) \
   if (__builtin_expect (trace_ptr != NULL, 1)) \
-    trace_ptr->var = (uint64_t) value;
+    trace_ptr->var = value;
 
 #else
 #define __MTB_TRACE_ENTRY(type,size,ptr1)
@@ -3000,11 +3000,10 @@ mremap_chunk (mchunkptr p, size_t new_size)
 #define USE_TCACHE 1
 
 #if USE_TCACHE
-#define TCACHE_SHIFT   4
 /* we want 64 entries */
-#define MAX_TCACHE_SIZE        (1024 - (1 << TCACHE_SHIFT))
-#define TCACHE_IDX     ((MAX_TCACHE_SIZE >> TCACHE_SHIFT)+1)
-#define size2tidx(bytes) (((bytes)+(1<<TCACHE_SHIFT)-1)>>TCACHE_SHIFT)
+#define MAX_TCACHE_SIZE                (MALLOC_ALIGNMENT * 63)
+#define TCACHE_IDX             ((MAX_TCACHE_SIZE / MALLOC_ALIGNMENT) + 1)
+#define size2tidx(bytes)       (((bytes) + MALLOC_ALIGNMENT - 1) / MALLOC_ALIGNMENT)
 
 /* Rounds up, so...
    idx 0   bytes 0
@@ -3105,7 +3104,7 @@ __libc_malloc (size_t bytes)
       && tcache.initted == 1)
     {
       void *ent;
-      size_t tc_bytes = tc_idx << TCACHE_SHIFT;
+      size_t tc_bytes = tc_idx * MALLOC_ALIGNMENT;
       size_t tc_ibytes;
       size_t total_bytes;
       int i;
@@ -4414,7 +4413,7 @@ _int_free (mstate av, mchunkptr p, int have_lock)
 
 #if USE_TCACHE
   {
-    int tc_idx = size2tidx (size - SIZE_SZ*2);
+    int tc_idx = size2tidx (size - SIZE_SZ);
 
     if (size < MAX_TCACHE_SIZE
        && tcache.counts[tc_idx] < TCACHE_FILL_COUNT
index 949098a2712d7640c165bf7c89d33ac88c580212..e1446ac1df9e79060d67038bc4d462f8cdbcab23 100644 (file)
@@ -5,13 +5,26 @@
 #include <unistd.h>
 #include <sys/mman.h>
 
-/* Build like this:
+/* This module is a stand-alone control program for malloc's internal
+   trace buffer.  It is intended to be preloaded like this:
 
-   gcc -shared -fpic mtrace-ctl.c -o /tmp/mtrace-ctl.so ../../glibc.build/libc.so
+   LD_PRELOAD=/usr/lib/libmtracectl.so ./myprog
 
-   Invoke like this:
+   This module uses the following environment variables:
 
-   LD_PRELOAD=/tmp/mtrace-ctl.so ./myprog
+   MTRACE_CTL_COUNT - how many records to store (default: 1000).  Each
+   record is 32 bytes, and the entire buffer is mmap'd at once.  If
+   the buffer isn't big enough, it will overwrite early records with
+   newer ones.  The total number of trace records is reported in the
+   output file so that a larger buffer may be allocated on future runs.
+
+   MTRACE_CTL_FILE - the output file name (default:
+   /tmp/mtrace-$$.out).  Note that the default is per-pid but there is
+   no way to specify a per-pid pattern via this environment variable.
+
+   The output file will contain a header that says how many trace
+   records were seen (which is usually more or less than the trace
+   buffer size).  The trace buffer is then dumped one entry per line.
 
 */
 
@@ -106,9 +119,9 @@ djend(void)
                   t->path_munmap ? 'U' : '-',
                   t->path_m_f_realloc ? 'R' : '-',
                   t->path_hook ? 'H' : '-',
-                  (long long unsigned int) t->ptr1,
+                  (long long unsigned int) (size_t) t->ptr1,
                   (long long unsigned int) t->size,
-                  (long long unsigned int) t->ptr2);
+                  (long long unsigned int) (size_t) t->ptr2);
          break;
        }
     }
index 8dea72c472dd14a8b6d92243de01b8d4df0f0e0e..db3cbe51a6838fdde715bf16400a2c0ce3dc46f8 100644 (file)
@@ -36,9 +36,9 @@ struct __malloc_trace_buffer_s {
   uint32_t path_hook:1; /* A hook was used to complete the request */
   uint32_t path:16; /* remaining bits */
 
-  uint64_t ptr1;
-  uint64_t ptr2;
-  uint64_t size;
+  void *ptr1;
+  void *ptr2;
+  size_t size;
 };
 
 typedef struct __malloc_trace_buffer_s *__malloc_trace_buffer_ptr;
index 52d548738ec253e1ffa3ba9202755064553707af..e34ad90c01c7051c05096806a854a9ad335e34f0 100644 (file)
 #define C_NTHREADS 10
 #define C_START_THREAD 11
 
-static __inline__ int64_t rdtsc_s(void)
+#ifdef x86_64
+
+#define ticks_t int64_t
+
+static __inline__ ticks_t rdtsc_s(void)
 {
   unsigned a, d;
   asm volatile("cpuid" ::: "%rax", "%rbx", "%rcx", "%rdx");
@@ -33,7 +37,7 @@ static __inline__ int64_t rdtsc_s(void)
   return ((unsigned long)a) | (((unsigned long)d) << 32);
 }
 
-static __inline__ int64_t rdtsc_e(void)
+static __inline__ ticks_t rdtsc_e(void)
 {
   unsigned a, d;
   asm volatile("rdtscp" : "=a" (a), "=d" (d));
@@ -41,9 +45,31 @@ static __inline__ int64_t rdtsc_e(void)
   return ((unsigned long)a) | (((unsigned long)d) << 32);
 }
 
-static int64_t diff_timeval (struct timeval e, struct timeval s)
+#else
+
+#define ticks_t int32_t
+
+static __inline__ ticks_t rdtsc_s(void)
+{
+  unsigned a, d;
+  asm volatile("cpuid" ::: "%ax", "%bx", "%cx", "%dx");
+  asm volatile("rdtsc" : "=a" (a), "=d" (d));
+  return ((unsigned long)a) | (((unsigned long)d) << 16);
+}
+
+static __inline__ ticks_t rdtsc_e(void)
+{
+  unsigned a, d;
+  asm volatile("rdtscp" : "=a" (a), "=d" (d));
+  asm volatile("cpuid" ::: "%ax", "%bx", "%cx", "%dx");
+  return ((unsigned long)a) | (((unsigned long)d) << 16);
+}
+
+#endif
+
+static ticks_t diff_timeval (struct timeval e, struct timeval s)
 {
-  int64_t usec;
+  ticks_t usec;
   if (e.tv_usec < s.tv_usec)
     usec = (e.tv_usec + 1000000 - s.tv_usec) + (e.tv_sec-1 - s.tv_sec)*1000000;
   else
@@ -65,7 +91,7 @@ pthread_mutex_t cmutex = PTHREAD_MUTEX_INITIALIZER;
 static char cbuf[NCBUF][30];
 static int ci = 0;
 
-char *comma(int64_t x)
+char *comma(ticks_t x)
 {
   char buf[30], *bs, *bd;
   int l, i, idx;
@@ -77,7 +103,7 @@ char *comma(int64_t x)
   bs = buf;
   bd = cbuf[idx];
 
-  sprintf(buf, "%lld", x);
+  sprintf(buf, "%lld", (long long int)x);
   l = strlen(buf);
   i = l;
   while (*bs)
@@ -101,21 +127,23 @@ static unsigned char *data;
 static size_t n_data;
 
 static pthread_mutex_t stat_mutex = PTHREAD_MUTEX_INITIALIZER;
-int64_t malloc_time = 0, malloc_count = 0;
-int64_t calloc_time = 0, calloc_count = 0;
-int64_t realloc_time = 0, realloc_count = 0;
-int64_t free_time = 0, free_count = 0;
+ticks_t malloc_time = 0, malloc_count = 0;
+ticks_t calloc_time = 0, calloc_count = 0;
+ticks_t realloc_time = 0, realloc_count = 0;
+ticks_t free_time = 0, free_count = 0;
 
 pthread_mutex_t stop_mutex = PTHREAD_MUTEX_INITIALIZER;
 int threads_done = 0;
 
 //#define dprintf printf
-#define dprintf(...) 1
+#define dprintf(...) (void)1
 
 //#define mprintf printf
-#define mprintf(...) 1
+//#define MDEBUG 1
+#define mprintf(...) (void)1
 
 #define myabort() my_abort_2(me, __LINE__)
+void
 my_abort_2 (pthread_t me, int line)
 {
   fprintf(stderr, "Abort thread %d at line %d\n", (int)me, line);
@@ -127,16 +155,10 @@ wmem (volatile void *ptr, int count)
 {
   char *p = (char *)ptr;
   int i;
-  size_t sz;
 
   if (!p)
     return;
 
-  //  sz = *((size_t *)ptr-1) & ~7;
-  //  fprintf(stderr, "wmem: %p size %x csize %x\n", ptr,
-  //     count, sz);
-  //  if (sz < 4*sizeof(size_t))
-  //    abort();
   for (i=0; i<count; i+=8)
     p[i] = 0x11;
 }
@@ -162,12 +184,14 @@ thread_common (void *my_data_v)
   pthread_t me = pthread_self ();
   size_t p1, p2, sz;
   unsigned char *cp = my_data_v;
-  int64_t my_malloc_time = 0, my_malloc_count = 0;
-  int64_t my_calloc_time = 0, my_calloc_count = 0;
-  int64_t my_realloc_time = 0, my_realloc_count = 0;
-  int64_t my_free_time = 0, my_free_count = 0;
-  int64_t stime;
+  ticks_t my_malloc_time = 0, my_malloc_count = 0;
+  ticks_t my_calloc_time = 0, my_calloc_count = 0;
+  ticks_t my_realloc_time = 0, my_realloc_count = 0;
+  ticks_t my_free_time = 0, my_free_count = 0;
+  ticks_t stime;
+#ifdef MDEBUG
   volatile void *tmp;
+#endif
 
   while (1)
     {
@@ -243,7 +267,9 @@ thread_common (void *my_data_v)
            myabort();
          stime = rdtsc_s();
          Q1;
+#ifdef MDEBUG
          tmp = ptrs[p1];
+#endif
          ptrs[p2] = realloc ((void *)ptrs[p1], sz);
          mprintf("%p = relloc(%p,%lx)\n", ptrs[p2], tmp,sz);
          Q2;
@@ -312,7 +338,7 @@ static void *alloc_mem (size_t amt)
 static pthread_t *thread_ids;
 
 void *
-my_malloc (char *msg, int size, unsigned char **cp, size_t *psz, size_t count)
+my_malloc (const char *msg, int size, unsigned char **cp, size_t *psz, size_t count)
 {
   void *rv;
   if (psz)
@@ -344,7 +370,7 @@ static const char * const scan_names[] = {
 void
 malloc_scan_callback (void *ptr, size_t length, int type)
 {
-  printf("%s: ptr %p length %llx\n", scan_names[type], ptr, length);
+  printf("%s: ptr %p length %llx\n", scan_names[type], ptr, (long long)length);
 }
 
 #define MY_ALLOC(T, psz)                               \
@@ -355,16 +381,16 @@ malloc_scan_callback (void *ptr, size_t length, int type)
 int
 main(int argc, char **argv)
 {
-  int64_t start;
-  int64_t end;
-  int64_t usec;
+  ticks_t start=0;
+  ticks_t end;
+  ticks_t usec;
   struct timeval tv_s, tv_e;
   int fd;
   struct stat statb;
   unsigned char *cp;
   int thread_idx = 0;
   int i;
-  size_t n_threads;
+  size_t n_threads = 0;
   size_t idx;
   struct rusage res_start, res_end;
 
@@ -445,7 +471,7 @@ main(int argc, char **argv)
   printf("%s usec wall time\n", comma(usec));
 
   usec = diff_timeval (res_end.ru_utime, res_start.ru_utime);
-  printf("%s usec across %d thread%s\n", comma(usec), n_threads, n_threads == 1 ? "" : "s");
+  printf("%s usec across %d thread%s\n", comma(usec), (int)n_threads, n_threads == 1 ? "" : "s");
   printf("%s Kb Max RSS (%s -> %s)\n",
         comma(res_end.ru_maxrss - res_start.ru_maxrss),
         comma(res_start.ru_maxrss), comma(res_end.ru_maxrss));
@@ -473,12 +499,14 @@ main(int argc, char **argv)
       }
 #endif
 
+#if 0
   /* This will fail (crash) for system glibc but that's OK.  */
   __malloc_scan_chunks(malloc_scan_callback);
 
   malloc_info (0, stdout);
+#endif
 
-#if 1
+#if 0
   /* ...or report them as used.  */
   for (idx=0; idx<n_ptrs; idx++)
     if (ptrs[idx])