From cc9ee6059e4d3fb51c0695a8a57f75eb988a1786 Mon Sep 17 00:00:00 2001 From: fche Date: Mon, 5 Sep 2005 22:00:43 +0000 Subject: 2005-09-05 Frank Ch. Eigler PR 1172. * staptree.h, staptree.cxx: Make all ::print*(), operator<< functions take const staptree objects. (literal_string::print): \-prefix double-quotes. * translate.cxx (emit_common_header): Add context probe_point field. Switch to atomic_t busy flags. (emit_module_exit): Use atomic operations for busy flag. (visit_*): Use lex_cast_qstring for last_stmt strings. * tapsets.cxx (lex_cast_quoted): \-prefix double-quotes too. (*::emit_probe_entries): Populate probe_point. Use atomic operations for busy flag. * tapset/context.stp (pp): New function. * stapfuncs.5.in: Document it. * testsuite/buildok/context_test.stp: Test it. --- tapsets.cxx | 111 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 67 insertions(+), 44 deletions(-) (limited to 'tapsets.cxx') diff --git a/tapsets.cxx b/tapsets.cxx index 14031308..de80d3a2 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -38,6 +38,51 @@ extern "C" { using namespace std; + +// XXX: should standardize to these functions throughout translator + +template inline OUT +lex_cast(IN const & in) +{ + stringstream ss; + OUT out; + if (!(ss << in && ss >> out)) + throw runtime_error("bad lexical cast"); + return out; +} + +template inline OUT +lex_cast_hex(IN const & in) +{ + stringstream ss; + OUT out; + if (!(ss << hex << showbase << in && ss >> out)) + throw runtime_error("bad lexical cast"); + return out; +} + + +// return as quoted string, with at least '"' backslash-escaped +template inline string +lex_cast_qstring(IN const & in) +{ + stringstream ss; + string out, out2; + if (!(ss << in && ss >> out)) + throw runtime_error("bad lexical cast"); + + out2 += '"'; + for (unsigned i=0; inewline(1) << "struct context* c = & contexts [smp_processor_id()];"; + o->newline() << "const char* probe_point = " + << lex_cast_qstring(*l) << ";"; // 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 @@ -110,16 +157,15 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j) 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(-1) << "if (atomic_inc_return (&c->busy) != 1) {"; + o->newline(1) << "printk (KERN_ERR \"probe reentrancy (%s vs %s)\", " + << "c->probe_point, probe_point);"; 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->last_error = 0;"; + o->newline() << "c->probe_point = probe_point;"; o->newline() << "c->nesting = 0;"; o->newline() << "c->regs = 0;"; o->newline() << "c->actioncount = 0;"; @@ -132,8 +178,7 @@ be_derived_probe::emit_probe_entries (translator_output* o, unsigned j) o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; o->newline(-1) << "}"; - o->newline() << "c->busy --;"; - o->newline() << "mb ();"; + o->newline() << "atomic_dec (&c->busy);"; o->newline(-1) << "}" << endl; } } @@ -156,27 +201,7 @@ static string TOK_LABEL("label"); static string TOK_RELATIVE("relative"); -// XXX: should standardize to these functions throughout translator -template inline OUT -lex_cast(IN const & in) -{ - stringstream ss; - OUT out; - if (!(ss << in && ss >> out)) - throw runtime_error("bad lexical cast"); - return out; -} - -template inline OUT -lex_cast_hex(IN const & in) -{ - stringstream ss; - OUT out; - if (!(ss << hex << showbase << in && ss >> out)) - throw runtime_error("bad lexical cast"); - return out; -} struct func_info @@ -1973,7 +1998,6 @@ dwarf_derived_probe::emit_deregistrations (translator_output* o, unsigned proben void 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(); @@ -1985,22 +2009,23 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum o->line() << "struct kprobe *_ignored"; o->line() << ", struct pt_regs *regs) {"; o->newline(1) << "struct context *c = & contexts [smp_processor_id()];"; - o->newline(); + o->newline() << "const char* probe_point = " + << lex_cast_qstring(*locations[0]) << ";"; // 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 0;"; - o->newline(-1) << "if (c->busy) {"; - o->newline(1) << "printk (KERN_ERR \"probe reentrancy\");"; + o->newline(-1) << "if (atomic_inc_return (&c->busy) != 1) {"; + o->newline(1) << "printk (KERN_ERR \"probe reentrancy (%s vs %s)\", " + << "c->probe_point, probe_point);"; o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; o->newline() << "return 0;"; o->newline(-1) << "}"; o->newline(); - o->newline() << "c->busy ++;"; - o->newline() << "mb ();"; // for smp o->newline() << "c->last_error = 0;"; + o->newline() << "c->probe_point = probe_point;"; o->newline() << "c->nesting = 0;"; o->newline() << "c->regs = regs;"; o->newline() << "c->actioncount = 0;"; @@ -2013,9 +2038,7 @@ dwarf_derived_probe::emit_probe_entries (translator_output* o, unsigned probenum o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; o->newline(-1) << "}"; - o->newline() << "c->busy --;"; - o->newline() << "mb ();"; - + o->newline() << "atomic_dec (& c->busy);"; o->newline() << "return 0;"; o->newline(-1) << "}" << endl; @@ -2140,7 +2163,8 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j) o->newline() << "void enter_" << j << " (unsigned long val) {"; o->newline(1) << "struct context* c = & contexts [smp_processor_id()];"; - + o->newline() << "const char* probe_point = " + << lex_cast_qstring(*locations[0]) << ";"; o->newline() << "(void) val;"; // A precondition for running a probe handler is that we're in @@ -2149,8 +2173,9 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j) 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(-1) << "if (atomic_inc_return (&c->busy) != 1) {"; + o->newline(1) << "printk (KERN_ERR \"probe reentrancy (%s vs %s)\", " + << "c->probe_point, probe_point);"; o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; o->newline() << "return;"; o->newline(-1) << "}"; @@ -2162,11 +2187,10 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j) o->line() << " + _stp_random_pm(" << randomize << ")"; o->line() << ");"; - o->newline() << "c->busy ++;"; - o->newline() << "mb ();"; // for smp + o->newline() << "c->probe_point = probe_point;"; o->newline() << "c->last_error = 0;"; o->newline() << "c->nesting = 0;"; - o->newline() << "if (! in_interrupt())"; + o->newline() << "if (in_interrupt())"; o->newline(1) << "c->regs = 0;"; o->newline(-1) << "else"; o->newline(1) << "c->regs = task_pt_regs (current);"; @@ -2181,8 +2205,7 @@ timer_derived_probe::emit_probe_entries (translator_output* o, unsigned j) o->newline() << "atomic_set (& session_state, STAP_SESSION_ERROR);"; o->newline(-1) << "}"; - o->newline() << "c->busy --;"; - o->newline() << "mb ();"; + o->newline() << "atomic_dec (&c->busy);"; o->newline(-1) << "}" << endl; } -- cgit