/usr/share/systemtap/runtime/linux
NameSizeModeActions
uprobes/-0755rm
uprobes2/-0755rm
access_process_vm.h43110644editdlrm
addr-map.c97490644editdlrm
alloc.c159000644editdlrm
arith.c167990644editdlrm
autoconf-514-panic.c680644editdlrm
autoconf-access_ok_2args.c900644editdlrm
autoconf-alloc-percpu-align.c1180644editdlrm
autoconf-asm-syscall.c510644editdlrm
autoconf-atomic_fetch_add_unless.c940644editdlrm
autoconf-bio-bi_opf.c8240644editdlrm
autoconf-blk-types.c3590644editdlrm
autoconf-compat-utimbuf.c530644editdlrm
autoconf-compat_sigaction.c4480644editdlrm
autoconf-constant-tsc.c630644editdlrm
autoconf-cpu-clock.c12770644editdlrm
autoconf-dpath-path.c1210644editdlrm
autoconf-files_lookup_fd_raw.c1360644editdlrm
autoconf-from_kuid_munged.c1910644editdlrm
autoconf-fs_supers-hlist.c3540644editdlrm
autoconf-generated-compile.c560644editdlrm
autoconf-genhd.c2010644editdlrm
autoconf-get-kretprobe.c1070644editdlrm
autoconf-get_user_pages-flags.c15490644editdlrm
autoconf-get_user_pages-notask_struct.c13010644editdlrm
autoconf-get_user_pages_remote-flags.c15500644editdlrm
autoconf-get_user_pages_remote-flags_locked.c13310644editdlrm
autoconf-get_user_pages_remote-notask_struct.c14380644editdlrm
autoconf-grsecurity.c2190644editdlrm
autoconf-hlist-4args.c2960644editdlrm
autoconf-hlist_add_tail_rcu.c1120644editdlrm
autoconf-hrtimer-getset-expires.c1260644editdlrm
autoconf-hrtimer-rel.c870644editdlrm
autoconf-hw_breakpoint_context.c3150644editdlrm
autoconf-inode-private.c1730644editdlrm
autoconf-inode-rwsem.c1720644editdlrm
autoconf-inode-uretprobes.c2640644editdlrm
autoconf-kernel_read-new-args.c10300644editdlrm
autoconf-kprobe-symbol-name.c900644editdlrm
autoconf-ktime-get-real.c980644editdlrm
autoconf-linux-sched_headers.c16780644editdlrm
autoconf-local-clock.c12820644editdlrm
autoconf-lockdown-debugfs.c1020644editdlrm
autoconf-lockdown-kernel.c900644editdlrm
autoconf-mm-context-vdso-base.c1170644editdlrm
autoconf-mm-context-vdso.c1140644editdlrm
autoconf-mm-shmempages.c720644editdlrm
autoconf-mmap_lock.c1750644editdlrm
autoconf-module-sect-attrs.c1580644editdlrm
autoconf-module_layout.c520644editdlrm
autoconf-mod_kallsyms.c510644editdlrm
autoconf-nameidata.c960644editdlrm
autoconf-netfilter-4_1.c7690644editdlrm
autoconf-netfilter-4_4.c14600644editdlrm
autoconf-netfilter-313b.c6020644editdlrm
autoconf-netfilter.c4220644editdlrm
autoconf-old-inode-uprobes.c3570644editdlrm
autoconf-oneachcpu-retry.c9570644editdlrm
autoconf-pagefault_disable.c1370644editdlrm
autoconf-pde_data.c2260644editdlrm
autoconf-perf-structpid.c4440644editdlrm
autoconf-procfs-owner.c1580644editdlrm
autoconf-proc_ops.c5660644editdlrm
autoconf-rcu_is_watching.c3850644editdlrm
autoconf-real-parent.c4270644editdlrm
autoconf-regset.c2390644editdlrm
autoconf-relay-umode_t.c7300644editdlrm
autoconf-relay_buf-per_cpu_ptr.c9200644editdlrm
autoconf-ring_buffer-flags.c1120644editdlrm
autoconf-ring_buffer_lost_events.c2960644editdlrm
autoconf-ring_buffer_read_prepare.c1810644editdlrm
autoconf-save-stack-trace-no-bp.c4980644editdlrm
autoconf-save-stack-trace.c5010644editdlrm
autoconf-set_fs.c2210644editdlrm
autoconf-smpcall-4args.c1660644editdlrm
autoconf-smpcall-5args.c1690644editdlrm
autoconf-stack-trace-save-regs.c1760644editdlrm
autoconf-stacktrace_ops-int-address.c4090644editdlrm
autoconf-stacktrace_ops-warning.c1880644editdlrm
autoconf-syscall_get_args_3args.c2390644editdlrm
autoconf-task-state.c5500644editdlrm
autoconf-task-uid.c1520644editdlrm
autoconf-task_work-struct.c2190644editdlrm
autoconf-time32-old.c520644editdlrm
autoconf-time32.c530644editdlrm
autoconf-timerfd.c2320644editdlrm
autoconf-trace-printk.c1510644editdlrm
autoconf-tracepoint-has-data.c4930644editdlrm
autoconf-tracepoint-strings.c2330644editdlrm
autoconf-uaccess.c280644editdlrm
autoconf-uapi-mount.c520644editdlrm
autoconf-udelay_simple.c900644editdlrm
autoconf-uidgid.c500644editdlrm
autoconf-unwind-stack-trace.c3260644editdlrm
autoconf-uprobe-get-pc.c3740644editdlrm
autoconf-utrace-regset.c2730644editdlrm
autoconf-utrace-via-tracepoints.c17120644editdlrm
autoconf-vm-area-pte.c1410644editdlrm
autoconf-walk-stack.c2170644editdlrm
autoconf-x86-fs.c900644editdlrm
autoconf-x86-gs.c900644editdlrm
autoconf-x86-uniregs.c1400644editdlrm
autoconf-x86-xfs.c910644editdlrm
common_session_state.h32490644editdlrm
compat_net.h8580644editdlrm
compat_structs.h44090644editdlrm
compat_unistd.h683840644editdlrm
copy.c27170644editdlrm
debug.h29780644editdlrm
io.c52910644editdlrm
itrace.c148740644editdlrm
kprobes.c251260644editdlrm
loc2c-runtime.h298740644editdlrm
map_list.h12200644editdlrm
map_runtime.h52660644editdlrm
namespaces.h71280644editdlrm
netfilter.c14100644editdlrm
perf.c75960644editdlrm
perf.h12720644editdlrm
perf_event_counter_context.c3360644editdlrm
perf_probe_handler_nmi.c2780644editdlrm
perf_read.h9590644editdlrm
print.c114020644editdlrm
probe_lock.h18070644editdlrm
regs-ia64.c37410644editdlrm
regs.c134900644editdlrm
runtime.h125910644editdlrm
runtime_context.h60890644editdlrm
runtime_defines.h10410644editdlrm
stap_mmap_lock.h3430644editdlrm
stat_runtime.h17740644editdlrm
stp_tls.h11810644editdlrm
stp_tracepoint.c114810644editdlrm
stp_tracepoint.h22700644editdlrm
syscalls-common.h9760644editdlrm
task_finder.c538600644editdlrm
task_finder2.c576400644editdlrm
task_finder_map.c51940644editdlrm
task_finder_stubs.c24420644editdlrm
task_work_compatibility.h12830644editdlrm
timer.c22000644editdlrm
timer.h13830644editdlrm
timer_compatibility.h23170644editdlrm
uprobes-common.c155730644editdlrm
uprobes-common.h16530644editdlrm
uprobes-inc.h4840644editdlrm
uprobes-inode.c340860644editdlrm
Edit: /usr/share/systemtap/runtime/linux/alloc.c (15900B)
/* -*- linux-c -*- * Memory allocation functions * Copyright (C) 2005-2018 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 * Public License (GPL); either version 2, or (at your option) any * later version. */ #ifndef _STAPLINUX_ALLOC_C_ #define _STAPLINUX_ALLOC_C_ #include #include "stp_helper_lock.h" static long _stp_allocated_net_memory = 0; /* Default, and should be "safe" from anywhere. */ #define STP_ALLOC_FLAGS ((GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN) \ & ~__GFP_WAIT) /* May only be used in context that can sleep. __GFP_NORETRY is to suppress the oom-killer from kicking in. */ #define STP_ALLOC_SLEEP_FLAGS (GFP_KERNEL | __GFP_NORETRY) /* #define DEBUG_MEMALLOC_MIGHT_SLEEP */ /* * If DEBUG_MEMALLOC_MIGHT_SLEEP is defined (stap -DDEBUG_MEMALLOC_MIGHT_SLEEP ...) * then all memory allocation operations are assumed to sleep. This * can be used to check whether any memory allocations occur in atomic * context, which is discouraged on realtime kernels. */ /* #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. */ static long _stp_allocated_memory = 0; #ifdef DEBUG_MEM static STP_DEFINE_SPINLOCK(_stp_mem_lock); #define MEM_MAGIC 0xc11cf77f #define MEM_FENCE_SIZE 32 enum _stp_memtype { MEM_KMALLOC, MEM_VMALLOC, MEM_PERCPU }; typedef struct { char *alloc; char *free; } _stp_malloc_type; static const _stp_malloc_type _stp_malloc_types[] = { {"kmalloc", "kfree"}, {"vmalloc", "vfree"}, {"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); static 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++; } } static void *_stp_mem_debug_setup(void *addr, size_t size, enum _stp_memtype type) { struct list_head *p; struct _stp_mem_entry *m; unsigned long flags; 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; stp_spin_lock_irqsave(&_stp_mem_lock, flags); list_add(p, &_stp_mem_list); stp_spin_unlock_irqrestore(&_stp_mem_lock, flags); return addr; } /* Percpu allocations don't have the fence. Implementing it is problematic. */ static void _stp_mem_debug_percpu(struct _stp_mem_entry *m, void *addr, size_t size) { struct list_head *p = (struct list_head *)m; unsigned long flags; m->magic = MEM_MAGIC; m->type = MEM_PERCPU; m->len = size; m->addr = addr; stp_spin_lock_irqsave(&_stp_mem_lock, flags); list_add(p, &_stp_mem_list); stp_spin_unlock_irqrestore(&_stp_mem_lock, flags); } static 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; unsigned long flags; if (!addr) { /* Passing NULL to these *free() functions is safe */ switch (type) { case MEM_KMALLOC: case MEM_PERCPU: case MEM_VMALLOC: return; } } stp_spin_lock_irqsave(&_stp_mem_lock, flags); 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; } } stp_spin_unlock_irqrestore(&_stp_mem_lock, flags); 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; } static void _stp_mem_debug_validate(void *addr) { int found = 0; struct list_head *p, *tmp; struct _stp_mem_entry *m = NULL; unsigned long flags; stp_spin_lock_irqsave(&_stp_mem_lock, flags); list_for_each_safe(p, tmp, &_stp_mem_list) { m = list_entry(p, struct _stp_mem_entry, list); if (m->addr == addr) { found = 1; break; } } stp_spin_unlock_irqrestore(&_stp_mem_lock, flags); if (!found) { printk("SYSTEMTAP ERROR: Couldn't validate memory %p\n", addr); return; } if (m->magic != MEM_MAGIC) { printk("SYSTEMTAP ERROR: Memory at %p corrupted!!\n", addr); return; } switch (m->type) { case MEM_KMALLOC: _stp_check_mem_fence(addr, m->len); break; case MEM_PERCPU: /* do nothing */ break; case MEM_VMALLOC: _stp_check_mem_fence(addr, m->len); break; default: printk("SYSTEMTAP ERROR: Attempted to validate memory at addr %p len=%d with unknown allocation type.\n", addr, (int)m->len); } return; } #endif /* #define STP_MAXMEMORY 8192 */ /* * If STP_MAXMEMORY is defined to a value (stap -DSTP_MAXMEMORY=8192 * ...) then every memory allocation is checked to make sure the * systemtap module doesn't use more than STP_MAXMEMORY of memory. * STP_MAXMEMORY is specified in kilobytes, so, for example, '8192' * means that the systemtap module won't use more than 8 megabytes of * memory. * * Note 1: This size does include the size of the module itself, plus * any additional allocations. * * Note 2: Since we can't be ensured that the module transport is set * up when a memory allocation problem happens, this code can't * directly report an error back to a user (so instead it uses * 'printk'). If the modules transport has been set up, the code that * calls the memory allocation functions * (_stp_kmalloc/_stp_kzalloc/etc.) should report an error directly to * the user. * * Note 3: This only tracks direct allocations by the systemtap * runtime. This does not track indirect allocations (such as done by * kprobes/uprobes/etc. internals). */ #ifdef STP_MAXMEMORY #ifdef STAPCONF_MODULE_LAYOUT #define _STP_MODULE_CORE_SIZE (THIS_MODULE->core_layout.size) #elif defined(STAPCONF_GRSECURITY) #define _STP_MODULE_CORE_SIZE (THIS_MODULE->core_size_rw) #else #define _STP_MODULE_CORE_SIZE (THIS_MODULE->core_size) #endif #endif static void *_stp_kmalloc_gfp(size_t size, gfp_t gfp_mask) { void *ret; #ifdef DEBUG_MEMALLOC_MIGHT_SLEEP might_sleep(); #endif #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef DEBUG_MEM ret = kmalloc(size + MEM_DEBUG_SIZE, gfp_mask); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); } #else ret = kmalloc(size, gfp_mask); if (likely(ret)) { _stp_allocated_memory += size; } #endif return ret; } static void *_stp_kmalloc(size_t size) { return _stp_kmalloc_gfp(size, STP_ALLOC_FLAGS); } static void *_stp_kzalloc_gfp(size_t size, gfp_t gfp_mask) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) { void *ret; #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef DEBUG_MEM ret = kmalloc(size + MEM_DEBUG_SIZE, gfp_mask); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); memset (ret, 0, size); } #else ret = kmalloc(size, gfp_mask); if (likely(ret)) { _stp_allocated_memory += size; memset (ret, 0, size); } #endif /* DEBUG_MEM */ return ret; } #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */ { void *ret; #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef DEBUG_MEM ret = kzalloc(size + MEM_DEBUG_SIZE, gfp_mask); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); } #else ret = kzalloc(size, gfp_mask); if (likely(ret)) { _stp_allocated_memory += size; } #endif return ret; } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) */ static void *_stp_kzalloc(size_t size) { return _stp_kzalloc_gfp(size, STP_ALLOC_FLAGS); } #ifndef STAPCONF_VZALLOC static void *vzalloc(unsigned long size) { void *ret = vmalloc(size); if (ret) memset(ret, 0, size); return ret; } #endif static void *_stp_vzalloc(size_t size) { void *ret; #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef DEBUG_MEM ret = vzalloc(size + MEM_DEBUG_SIZE); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_VMALLOC); } #else ret = vzalloc(size); if (likely(ret)) { _stp_allocated_memory += size; } #endif return ret; } #ifndef STAPCONF_VMALLOC_NODE static void *vmalloc_node(unsigned long size, int node __attribute__((unused))) { return vmalloc(size); } #endif #ifndef STAPCONF_VZALLOC_NODE static void *vzalloc_node(unsigned long size, int node) { void *ret = vmalloc_node(size, node); if (ret) memset(ret, 0, size); return ret; } #endif static void *_stp_vzalloc_node(size_t size, int node) { void *ret; #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef DEBUG_MEM ret = vzalloc_node(size + MEM_DEBUG_SIZE, node); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_VMALLOC); } #else ret = vzalloc_node(size, node); if (likely(ret)) { _stp_allocated_memory += size; } #endif return ret; } #ifdef PCPU_MIN_UNIT_SIZE #define _STP_MAX_PERCPU_SIZE PCPU_MIN_UNIT_SIZE #else #define _STP_MAX_PERCPU_SIZE 131072 #endif /* Note, calls __alloc_percpu which may sleep and always uses GFP_KERNEL. */ static void *_stp_alloc_percpu(size_t size) { void *ret; if (size > _STP_MAX_PERCPU_SIZE) return NULL; #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + (size * num_possible_cpus())) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef STAPCONF_ALLOC_PERCPU_ALIGN ret = __alloc_percpu(size, 8); #else ret = __alloc_percpu(size); #endif #ifdef DEBUG_MEM if (likely(ret)) { struct _stp_mem_entry *m = kmalloc(sizeof(struct _stp_mem_entry), GFP_KERNEL); if (unlikely(m == NULL)) { free_percpu(ret); return NULL; } _stp_allocated_memory += size * num_possible_cpus(); _stp_mem_debug_percpu(m, ret, size); } #else if (likely(ret)) { _stp_allocated_memory += size * num_possible_cpus(); } #endif return ret; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) #define _stp_kmalloc_node(size,node) _stp_kmalloc(size) #define _stp_kmalloc_node_gfp(size,node,gfp) _stp_kmalloc_gfp(size,gfp) #define _stp_kzalloc_node(size,node) _stp_kzalloc(size) #define _stp_kzalloc_node_gfp(size,node,gfp) _stp_kzalloc_gfp(size,gfp) #else static void *_stp_kmalloc_node_gfp(size_t size, int node, gfp_t gfp_mask) { void *ret; #ifdef DEBUG_MEMALLOC_MIGHT_SLEEP might_sleep(); #endif #ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) > (STP_MAXMEMORY * 1024)) { return NULL; } #endif #ifdef DEBUG_MEM ret = kmalloc_node(size + MEM_DEBUG_SIZE, gfp_mask, node); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); } #else ret = kmalloc_node(size, gfp_mask, node); if (likely(ret)) { _stp_allocated_memory += size; } #endif return ret; } static void *_stp_kzalloc_node_gfp(size_t size, int node, gfp_t gfp_mask) { /* This used to be simply: * return _stp_kmalloc_node_gfp(size, node, gfp_mask | __GFP_ZERO); * but rhel5-era kernels BUG out on that flag. (PR14957) * * We could make a big #if-alternation for kernels which have support * for kzalloc_node (kernel commit 979b0fea), as in _stp_kzalloc_gfp, * but IMO that's needlessly complex. * * So for now, just malloc and zero it manually. */ void *ret = _stp_kmalloc_node_gfp(size, node, gfp_mask); #ifdef DEBUG_MEMALLOC_MIGHT_SLEEP might_sleep(); #endif if (likely(ret)) { memset (ret, 0, size); } return ret; } static void *_stp_kmalloc_node(size_t size, int node) { return _stp_kmalloc_node_gfp(size, node, STP_ALLOC_FLAGS); } static void *_stp_kzalloc_node(size_t size, int node) { return _stp_kzalloc_node_gfp(size, node, STP_ALLOC_FLAGS); } #endif /* LINUX_VERSION_CODE */ static void _stp_kfree(void *addr) { #ifdef DEBUG_MEMALLOC_MIGHT_SLEEP might_sleep(); #endif #ifdef DEBUG_MEM _stp_mem_debug_free(addr, MEM_KMALLOC); #else kfree(addr); #endif } static void _stp_vfree(void *addr) { #ifdef DEBUG_MEMALLOC_MIGHT_SLEEP might_sleep(); #endif #ifdef DEBUG_MEM _stp_mem_debug_free(addr, MEM_VMALLOC); #else vfree(addr); #endif } static void _stp_free_percpu(void *addr) { #ifdef DEBUG_MEMALLOC_MIGHT_SLEEP might_sleep(); #endif #ifdef DEBUG_MEM _stp_mem_debug_free(addr, MEM_PERCPU); #else free_percpu(addr); #endif } static void _stp_mem_debug_done(void) { #ifdef DEBUG_MEM struct list_head *p, *tmp; struct _stp_mem_entry *m; unsigned long flags; stp_spin_lock_irqsave(&_stp_mem_lock, flags); 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: stp_spin_unlock_irqrestore(&_stp_mem_lock, flags); return; #endif } #endif /* _STAPLINUX_ALLOC_C_ */