]> sourceware.org Git - systemtap.git/commitdiff
Add support for memory allocation tracking.
authorhunt <hunt>
Tue, 15 Jan 2008 16:57:20 +0000 (16:57 +0000)
committerhunt <hunt>
Tue, 15 Jan 2008 16:57:20 +0000 (16:57 +0000)
17 files changed:
runtime/ChangeLog
runtime/alloc.c
runtime/counter.c
runtime/map.c
runtime/print.c
runtime/stack-i386.c
runtime/stack-x86_64.c
runtime/stat.c
runtime/sym.c
runtime/time.c
runtime/transport/ChangeLog
runtime/transport/control.c
runtime/transport/procfs.c
runtime/transport/relayfs.c
runtime/transport/symbols.c
runtime/transport/transport.c
runtime/transport/utt.c

index 8fa116955285897d4a5ec2b15c793b908eb9e974..7536cc883b1d6dbf9dc9753f8756e5fc535c171c 100644 (file)
@@ -1,3 +1,13 @@
+2008-01-14  Martin Hunt  <hunt@redhat.com>
+
+       * print.c (_stp_print_kernel_info): New function.
+       (all):  Call stp memory functions.
+
+       * alloc.c: Rewrite to track allocated memory if 
+       DEBUG_MEM is defined.
+       * counter.c, map.c, stat.c, time.c: Call stp
+       memory functions.
+       
 2007-11-14  Zhaolei  <zhaolei@cn.fujitsu.com>
 
        From Cai Fei <caifei@cn.fujitsu.com>
index 8f2a7451ebdb4f214805925ec8da97a4a6569e53..71b592a7cd333762a57af873074e94404b7948f1 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- linux-c -*- 
  * Memory allocation functions
- * Copyright (C) 2005, 2006, 2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
  *
  * This file is part of systemtap, and is free software.  You can
  * redistribute it and/or modify it under the terms of the GNU General
 #ifndef _ALLOC_C_
 #define _ALLOC_C_
 
-/* counters of how much memory has been allocated */
-static int _stp_allocated_memory = 0;
 static int _stp_allocated_net_memory = 0;
-
 #define STP_ALLOC_FLAGS (GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN)
 
+#define DEBUG_MEM
+/*
+ * If DEBUG_MEM is defined (stap -DDEBUG_MEM ...) then full memory
+ * tracking is used. Each allocation is recorded and matched with 
+ * a free. Also a fence is set around the allocated memory so overflows
+ * and underflows can be detected. Errors are written to the system log
+ * with printk.
+ *
+ * NOTE: if youy system is slow or your script makes a very large number
+ * of allocations, you may get a warning in the system log:
+ * BUG: soft lockup - CPU#1 stuck for 11s! [staprun:28269]
+ * This is an expected side-effect of the overhead of tracking, especially
+ * with a simple linked list of allocations. Optimization
+ * would be nice, but DEBUG_MEM is only for testing.
+ */
+
+#ifdef DEBUG_MEM
+
+static spinlock_t _stp_mem_lock = SPIN_LOCK_UNLOCKED;
+static int _stp_allocated_memory = 0;
+
+#define MEM_MAGIC 0xc11cf77f
+#define MEM_FENCE_SIZE 32
+
+enum _stp_memtype { MEM_KMALLOC, MEM_VMALLOC, MEM_PERCPU };
+
+typedef struct {
+       enum _stp_memtype type;
+       char *alloc;
+       char *free;
+} _stp_malloc_type;
+
+static const _stp_malloc_type const _stp_malloc_types[] = {
+       {MEM_KMALLOC, "kmalloc", "kfree"},
+       {MEM_VMALLOC, "vmalloc", "vfree"},
+       {MEM_PERCPU, "alloc_percpu", "free_percpu"}
+};
+
+struct _stp_mem_entry {
+       struct list_head list;
+       int32_t magic;
+       enum _stp_memtype type;
+       size_t len;
+       void *addr;
+};
+
+#define MEM_DEBUG_SIZE (2*MEM_FENCE_SIZE+sizeof(struct _stp_mem_entry))
+
+static LIST_HEAD(_stp_mem_list);
+
+void _stp_check_mem_fence (char *addr, int size)
+{
+       char *ptr;
+       int i;
+
+       ptr = addr - MEM_FENCE_SIZE;
+       while (ptr < addr) {
+               if (*ptr != 0x55) {
+                       printk("SYSTEMTAP ERROR: Memory fence corrupted before allocated memory\n");
+                       printk("at addr %p. (Allocation starts at %p)", ptr, addr);
+                       return;
+               }
+               ptr++;
+       }
+       ptr = addr + size;
+       while (ptr < addr + size + MEM_FENCE_SIZE) {
+               if (*ptr != 0x55) {
+                       printk("SYSTEMTAP ERROR: Memory fence corrupted after allocated memory\n");
+                       printk("at addr %p. (Allocation ends at %p)", ptr, addr + size - 1);
+                       return;
+               }
+               ptr++;
+       }
+}
+
+void *_stp_mem_debug_setup(void *addr, size_t size, enum _stp_memtype type)
+{
+       struct list_head *p;
+       struct _stp_mem_entry *m;
+       memset(addr, 0x55, MEM_FENCE_SIZE);
+       addr += MEM_FENCE_SIZE;
+       memset(addr + size, 0x55, MEM_FENCE_SIZE);
+       p = (struct list_head *)(addr + size + MEM_FENCE_SIZE);
+       m = (struct _stp_mem_entry *)p;
+       m->magic = MEM_MAGIC;
+       m->type = type;
+       m->len = size;
+       m->addr = addr;
+       spin_lock(&_stp_mem_lock);
+       list_add(p, &_stp_mem_list); 
+       spin_unlock(&_stp_mem_lock);
+       return addr;
+}
+
+/* Percpu allocations don't have the fence. Implementing it is problematic. */
+void _stp_mem_debug_percpu(struct _stp_mem_entry *m, void *addr, size_t size)
+{
+       struct list_head *p = (struct list_head *)m;
+       m->magic = MEM_MAGIC;
+       m->type = MEM_PERCPU;
+       m->len = size;
+       m->addr = addr;
+       spin_lock(&_stp_mem_lock);
+       list_add(p, &_stp_mem_list);
+       spin_unlock(&_stp_mem_lock);    
+}
+
+void _stp_mem_debug_free(void *addr, enum _stp_memtype type)
+{
+       int found = 0;
+       struct list_head *p, *tmp;
+       struct _stp_mem_entry *m = NULL;
+
+       spin_lock(&_stp_mem_lock);
+       list_for_each_safe(p, tmp, &_stp_mem_list) {
+               m = list_entry(p, struct _stp_mem_entry, list);
+               if (m->addr == addr) {
+                       list_del(p);
+                       found = 1;
+                       break;
+               }
+       }
+       spin_unlock(&_stp_mem_lock);
+       if (!found) {
+               printk("SYSTEMTAP ERROR: Free of unallocated memory %p type=%s\n", 
+                      addr, _stp_malloc_types[type].free);
+               return;
+       }
+       if (m->magic != MEM_MAGIC) {
+               printk("SYSTEMTAP ERROR: Memory at %p corrupted!!\n", addr);
+               return;
+       }
+       if (m->type != type) {
+               printk("SYSTEMTAP ERROR: Memory allocated with %s and freed with %s\n",
+                      _stp_malloc_types[m->type].alloc,                       
+                      _stp_malloc_types[type].free);
+       }
+       
+       switch (m->type) {
+       case MEM_KMALLOC:
+               _stp_check_mem_fence(addr, m->len);
+               kfree(addr - MEM_FENCE_SIZE);
+               break;
+       case MEM_PERCPU:
+               free_percpu(addr);
+               kfree(p);
+               break;
+       case MEM_VMALLOC:
+               _stp_check_mem_fence(addr, m->len);
+               vfree(addr - MEM_FENCE_SIZE);           
+               break;
+       default:
+               printk("SYSTEMTAP ERROR: Attempted to free memory at addr %p len=%d with unknown allocation type.\n", addr, (int)m->len);
+       }
+
+       return;
+}
+#endif
+
 static void *_stp_kmalloc(size_t size)
 {
-       void *ret = kmalloc(size, STP_ALLOC_FLAGS);
-       if (ret)
+#ifdef DEBUG_MEM
+       void *ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS);
+       if (likely(ret)) {
+               ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
                _stp_allocated_memory += size;
+       }
        return ret;
+#else
+       return kmalloc(size, STP_ALLOC_FLAGS);
+#endif
 }
 
 static void *_stp_kzalloc(size_t size)
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
 {
-       void *ret = kmalloc(size, STP_ALLOC_FLAGS);
-       if (ret) {
+#ifdef DEBUG_MEM
+       void *ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS);
+       if (likely(ret)) {
+               ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
                memset (ret, 0, size);
                _stp_allocated_memory += size;
        }
+#else
+       void *ret = kmalloc(size, STP_ALLOC_FLAGS);
+       if (likely(ret))
+               memset (ret, 0, size);
+#endif /* DEBUG_MEM */
        return ret;
 }
-#else
+#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */
 {
-       void *ret = kzalloc(size, STP_ALLOC_FLAGS);
-       if (ret)
+#ifdef DEBUG_MEM
+       void *ret = kzalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS);
+       if (likely(ret)) {
+               ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
                _stp_allocated_memory += size;
+       }
        return ret;
-}
+#else
+       return kzalloc(size, STP_ALLOC_FLAGS);
 #endif
+}
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) */
 
 static void *_stp_vmalloc(unsigned long size)
 {
-       void *ret = __vmalloc(size, STP_ALLOC_FLAGS, PAGE_KERNEL);
-       if (ret)
+#ifdef DEBUG_MEM
+       void *ret = __vmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, PAGE_KERNEL);
+       if (likely(ret)) {
+               ret = _stp_mem_debug_setup(ret, size, MEM_VMALLOC);
                _stp_allocated_memory += size;
+       }
        return ret;
+#else
+       return __vmalloc(size, STP_ALLOC_FLAGS, PAGE_KERNEL);
+#endif
+
 }
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)
-#define _stp_alloc_percpu(size) __alloc_percpu(size, 8)
+static void *_stp_alloc_percpu(size_t size)
+{
+#ifdef DEBUG_MEM
+       void *ret = __alloc_percpu(size, 8);
+       if (likely(ret)) {
+               struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), STP_ALLOC_FLAGS);
+               if (unlikely(m == NULL)) {
+                       free_percpu(ret);
+                       return NULL;
+               }
+               _stp_mem_debug_percpu(m, ret, size);
+               _stp_allocated_memory += size * num_online_cpus();
+       }
+       return ret;
 #else
-#define _stp_alloc_percpu(size) __alloc_percpu(size)
+       return __alloc_percpu(size, 8);
 #endif
+}
+#else
+static void *_stp_alloc_percpu(size_t size)
+{
+#ifdef DEBUG_MEM
+       void *ret = __alloc_percpu(size);
+       if (likely(ret)) {
+               struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), STP_ALLOC_FLAGS);
+               if (unlikely(m == NULL)) {
+                       free_percpu(ret);
+                       return NULL;
+               }
+               _stp_mem_debug_percpu(m, ret, size);
+               _stp_allocated_memory += size * num_online_cpus();
+       }
+       return ret;
+#else
+       return __alloc_percpu(size);
+#endif
+}
+#endif /* LINUX_VERSION_CODE */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
-#define kmalloc_node(size,flags,node) kmalloc(size,flags)
+#define _stp_kmalloc_node(size,node) _stp_kmalloc(size)
+#else
+static void *_stp_kmalloc_node(size_t size, int node)
+{
+#ifdef DEBUG_MEM
+       void *ret = kmalloc_node(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, node);
+       if (likely(ret)) {
+               ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC);
+               _stp_allocated_memory += size;
+       }
+       return ret;
+#else
+       return kmalloc_node(size, STP_ALLOC_FLAGS, node);
+#endif
+}
 #endif /* LINUX_VERSION_CODE */
 
+void _stp_kfree(void *addr)
+{
+#ifdef DEBUG_MEM
+       _stp_mem_debug_free(addr, MEM_KMALLOC);
+#else
+       kfree(addr);
+#endif
+}
+
+void _stp_vfree(void *addr)
+{
+#ifdef DEBUG_MEM
+       _stp_mem_debug_free(addr, MEM_VMALLOC);
+#else
+       vfree(addr);
+#endif
+}
+
+void _stp_free_percpu(void *addr)
+{
+#ifdef DEBUG_MEM
+       _stp_mem_debug_free(addr, MEM_PERCPU);
+#else
+       free_percpu(addr);
+#endif
+}
+
+void _stp_mem_debug_done(void)
+{
+#ifdef DEBUG_MEM
+       struct list_head *p, *tmp;
+       struct _stp_mem_entry *m;
+
+       spin_lock(&_stp_mem_lock);
+       list_for_each_safe(p, tmp, &_stp_mem_list) {
+               m = list_entry(p, struct _stp_mem_entry, list);
+               list_del(p);
+
+               printk("SYSTEMTAP ERROR: Memory %p len=%d allocation type: %s. Not freed.\n", 
+                      m->addr, (int)m->len, _stp_malloc_types[m->type].alloc);
+
+               if (m->magic != MEM_MAGIC) {
+                       printk("SYSTEMTAP ERROR: Memory at %p len=%d corrupted!!\n", m->addr, (int)m->len);
+                       /* Don't free. Too dangerous */
+                       goto done;
+               }
+
+               switch (m->type) {
+               case MEM_KMALLOC:
+                       _stp_check_mem_fence(m->addr, m->len);
+                       kfree(m->addr - MEM_FENCE_SIZE);
+                       break;
+               case MEM_PERCPU:
+                       free_percpu(m->addr);
+                       kfree(p);
+                       break;
+               case MEM_VMALLOC:
+                       _stp_check_mem_fence(m->addr, m->len);
+                       vfree(m->addr - MEM_FENCE_SIZE);                
+                       break;
+               default:
+                       printk("SYSTEMTAP ERROR: Attempted to free memory at addr %p len=%d with unknown allocation type.\n", m->addr, (int)m->len);
+               }
+       }
+done:
+       spin_unlock(&_stp_mem_lock);
+
+       return;
+
+#endif
+}
 #endif /* _ALLOC_C_ */
index def734f6ca57c6bd1063b87d974612ac6b80edd7..42555dfad45dd9c75dd54df101a26449857ac958 100644 (file)
@@ -54,7 +54,7 @@ typedef struct _counter *Counter;
  */
 Counter _stp_counter_init (void)
 {
-       Counter cnt = alloc_percpu (struct _counter);
+       Counter cnt = _stp_alloc_percpu (struct _counter);
 #if NEED_COUNTER_LOCKS == 1
        {
                int i;
@@ -135,7 +135,7 @@ int64_t _stp_counter_get (Counter cnt, int clear)
  */
 void _stp_counter_free (Counter cnt)
 {
-       free_percpu (cnt);
+       _stp_free_percpu (cnt);
 }
 
 /** @} */
index 2acf2fe2f327937cf7e5b28ddb00d545aedf3081..709908762f5973861fd598b6a80b0c966f138904 100644 (file)
@@ -205,18 +205,13 @@ static int _stp_map_init(MAP m, unsigned max_entries, int type, int key_size, in
                
                for (i = 0; i < max_entries; i++) {
                        if (cpu < 0)
-                               tmp = kmalloc(size, STP_ALLOC_FLAGS);
+                               tmp = _stp_kmalloc(size);
                        else
-                               tmp = kmalloc_node(size, STP_ALLOC_FLAGS, cpu_to_node(cpu));
+                               tmp = _stp_kmalloc_node(size, cpu_to_node(cpu));
                
                        if (!tmp)
                                return -1;
                        
-                       if (cpu < 0)
-                               _stp_allocated_memory += size;
-                       else
-                               _stp_allocated_memory += size * num_online_cpus();
-                               
 //                     dbug ("allocated %lx\n", (long)tmp);
                        list_add((struct list_head *)tmp, &m->pool);
                        ((struct map_node *)tmp)->map = m;
@@ -252,10 +247,9 @@ static PMAP _stp_pmap_new(unsigned max_entries, int type, int key_size, int data
        if (pmap == NULL)
                return NULL;
 
-       pmap->map = map = (MAP) alloc_percpu (struct map_root);
+       pmap->map = map = (MAP) _stp_alloc_percpu (sizeof(struct map_root));
        if (map == NULL) 
                goto err;
-       _stp_allocated_memory += sizeof(struct map_root) * num_online_cpus();
 
        /* initialize the memory lists first so if allocations fail */
         /* at some point, it is easy to clean up. */
@@ -284,9 +278,9 @@ err1:
                m = per_cpu_ptr (map, i);
                __stp_map_del(m);
        }
-       free_percpu(map);
+       _stp_free_percpu(map);
 err:
-       kfree(pmap);
+       _stp_kfree(pmap);
        return NULL;
 }
 
@@ -387,13 +381,13 @@ static void __stp_map_del(MAP map)
        /* free unused pool */
        list_for_each_safe(p, tmp, &map->pool) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
 
        /* free used list */
        list_for_each_safe(p, tmp, &map->head) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
 }
 
@@ -409,7 +403,7 @@ void _stp_map_del(MAP map)
 
        __stp_map_del(map);
 
-       kfree(map);
+       _stp_kfree(map);
 }
 
 void _stp_pmap_del(PMAP pmap)
@@ -423,12 +417,12 @@ void _stp_pmap_del(PMAP pmap)
                MAP m = per_cpu_ptr (pmap->map, i);
                __stp_map_del(m);
        }
-       free_percpu(pmap->map);
+       _stp_free_percpu(pmap->map);
 
        /* free agg map elements */
        __stp_map_del(&pmap->agg);
        
-       kfree(pmap);
+       _stp_kfree(pmap);
 }
 
 /* sort keynum values */
index a451f62227a33fdeb7fd0009a45aeba33407fea6..0442ba0984bcaec0b903cdd96262352837e12154 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- linux-c -*- 
  * Print Functions
- * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2007-2008 Red Hat Inc.
  *
  * This file is part of systemtap, and is free software.  You can
  * redistribute it and/or modify it under the terms of the GNU General
@@ -50,26 +50,25 @@ void *Stp_lbuf = NULL;
 /* create percpu print and io buffers */
 int _stp_print_init (void)
 {
-       Stp_pbuf = alloc_percpu(_stp_pbuf);
+       Stp_pbuf = _stp_alloc_percpu(sizeof(_stp_pbuf));
        if (unlikely(Stp_pbuf == 0))
                return -1;
 
        /* now initialize IO buffer used in io.c */
-       Stp_lbuf = alloc_percpu(_stp_lbuf);
+       Stp_lbuf = _stp_alloc_percpu(sizeof(_stp_lbuf));
        if (unlikely(Stp_lbuf == 0)) {
-               free_percpu(Stp_pbuf);
+               _stp_free_percpu(Stp_pbuf);
                return -1;
        }
-       _stp_allocated_memory += (sizeof(_stp_pbuf)+sizeof(_stp_lbuf)) * num_online_cpus();
        return 0;
 }
 
 void _stp_print_cleanup (void)
 {
        if (Stp_pbuf)
-               free_percpu(Stp_pbuf);
+               _stp_free_percpu(Stp_pbuf);
        if (Stp_lbuf)
-               free_percpu(Stp_lbuf);
+               _stp_free_percpu(Stp_lbuf);
 }
 
 #define __DEF_EXPORT_FN(fn, postfix) fn ## _ ## postfix
@@ -276,5 +275,31 @@ static char *next_fmt(char *fmt, int *num)
        return f;
 }
 
+void _stp_print_kernel_info(char *vstr, int ctx, int num_probes)
+{
+#ifdef DEBUG_MEM
+       printk(KERN_DEBUG "%s: systemtap: %s, base: %p, memory: %lu+%lu+%u+%u+%u data+text+ctx+net+alloc, probes: %d\n",
+              THIS_MODULE->name,
+              vstr, 
+              THIS_MODULE->module_core,  
+              (unsigned long) (THIS_MODULE->core_size - THIS_MODULE->core_text_size),
+               (unsigned long) THIS_MODULE->core_text_size,
+              ctx,
+              _stp_allocated_net_memory,
+              _stp_allocated_memory - _stp_allocated_net_memory,
+               num_probes);
+#else
+       printk(KERN_DEBUG "%s: systemtap: %s, base: %p, memory: %lu+%lu+%u+%u data+text+ctx+net, probes: %d\n",
+              THIS_MODULE->name,
+              vstr, 
+              THIS_MODULE->module_core,  
+              (unsigned long) (THIS_MODULE->core_size - THIS_MODULE->core_text_size),
+               (unsigned long) THIS_MODULE->core_text_size,
+              ctx,
+              _stp_allocated_net_memory,
+              num_probes);
+#endif
+}
+
 /** @} */
 #endif /* _PRINT_C_ */
index a80de048776b4190d45c3f46ed5be2cefc2d7676..3675fc97117db767c275b318da962c864a01c81c 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- linux-c -*-
  * i386 stack tracing functions
- * Copyright (C) 2005, 2006, 2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
  *
  * This file is part of systemtap, and is free software.  You can
  * redistribute it and/or modify it under the terms of the GNU General
@@ -37,7 +37,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
 #else
        while (_stp_valid_stack_ptr(context, (unsigned long)stack)) {
                addr = *stack++;
-               _stp_func_print(addr, verbose);
+               _stp_func_print(addr, verbose, 1);
        }
 #endif
 }
index 16e3bf7c6733c459e352f962dd8c5e9a1e542187..186b2ad440b695785d09b943e2ec034cd9956358 100644 (file)
@@ -15,6 +15,6 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
 
        while ((long)stack & (THREAD_SIZE-1)) {
                addr = *stack++;
-               _stp_func_print(addr, verbose);
+               _stp_func_print(addr, verbose, 1);
        }
 }
index 3df1d0639c77f0f7f1c47ea0d91ceebfe474d247..298a6653e0bd1b5f69d32acd8b391fed7fb4597d 100644 (file)
@@ -52,7 +52,7 @@
 /** Stat struct for stat.c. Maps do not need this */
 struct _Stat {
        struct _Hist hist;
-       /* per-cpu data. allocated with alloc_percpu() */
+       /* per-cpu data. allocated with _stp_alloc_percpu() */
        stat *sd;
        /* aggregated data */   
        stat *agg;  
@@ -130,9 +130,9 @@ Stat _stp_stat_init (int type, ...)
        return st;
 
 exit2:
-       kfree (sd);
+       _stp_kfree (sd);
 exit1:
-       kfree (st);
+       _stp_kfree (st);
        return NULL;
 }
 
@@ -144,9 +144,9 @@ exit1:
 void _stp_stat_del (Stat st)
 {
        if (st) {
-               free_percpu (st->sd);
-               kfree (st->agg);
-               kfree (st);
+               _stp_free_percpu (st->sd);
+               _stp_kfree (st->agg);
+               _stp_kfree (st);
        }
 }
        
index c40f48dbc62c05fbabd0afa4495db13cccaf6458..56c93064a298605b3d1218a7c4752ceded01cd64 100644 (file)
@@ -193,7 +193,7 @@ void _stp_symbol_print (unsigned long address)
        _stp_printf ("%p", (int64_t)address);
 
        if (name) {             
-               if (modname)
+               if (modname && *modname)
                        _stp_printf (" : %s+%#lx/%#lx [%s]", name, offset, size, modname);
                else
                        _stp_printf (" : %s+%#lx/%#lx", name, offset, size);
@@ -202,22 +202,28 @@ void _stp_symbol_print (unsigned long address)
 
 /* Like _stp_symbol_print, except only print if the address is a valid function address */
 
-void _stp_func_print (unsigned long address, int verbose)
+void _stp_func_print (unsigned long address, int verbose, int exact)
 { 
        char *modname;
         const char *name;
         unsigned long offset, size;
+       char *exstr;
+
+       if (exact)
+               exstr = "";
+       else
+               exstr = " (inexact)";
 
         name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
 
        if (name) {
                if (verbose) {
-                       if (modname)
-                               _stp_printf (" %p : %s+%#lx/%#lx [%s]\n", 
-                                            (int64_t)address, name, offset, size, modname);
+                       if (modname && *modname)
+                               _stp_printf (" %p : %s+%#lx/%#lx [%s]%s\n", 
+                                            (int64_t)address, name, offset, size, modname, exstr);
                        else
-                               _stp_printf (" %p : %s+%#lx/%#lx\n", 
-                                            (int64_t)address, name, offset, size);
+                               _stp_printf (" %p : %s+%#lx/%#lx%s\n", 
+                                            (int64_t)address, name, offset, size, exstr);
                } else 
                        _stp_printf ("%p ", (int64_t)address);
        }
index 688427f43b988c7c9ef812496f5e5497a9bfcfae..52a2edbb46e49a899e78c8329af40450f4d554a0 100644 (file)
@@ -219,7 +219,7 @@ _stp_kill_time(void)
         }
 #endif
 
-        free_percpu(stp_time);
+        _stp_free_percpu(stp_time);
     }
 }
 
@@ -229,10 +229,9 @@ _stp_init_time(void)
 {
     int ret = 0;
 
-    stp_time = alloc_percpu(stp_time_t);
+    stp_time = _stp_alloc_percpu(sizeof(stp_time_t));
     if (unlikely(stp_time == 0))
            return -1;
-    _stp_allocated_memory += sizeof(stp_time_t) * num_online_cpus();
     
     stp_timer_reregister = 1;
     ret = on_each_cpu(__stp_init_time, NULL, 0, 1);
index 263a6bf8c1a1be52f5220fb8aefc59ea8a31bd9b..26268e661cd16c90bde9865e037348d2b29434ad 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-15  Martin Hunt  <hunt@redhat.com>
+
+       Support for DEBUG_MEM
+       * transport.c (_stp_transport): Call stp_mem_debug_done();
+        * (*.c):  Call stp malloc and free functions.
+
 2007-11-09  Masami Hiramatsu  <mhiramat@redhat.com>
 
        PR3858
index 7846572a41f464e321ba9652af5769b6f62f0707..3cfeca1ee6fafca3eb6cc8d8d054999ed89d001d 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- linux-c -*-
  *
  * debugfs control channel
- * Copyright (C) 2007 Red Hat Inc.
+ * Copyright (C) 2007, 2008 Red Hat Inc.
  *
  * This file is part of systemtap, and is free software.  You can
  * redistribute it and/or modify it under the terms of the GNU General
@@ -422,7 +422,7 @@ static int _stp_register_ctl_channel (void)
 
        /* allocate buffers */
        for (i = 0; i < STP_DEFAULT_BUFFERS; i++) {
-               p = (struct list_head *)kmalloc(sizeof(struct _stp_buffer),STP_ALLOC_FLAGS);
+               p = (struct list_head *)_stp_kmalloc(sizeof(struct _stp_buffer));
                // printk("allocated buffer at %lx\n", (long)p);
                if (!p)
                        goto err0;
@@ -448,7 +448,7 @@ err0:
 
        list_for_each_safe(p, tmp, &_stp_pool_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
        errk ("Error creating systemtap debugfs entries.\n");
        return -1;
@@ -464,15 +464,15 @@ static void _stp_unregister_ctl_channel (void)
        /* free memory pools */
        list_for_each_safe(p, tmp, &_stp_pool_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
        list_for_each_safe(p, tmp, &_stp_sym_ready_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
        list_for_each_safe(p, tmp, &_stp_ctl_ready_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
 }
 
index 069e379ee93b80290dff743770505e7900bdf2c0..5d40cae482fa7ff3152f988fe356da47295f1663 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- linux-c -*-
  *
  * /proc transport and control
- * Copyright (C) 2005-2007 Red Hat Inc.
+ * Copyright (C) 2005-2008 Red Hat Inc.
  *
  * This file is part of systemtap, and is free software.  You can
  * redistribute it and/or modify it under the terms of the GNU General
@@ -485,7 +485,7 @@ static int _stp_set_buffers(int num)
        
        if (num > _stp_current_buffers) {
                for (i = 0; i < num - _stp_current_buffers; i++) {
-                       p = (struct list_head *)kmalloc(sizeof(struct _stp_buffer),STP_ALLOC_FLAGS);
+                       p = (struct list_head *)_stp_kmalloc(sizeof(struct _stp_buffer));
                        if (!p) {
                                _stp_current_buffers += i;
                                goto err;
@@ -501,7 +501,7 @@ static int _stp_set_buffers(int num)
                        p = _stp_pool_q.next;
                        list_del(p);
                        spin_unlock_irqrestore(&_stp_pool_lock, flags);
-                       kfree(p);
+                       _stp_kfree(p);
                }
        }
        _stp_current_buffers = num;
@@ -542,7 +542,7 @@ static int _stp_register_ctl_channel (void)
 
        /* allocate buffers */
        for (i = 0; i < STP_DEFAULT_BUFFERS; i++) {
-               p = (struct list_head *)kmalloc(sizeof(struct _stp_buffer),STP_ALLOC_FLAGS);
+               p = (struct list_head *)_stp_kmalloc(sizeof(struct _stp_buffer));
                // printk("allocated buffer at %lx\n", (long)p);
                if (!p)
                        goto err0;
@@ -593,7 +593,7 @@ err2:
 err1:
 #ifdef STP_BULKMODE
        for (de = _stp_proc_root->subdir; de; de = de->next)
-               kfree (de->data);
+               _stp_kfree (de->data);
        for_each_cpu(j) {
                if (j == i)
                        break;
@@ -607,7 +607,7 @@ err1:
 err0:
        list_for_each_safe(p, tmp, &_stp_pool_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
 
        errk ("Error creating systemtap /proc entries.\n");
@@ -624,7 +624,7 @@ static void _stp_unregister_ctl_channel (void)
        struct proc_dir_entry *de;
        kbug("unregistering procfs\n");
        for (de = _stp_proc_root->subdir; de; de = de->next)
-               kfree (de->data);
+               _stp_kfree (de->data);
 
        for_each_cpu(i) {
                sprintf(buf, "%d", i);
@@ -640,15 +640,15 @@ static void _stp_unregister_ctl_channel (void)
        /* free memory pools */
        list_for_each_safe(p, tmp, &_stp_pool_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
        list_for_each_safe(p, tmp, &_stp_sym_ready_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
        list_for_each_safe(p, tmp, &_stp_ctl_ready_q) {
                list_del(p);
-               kfree(p);
+               _stp_kfree(p);
        }
 }
 
index 2c7ca7544fb1407a80b4eb4cdd5c2baa3315bbdd..375c8e590d710dbe623b58a2cd8f1d18f7ebbcd6 100644 (file)
@@ -118,7 +118,7 @@ err:
                _stp_remove_relay_dir(utt->dir);
        if (utt->utt_tree_root)
                _stp_remove_relay_root(utt->utt_tree_root);
-       kfree(utt);
+       _stp_kfree(utt);
        return NULL;
 }
 
@@ -173,7 +173,7 @@ int utt_trace_remove(struct utt_trace *utt)
                        _stp_remove_relay_dir(utt->dir);
                if (utt->utt_tree_root)
                        _stp_remove_relay_root(utt->utt_tree_root);
-               kfree(utt);
+               _stp_kfree(utt);
        }
        return 0;
 }
index 1d930183fca7b0eeba9ef826d692336f644fad3c..a3ab58072d7ee4436585455dab20a3b615b65495 100644 (file)
@@ -90,10 +90,10 @@ static struct _stp_module * _stp_alloc_module(unsigned num, unsigned datasize)
 bad:
        if (mod) {
                if (mod->allocated && mod->symbols)
-                       vfree(mod->symbols);
+                       _stp_vfree(mod->symbols);
                else
-                       kfree(mod->symbols);
-               kfree(mod); 
+                       _stp_kfree(mod->symbols);
+               _stp_kfree(mod); 
        }
        return NULL;
 }
@@ -109,19 +109,19 @@ static void _stp_free_module(struct _stp_module *mod)
        /* free symbol memory */
        if (mod->num_symbols) {
                if (mod->allocated & 1)
-                       vfree(mod->symbols);
+                       _stp_vfree(mod->symbols);
                else
-                       kfree(mod->symbols);
+                       _stp_kfree(mod->symbols);
                if (mod->allocated & 2)
-                       vfree(mod->symbol_data);
+                       _stp_vfree(mod->symbol_data);
                else
-                       kfree(mod->symbol_data);
+                       _stp_kfree(mod->symbol_data);
        }
        if (mod->sections)
-               kfree(mod->sections);
+               _stp_kfree(mod->sections);
 
        /* free module memory */
-       kfree(mod);
+       _stp_kfree(mod);
 }
 
 /* Delete a module and free its memory. */
@@ -455,7 +455,7 @@ static int _stp_do_module(const char __user *buf, int count)
                return -EFAULT;
        }
        if (copy_from_user ((char *)tmpmod.sections, buf+sizeof(tmpmod), count-sizeof(tmpmod))) {
-               kfree(tmpmod.sections);
+               _stp_kfree(tmpmod.sections);
                return -EFAULT;
        }
        for (i = 0; i < tmpmod.num_sections; i++) {
@@ -472,7 +472,7 @@ static int _stp_do_module(const char __user *buf, int count)
        /* load symbols from tmpmod.module to mod */
        mod = _stp_load_module_symbols(&tmpmod);        
        if (mod == NULL) {
-               kfree(tmpmod.sections);
+               _stp_kfree(tmpmod.sections);
                return 0;
        }
 
index 2904cf2fc8d4de8ca3483befa3e76be8b7f237ac..0b18b275c28e542ee3121628d28b58c1839748ef 100644 (file)
@@ -2,7 +2,7 @@
  * transport.c - stp transport functions
  *
  * Copyright (C) IBM Corporation, 2005
- * Copyright (C) Red Hat Inc, 2005-2007
+ * Copyright (C) Red Hat Inc, 2005-2008
  * Copyright (C) Intel Corporation, 2006
  *
  * This file is part of systemtap, and is free software.  You can
@@ -215,6 +215,7 @@ void _stp_transport_close()
        _stp_free_modules();
        _stp_kill_time();
        _stp_print_cleanup();   /* free print buffers */
+       _stp_mem_debug_done();
        kbug("---- CLOSED ----\n");
 }
 
index ac2e15133eaa4df7eda42f774e9345f29d8502d2..182c11788611507594fa5943566127aaaadc95ab 100644 (file)
@@ -88,7 +88,7 @@ void utt_trace_cleanup(struct utt_trace *utt)
        if (utt->dropped_file)
                debugfs_remove(utt->dropped_file);
        utt_remove_tree(utt);
-       kfree(utt);
+       _stp_kfree(utt);
 }
 
 int utt_trace_remove(struct utt_trace *utt)
@@ -207,7 +207,7 @@ struct utt_trace *utt_trace_setup(struct utt_trace_setup *utts)
                goto err;
 
        ret = -ENOMEM;
-       utt = kzalloc(sizeof(*utt), GFP_KERNEL);
+       utt = _stp_kzalloc(sizeof(*utt));
        if (!utt)
                goto err;
 
@@ -251,7 +251,7 @@ err:
                        debugfs_remove(utt->dropped_file);
                if (utt->rchan)
                        relay_close(utt->rchan);
-               kfree(utt);
+               _stp_kfree(utt);
        }
        if (dir)
                utt_remove_tree(utt);
This page took 0.066831 seconds and 5 git commands to generate.