]> sourceware.org Git - systemtap.git/commitdiff
runtime: lock module_refresh with mutex
authorJonathan Lebon <jlebon@redhat.com>
Fri, 6 Jun 2014 17:52:39 +0000 (13:52 -0400)
committerJonathan Lebon <jlebon@redhat.com>
Mon, 11 Aug 2014 19:40:00 +0000 (15:40 -0400)
If STP_ON_THE_FLY is enabled, then we need to ensure that
systemtap_module_refresh() is never run concurrently. Since we use a
workqueue, no concurrency can occur from arm/disarm refreshes alone.
However, the module notifier could fire at any time.

translate.cxx

index b25526d6a1e548f9bcb5c14cf0dddf6d3b275ed6..01a0b0ff802a21bbe1bb2041b4fce62b4b628c03 100644 (file)
@@ -1935,16 +1935,29 @@ void
 c_unparser::emit_module_refresh ()
 {
   o->newline() << "static void systemtap_module_refresh (void) {";
-  o->newline(1) << "int i=0, j=0;"; // for derived_probe_group use
+  o->newline(1) << "int state;";
+  o->newline() << "int i=0, j=0;"; // for derived_probe_group use
+
+  // Ensure we're only doing the refreshing one at a time. NB: it's important
+  // that we get the lock prior to checking the session_state, in case whoever
+  // is holding the lock (e.g. systemtap_module_exit()) changes it.
+  o->newline() << "#ifdef STP_ON_THE_FLY";
+  o->newline() << "mutex_lock(&module_refresh_mutex);";
+  o->newline() << "#endif";
 
   /* If we're not in STARTING/RUNNING state, don't try doing any work.
      PR16766 */
-  o->newline() << "int state = atomic_read (session_state());";
+  o->newline() << "state = atomic_read (session_state());";
   o->newline() << "if (state != STAP_SESSION_RUNNING && state != STAP_SESSION_STARTING && state != STAP_SESSION_ERROR) {";
   // cannot _stp_warn etc. since we're not in probe context
   o->newline(1) << "#if defined(__KERNEL__)";
   o->newline() << "printk (KERN_ERR \"stap module notifier triggered in unexpected state %d\\n\", state);";
   o->newline() << "#endif";
+
+  o->newline() << "#ifdef STP_ON_THE_FLY";
+  o->newline() << "mutex_unlock(&module_refresh_mutex);";
+  o->newline() << "#endif";
+
   o->newline() << "return;";
   o->newline(-1) << "}";
 
@@ -1956,6 +1969,11 @@ c_unparser::emit_module_refresh ()
     {
       g[i]->emit_module_refresh (*session);
     }
+
+  o->newline() << "#ifdef STP_ON_THE_FLY";
+  o->newline() << "mutex_unlock(&module_refresh_mutex);";
+  o->newline() << "#endif";
+
   o->newline(-1) << "}\n";
 }
 
@@ -1983,6 +2001,10 @@ c_unparser::emit_module_exit ()
   // while to abort right away.  Currently running probes are allowed to
   // terminate.  These may set STAP_SESSION_ERROR!
 
+  // Get the lock before exiting to ensure there's no one in module_refresh
+  o->newline() << "#ifdef STP_ON_THE_FLY";
+  o->newline() << "mutex_lock(&module_refresh_mutex);";
+  o->newline() << "#endif";
 
   // We're processing the derived_probe_group list in reverse
   // order.  This ensures that probes get unregistered in reverse
@@ -1992,6 +2014,10 @@ c_unparser::emit_module_exit ()
        i != g.rend(); i++)
     (*i)->emit_module_exit (*session); // NB: runs "end" probes
 
+  o->newline() << "#ifdef STP_ON_THE_FLY";
+  o->newline() << "mutex_unlock(&module_refresh_mutex);";
+  o->newline() << "#endif";
+
   // But some other probes may have launched too during unregistration.
   // Let's wait a while to make sure they're all done, done, done.
 
@@ -7042,6 +7068,15 @@ translate_pass (systemtap_session& s)
       // Emit systemtap_module_refresh() prototype so we can reference it
       s.op->newline() << "static void systemtap_module_refresh (void);";
 
+      // When on-the-fly [dis]arming is used, module_refresh can be called from
+      // both the module notifier, as well as when probes need to be
+      // armed/disarmed. We need to protect it to ensure it's only run one at a
+      // time.
+      s.op->newline() << "#ifdef STP_ON_THE_FLY";
+      s.op->newline() << "#include <linux/mutex.h>";
+      s.op->newline() << "static DEFINE_MUTEX(module_refresh_mutex);";
+      s.op->newline() << "#endif";
+
       s.op->newline() << "#include \"runtime.h\"";
 
       // Emit embeds ahead of time, in case they affect context layout
This page took 0.038444 seconds and 5 git commands to generate.