diff options
author | fche <fche> | 2005-07-20 22:17:29 +0000 |
---|---|---|
committer | fche <fche> | 2005-07-20 22:17:29 +0000 |
commit | bfb3d2d24be81e7506c754350612f2743ac280f7 (patch) | |
tree | fd14f19c9ece85d931659ea9b432e40602ec8991 /tapsets.cxx | |
parent | e9e09d08194e98a84f1e00ec9fcfaefa478abe47 (diff) | |
download | systemtap-steved-bfb3d2d24be81e7506c754350612f2743ac280f7.tar.gz systemtap-steved-bfb3d2d24be81e7506c754350612f2743ac280f7.tar.xz systemtap-steved-bfb3d2d24be81e7506c754350612f2743ac280f7.zip |
2005-07-20 Frank Ch. Eigler <fche@redhat.com>
* tapsets.cxx (*::emit_[de]registrations): Add logic for probe
lifecycle control (session_state).
* translate.cxx (emit_common_header,emit_module_{init,exit}): Ditto.
(visit_*): Use per-context errorcount.
Diffstat (limited to 'tapsets.cxx')
-rw-r--r-- | tapsets.cxx | 84 |
1 files changed, 64 insertions, 20 deletions
diff --git a/tapsets.cxx b/tapsets.cxx index 97c538ee..6eff619f 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -70,26 +70,16 @@ be_derived_probe::emit_registrations (translator_output* o, unsigned j) { if (begin) for (unsigned i=0; i<locations.size(); i++) - { - o->newline() << "enter_" << j << "_" << i << " ();"; - o->newline() << "rc = errorcount;"; - } - else - o->newline() << "rc = 0;"; + o->newline() << "enter_" << j << "_" << i << " ();"; } void be_derived_probe::emit_deregistrations (translator_output* o, unsigned j) { - if (begin) - o->newline() << "rc = 0;"; - else + if (!begin) for (unsigned i=0; i<locations.size(); i++) - { - o->newline() << "enter_" << j << "_" << i << " ();"; - o->newline() << "rc = errorcount;"; - } + o->newline() << "enter_" << j << "_" << i << " ();"; } @@ -102,15 +92,45 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j) o->newline() << "/* location " << i << ": " << *l << " */"; o->newline() << "static void enter_" << j << "_" << i << " (void);"; o->newline() << "void enter_" << j << "_" << i << " () {"; - o->newline(1) << "struct context* c = & contexts [0];"; - // XXX: assert #0 is free; need locked search instead - o->newline() << "if (c->busy) { errorcount ++; return; }"; + + // While begin/end probes are executed single-threaded, we + // still code defensively and use a per-cpu context. + o->newline(1) << "struct context* c = & contexts [smp_processor_id()];"; + + // A precondition for running a probe handler is that we're in STARTING + // or STOPPING state (not ERROR), and that no one else is already using + // this context. + o->newline() << "if (atomic_read (&session_state) != "; + if (begin) o->line() << "STAP_SESSION_STARTING)"; + else o->line() << "STAP_SESSION_STOPPING)"; + o->newline(1) << "return;"; + o->newline(-1) << "if (c->busy) {"; + o->newline(1) << "printk (KERN_ERR \"probe reentrancy\");"; + o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; + o->newline() << "return;"; + o->newline(-1) << "}"; + o->newline(); + o->newline() << "c->busy ++;"; + o->newline() << "mb ();"; // for smp + o->newline() << "c->errorcount = 0;"; o->newline() << "c->actioncount = 0;"; o->newline() << "c->nesting = 0;"; + // NB: locals are initialized by probe function itself o->newline() << "probe_" << j << " (c);"; + + // see translate.cxx: visit_functioncall and elsewhere to see all the + // possible context indications that a probe exited prematurely + o->newline() << "if (c->errorcount || c->actioncount > MAXACTION"; + o->newline(1) << "|| c->nesting+2 >= MAXNESTING) {"; + o->newline() << "printk (KERN_ERR \"probe execution failure (e%d,n%d,a%d)\","; + o->newline(1) << "c->errorcount, c->nesting, c->actioncount);"; + o->newline(-1) << "atomic_set (& session_state, STAP_SESSION_ERROR);"; + o->newline(-1) << "}"; + o->newline() << "c->busy --;"; + o->newline() << "mb ();"; o->newline(-1) << "}" << endl; } } @@ -1092,22 +1112,46 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum // Construct a single entry function, and a struct kprobe pointing into // the entry function. The entry function will call the probe function. - o->newline(); o->newline() << "static void "; o->newline() << probe_entry_function_name(probenum) << " (void);"; o->newline() << "void "; o->newline() << probe_entry_function_name(probenum) << " ()"; o->newline() << "{"; - o->newline(1) << "struct context* c = & contexts [0];"; - // XXX: assert #0 is free; need locked search instead - o->newline() << "if (c->busy) { errorcount ++; return; }"; + o->newline(1) << "struct context* c = & contexts [smp_processor_id()];"; + o->newline(); + + // A precondition for running a probe handler is that we're in RUNNING + // state (not ERROR), and that no one else is already using this context. + o->newline() << "if (atomic_read (&session_state) != STAP_SESSION_RUNNING)"; + o->newline(1) << "return;"; + o->newline(-1) << "if (c->busy) {"; + o->newline(1) << "printk (KERN_ERR \"probe reentrancy\");"; + o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; + o->newline() << "return;"; + o->newline(-1) << "}"; + o->newline(); + o->newline() << "c->busy ++;"; + o->newline() << "mb ();"; // for smp + o->newline() << "c->errorcount = 0;"; o->newline() << "c->actioncount = 0;"; o->newline() << "c->nesting = 0;"; // NB: locals are initialized by probe function itself o->newline() << "probe_" << probenum << " (c);"; + + // see translate.cxx: visit_functioncall and elsewhere to see all the + // possible context indications that a probe exited prematurely + o->newline() << "if (c->errorcount || c->actioncount > MAXACTION"; + o->newline(1) << "|| c->nesting+2 >= MAXNESTING) {"; + o->newline() << "printk (KERN_ERR \"probe execution failure (e%d,n%d,a%d)\","; + o->newline(1) << "c->errorcount, c->nesting, c->actioncount);"; + o->newline(-1) << "atomic_set (& session_state, STAP_SESSION_ERROR);"; + o->newline(-1) << "}"; + o->newline() << "c->busy --;"; + o->newline() << "mb ();"; + o->newline(-1) << "}" << endl; o->newline(); |