common_probe_entryfn_epilogue (systemtap_session& s,
bool overload_processing)
{
+ // Check if we need to enable/disable probes based on the latest values of
+ // probes_condition_enabled[].
+
+ s.op->newline( 0) << "#ifdef STP_ON_THE_FLY";
+ s.op->newline( 0) << "if (need_module_refresh) {";
+ s.op->newline(+1) << "need_module_refresh = 0;";
+ s.op->newline( 0) << "schedule_work(&module_refresher_work);";
+ s.op->newline(-1) << "}";
+ s.op->newline( 0) << "#endif";
+
if (overload_processing && !s.runtime_usermode_p())
s.op->newline() << "#if defined(STP_TIMING) || defined(STP_OVERLOAD)";
else
emit_compiled_printfs();
- // Updated in probe handlers to signal that a module refresh is needed.
o->newline( 0) << "#ifdef STP_ON_THE_FLY";
+
+ // Updated in probe handlers to signal that a module refresh is needed.
+ // Checked and cleared by common epilogue after scheduling refresh work.
o->newline( 0) << "static unsigned need_module_refresh = 0;";
+
+ // We will use a workqueue to schedule module_refresh work when we need
+ // to enable/disable probes.
+ o->newline( 0) << "#include <linux/workqueue.h>";
+ o->newline( 0) << "static struct work_struct module_refresher_work;";
+ o->newline( 0) << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)";
+ o->newline( 0) << "static void module_refresher(void *data) {";
+ o->newline( 0) << "#else";
+ o->newline( 0) << "static void module_refresher(struct work_struct *work) {";
o->newline( 0) << "#endif";
+ o->newline( 1) << "systemtap_module_refresh();";
+ o->newline(-1) << "}";
+
+ o->newline( 0) << "#endif"; // STP_ON_THE_FLY
+
+ o->newline();
}
o->newline() << "#ifdef STP_ON_THE_FLY";
+ // Initialize workqueue needed for on-the-fly arming/disarming
+ o->newline() << "#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)";
+ o->newline() << "INIT_WORK(&module_refresher_work, module_refresher, NULL);";
+ o->newline() << "#else";
+ o->newline() << "INIT_WORK(&module_refresher_work, module_refresher);";
+ o->newline() << "#endif";
+
// Initialize probe conditions
for (unsigned i=0; i<session->probes.size(); i++)
emit_probe_condition_initialize(session->probes[i]);
// while to abort right away. Currently running probes are allowed to
// terminate. These may set STAP_SESSION_ERROR!
+
// We're processing the derived_probe_group list in reverse
// order. This ensures that probes get unregistered in reverse
// order of the way they were registered.
s.op->newline() << "#undef STP_ON_THE_FLY";
s.op->newline() << "#endif";
+ // Emit systemtap_module_refresh() prototype so we can reference it
+ s.op->newline() << "static void systemtap_module_refresh (void);";
+
s.op->newline() << "#include \"runtime.h\"";
// Emit embeds ahead of time, in case they affect context layout