]> sourceware.org Git - systemtap.git/commitdiff
semantic_pass_conditions(): collect affected probes
authorJonathan Lebon <jlebon@redhat.com>
Mon, 2 Jun 2014 14:49:04 +0000 (10:49 -0400)
committerJonathan Lebon <jlebon@redhat.com>
Mon, 11 Aug 2014 19:39:59 +0000 (15:39 -0400)
In anticipation for on-the-fly probe arming/disarming, we change
semantic_pass_conditions() to not only inline the probe condition into
its body, but also to collect, for each probe, the set of probes whose
conditions may change after the probe's handler is run. That set is
stored in the new derived_probe::probes_with_affected_conditions.

These sets will be used by the translator to emit code that will check
whether affected probes should be armed/disarmed after a handler is run.

We also introduce the STP_ON_THE_FLY define which will gate all
on-the-fly related code and will be emitted only if required. Finally,
we have STP_ON_THE_FLY_DISABLED which can be used to disable all
on-the-fly arming/disarming.

elaborate.cxx
elaborate.h
translate.cxx

index 4dc8b26a07ea1cd59cafbdef1493566ee09c6f0a..29d160d58583e3ba12af72a9e3e8143ef44d5b0f 100644 (file)
@@ -1384,53 +1384,121 @@ semantic_pass_vars (systemtap_session & sess)
 //
 // becomes:
 //
-// probe begin(MAX) { if (! (g1 || g2)) %{ disable_probe_foo %} }
 // probe foo { if (! (g1 || g2)) next; ... }
 // probe bar { ... g1 ++ ...;
 //             if (g1 || g2) %{ enable_probe_foo %} else %{ disable_probe_foo %}
 //           }
 //
-// XXX: As a first cut, do only the "inline probe condition" part of the
-// transform.
+// In other words, we perform two transformations:
+//    (1) Inline probe condition into its body.
+//    (2) For each probe that modifies a global var in use in any probe's
+//        condition, re-evaluate those probes' condition at the end of that
+//        probe's body.
+//
+// Here, we do all of (1), and half of (2): we simply collect the dependency
+// info between probes, which the translator will use to emit the affected
+// probes' condition re-evaluation. The translator will also ensure that the
+// conditions are evaluated using the globals' starting values prior to any
+// probes starting.
+
+// Adds the condition expression to the front of the probe's body
+static void
+derived_probe_condition_inline (derived_probe *p)
+{
+  expression* e = p->sole_location()->condition;
+  assert(e);
+
+  if_statement *ifs = new if_statement ();
+  ifs->tok = e->tok;
+  ifs->thenblock = new next_statement ();
+  ifs->thenblock->tok = e->tok;
+  ifs->elseblock = NULL;
+  unary_expression *notex = new unary_expression ();
+  notex->op = "!";
+  notex->tok = e->tok;
+  notex->operand = e;
+  ifs->condition = notex;
+  p->body = new block (ifs, p->body);
+}
 
 static int
 semantic_pass_conditions (systemtap_session & sess)
 {
+  map<derived_probe*, set<vardecl*> > vars_read_in_cond;
+  map<derived_probe*, set<vardecl*> > vars_written_in_body;
+
+  // do a first pass through the probes to ensure safety, inline any condition,
+  // and collect var usage
   for (unsigned i = 0; i < sess.probes.size(); ++i)
     {
       derived_probe* p = sess.probes[i];
       expression* e = p->sole_location()->condition;
+
       if (e)
         {
-          varuse_collecting_visitor vut(sess);
-          e->visit (& vut);
+          varuse_collecting_visitor vcv_cond(sess);
+          e->visit (& vcv_cond);
+
+          if (!vcv_cond.written.empty())
+            sess.print_error (SEMANTIC_ERROR (_("probe condition must not "
+                                                "modify any variables"),
+                                              e->tok));
+          else if (vcv_cond.embedded_seen)
+            sess.print_error (SEMANTIC_ERROR (_("probe condition must not "
+                                                "include impure embedded-C"),
+                                              e->tok));
+
+          derived_probe_condition_inline(p);
+
+          vars_read_in_cond[p].insert(vcv_cond.read.begin(),
+                                      vcv_cond.read.end());
+        }
 
-          if (! vut.written.empty())
-            {
-              string err = (_("probe condition must not modify any variables"));
-              sess.print_error (SEMANTIC_ERROR (err, e->tok));
-            }
-          else if (vut.embedded_seen)
+      varuse_collecting_visitor vcv_body(sess);
+      p->body->visit (& vcv_body);
+
+      vars_written_in_body[p].insert(vcv_body.written.begin(),
+                                     vcv_body.written.end());
+    }
+
+  // do a second pass to collect affected probes
+  bool need_on_the_fly = false;
+  for (unsigned i = 0; i < sess.probes.size(); ++i)
+    {
+      derived_probe *p = sess.probes[i];
+
+      // for each variable this probe modifies...
+      set<vardecl*>::const_iterator var;
+      for (var  = vars_written_in_body[p].begin();
+           var != vars_written_in_body[p].end(); ++var)
+        {
+          // collect probes which could be affected
+          for (unsigned j = 0; j < sess.probes.size(); ++j)
             {
-              sess.print_error (SEMANTIC_ERROR (_("probe condition must not include impure embedded-C"), e->tok));
+              if (vars_read_in_cond[sess.probes[j]].count(*var))
+                {
+                  if (!p->probes_with_affected_conditions.count(sess.probes[j]))
+                    {
+                      p->probes_with_affected_conditions.insert(sess.probes[j]);
+                      if (sess.verbose > 2)
+                        clog << "probe " << i << " can affect condition of "
+                                "probe " << j << endl;
+                    }
+                  need_on_the_fly = true;
+                }
             }
-
-          // Add the condition expression to the front of the
-          // derived_probe body.
-          if_statement *ifs = new if_statement ();
-          ifs->tok = e->tok;
-          ifs->thenblock = new next_statement ();
-          ifs->thenblock->tok = e->tok;
-          ifs->elseblock = NULL;
-          unary_expression *notex = new unary_expression ();
-          notex->op = "!";
-          notex->tok = e->tok;
-          notex->operand = e;
-          ifs->condition = notex;
-          p->body = new block (ifs, p->body);
         }
     }
 
+  // Emit STP_ON_THE_FLY macro if needed.
+  if (need_on_the_fly && !sess.runtime_usermode_p())
+    sess.c_macros.push_back("STP_ON_THE_FLY");
+
+  // As an extra precaution, explicitly disable STP_ON_THE_FLY if in usermode in
+  // case user provided -D STP_ON_THE_FLY.
+  else if (sess.runtime_usermode_p())
+    sess.c_macros.push_back("STP_ON_THE_FLY_DISABLED");
+
   return sess.num_errors();
 }
 
index 6c50cceb89e09b479166a0710216f44435414e01..91102baedfded83ff69c14877d12db0dc2d0ba94 100644 (file)
@@ -228,6 +228,10 @@ public:
 
   // index into session.probes[], set and used during translation
   unsigned session_index;
+
+  // List of other derived probes whose conditions may be affected by
+  // this probe.
+  std::set<derived_probe*> probes_with_affected_conditions;
 };
 
 // ------------------------------------------------------------------------
index da3935130077bcf482b773d1dd4512d13c970ff8..be4f48b542ca989d8c44a8b12368a7da7a5a9d2c 100644 (file)
@@ -6947,6 +6947,10 @@ translate_pass (systemtap_session& s)
       // Emit the total number of probes (not regarding merged probe handlers)
       s.op->newline() << "#define STP_PROBE_COUNT " << s.probes.size();
 
+      s.op->newline() << "#ifdef STP_ON_THE_FLY_DISABLED";
+      s.op->newline() << "#undef STP_ON_THE_FLY";
+      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.043471 seconds and 5 git commands to generate.