/usr/share/systemtap/runtime
NameSizeModeActions
dyninst/-0755rm
linux/-0755rm
softfloat/-0755rm
transport/-0755rm
unwind/-0755rm
addr-map.c5230644editdlrm
addr-map.h11560644editdlrm
alloc.c4980644editdlrm
arith.c4830644editdlrm
common_probe_context.h65760644editdlrm
common_session_state.h4150644editdlrm
compatdefs.h36820644editdlrm
copy.c5850644editdlrm
debug.h4850644editdlrm
io.c5080644editdlrm
k_syms.h1820644editdlrm
loc2c-runtime.h179370644editdlrm
map-gen.c259770644editdlrm
map-stat.c35890644editdlrm
map.c146600644editdlrm
map.h59180644editdlrm
mempool.c26440644editdlrm
namespaces.h4870644editdlrm
pmap-gen.c87100644editdlrm
print.c4860644editdlrm
print.h8720644editdlrm
print_flush.c30730644editdlrm
probe_lock.h4980644editdlrm
procfs-probes.c46730644editdlrm
procfs-probes.h6740644editdlrm
procfs.c40210644editdlrm
proc_fs_compatibility.h23160644editdlrm
ptrace_compatibility.h15120644editdlrm
regs.c42800644editdlrm
regs.h23520644editdlrm
runtime.h9280644editdlrm
runtime_context.h6690644editdlrm
runtime_defines.h35820644editdlrm
softfloat.c771590644editdlrm
softfloat.h51250644editdlrm
stack-arm.c16880644editdlrm
stack-ia64.c10830644editdlrm
stack-mips.c1250644editdlrm
stack-s390.c23620644editdlrm
stack.c217900644editdlrm
stat-common.c84860644editdlrm
stat.c74210644editdlrm
stat.h19640644editdlrm
stp_helper_lock.h36690644editdlrm
stp_string.c86320644editdlrm
stp_string.h5980644editdlrm
stp_task_work.c35110644editdlrm
stp_utrace.c947350644editdlrm
stp_utrace.h140100644editdlrm
sym.c397570644editdlrm
sym.h65390644editdlrm
syscall.h174080644editdlrm
task_finder_vma.c132900644editdlrm
time.c148870644editdlrm
timer.c4810644editdlrm
timer.h4820644editdlrm
uidgid_compatibility.h6030644editdlrm
unwind.c478900644editdlrm
utrace_compatibility.h31480644editdlrm
vma.c95450644editdlrm
vsprintf.c240580644editdlrm
vsprintf.h15020644editdlrm
Edit: /usr/share/systemtap/runtime/stp_task_work.c (3511B)
#ifndef _STP_TASK_WORK_C #define _STP_TASK_WORK_C #include "linux/task_work_compatibility.h" #if !defined(STAPCONF_TASK_WORK_ADD_EXPORTED) // First typedef from the original decls, then #define as typecasted calls. typedef typeof(&task_work_add) task_work_add_fn; #define task_work_add (* (task_work_add_fn)kallsyms_task_work_add) #endif #if !defined(STAPCONF_TASK_WORK_CANCEL_EXPORTED) typedef typeof(&task_work_cancel) task_work_cancel_fn; #define task_work_cancel (* (task_work_cancel_fn)kallsyms_task_work_cancel) #endif /* To avoid a crash when a task_work callback gets called after the * module is unloaded, keep track of the number of current callbacks. */ static atomic_t stp_task_work_callbacks = ATOMIC_INIT(0); static DECLARE_WAIT_QUEUE_HEAD(stp_task_work_waitq); /* * stp_task_work_init() should be called before any other * stp_task_work_* functions are called to do setup. */ static int stp_task_work_init(void) { #if !defined(STAPCONF_TASK_WORK_ADD_EXPORTED) /* The task_work_add()/task_work_cancel() functions aren't * exported. Look up those function addresses. */ kallsyms_task_work_add = (void *)kallsyms_lookup_name("task_work_add"); if (kallsyms_task_work_add == NULL) { _stp_error("Can't resolve task_work_add!"); return -ENOENT; } #endif #if !defined(STAPCONF_TASK_WORK_CANCEL_EXPORTED) kallsyms_task_work_cancel = (void *)kallsyms_lookup_name("task_work_cancel"); if (kallsyms_task_work_cancel == NULL) { _stp_error("Can't resolve task_work_cancel!"); return -ENOENT; } #endif return 0; } /* * stap_task_work_exit() should be called when no more * stp_task_work_* functions will be called (before module exit). * * This function makes sure that all the callbacks are finished before * letting the module unload. If the module unloads before a callback * is called, the kernel will try to make a function call to an * invalid address. */ static void stp_task_work_exit(void) { wait_event(stp_task_work_waitq, !atomic_read(&stp_task_work_callbacks)); } static void stp_task_work_get(void) { /* * We use atomic_inc_return() here instead of atomic_inc() because * atomic_inc_return() implies a full memory barrier and we need the * updates to stp_task_work_callbacks to be ordered correctly, otherwise * there could still be a task worker active after stp_task_work_exit() * returns (assuming that no task workers are added *after* * stp_task_work_exit() returns). */ atomic_inc_return(&stp_task_work_callbacks); } static void stp_task_work_put(void) { if (atomic_dec_and_test(&stp_task_work_callbacks)) wake_up(&stp_task_work_waitq); } /* * Our task_work_add() wrapper that remembers that we've got a pending * callback. */ static int stp_task_work_add(struct task_struct *task, struct task_work *twork) { int rc; rc = task_work_add(task, twork, true); if (rc == 0) stp_task_work_get(); return rc; } /* * Our task_work_cancel() wrapper that remembers that a callback has * been cancelled. */ static struct task_work * stp_task_work_cancel(struct task_struct *task, task_work_func_t func) { struct task_work *twork; twork = task_work_cancel(task, func); if (twork != NULL) stp_task_work_put(); return twork; } /* * stp_task_work_func_done() should be called at the very end of a * task_work callback function so that we can keep up with callback * accounting. */ static void stp_task_work_func_done(void) { stp_task_work_put(); } #endif /* _STP_TASK_WORK_C */