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.
+2005-09-05 Frank Ch. Eigler <fche@elastic.org>
+
+ 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.
+
2005-09-04 Frank Ch. Eigler <fche@elastic.org>
* translate.cxx (visit_literal_string): \-prefix double-quotes.
.TP
example1:long (v:string, k:long)
-Function "example1" does something with the given string and integer.
-It returns some integer.
+In function "example1", do something with the given string and integer.
+Return some integer.
.TP
example2:unknown ()
-Function "example2" does something. There is no explicit return value
-and it takes no parameters.
+In function "example2", do something. There is no explicit return value
+and take no parameters.
.SS LOGGING
.TP
execname:string ()
-Returns the name of the current process.
+Return the name of the current process.
.TP
pexecname:string()
-Returns the name of the parent process.
+Return the name of the parent process.
.TP
pid:long ()
-Returns the current pid.
+Return the current pid.
.TP
ppid:long ()
-Returns the current pid.
+Return the current pid.
.TP
uid:long ()
-Returns the uid of the current process.
+Return the uid of the current process.
.TP
euid:long ()
-Returns the effective uid of the current process.
+Return the effective uid of the current process.
.TP
gid:long ()
-Returns the gid of the current process.
+Return the gid of the current process.
.TP
egid:long ()
-Returns the effective gid of the current process.
+Return the effective gid of the current process.
.TP
print_regs:unknown ()
-Prints a register dump.
+Print a register dump.
.TP
print_backtrace:unknown ()
-Prints a symbolic backtrace. Use with care. May be timeconsuming.
+Print a symbolic backtrace. Use with care. May be timeconsuming.
.TP
backtrace:string ()
-Returns a string of hex addresses that are a backtrace of the stack.
+Return a string of hex addresses that are a backtrace of the stack.
May be truncated due to maximum string length.
.TP
-print_stack(bt:string)
-Does a symbolic lookup of the addresses in bt and prints one per line.
+print_stack (bt:string)
+Perform a symbolic lookup of the addresses in bt and prints one per line.
+
+.TP
+pp:string ()
+Return the probe point associated with the currently running probe handler,
+including alias and wildcard expansion effects.
.SH FILES
.nh
// ------------------------------------------------------------------------
// parse tree printing
-ostream& operator << (ostream& o, expression& k)
+ostream& operator << (ostream& o, const expression& k)
{
k.print (o);
return o;
}
-void literal_string::print (ostream& o)
+void literal_string::print (ostream& o) const
{
- // XXX: quote special chars
- o << '"' << value << '"';
+ o << '"';
+ for (unsigned i=0; i<value.size(); i++)
+ if (value[i] == '"') // or other escapeworthy characters?
+ o << '\\' << '"';
+ else
+ o << value[i];
+ o << '"';
}
-void literal_number::print (ostream& o)
+void literal_number::print (ostream& o) const
{
o << value;
}
-void binary_expression::print (ostream& o)
+void binary_expression::print (ostream& o) const
{
o << '(' << *left << ")"
<< op
}
-void unary_expression::print (ostream& o)
+void unary_expression::print (ostream& o) const
{
o << op << '(' << *operand << ")";
}
-void array_in::print (ostream& o)
+void array_in::print (ostream& o) const
{
o << "[";
for (unsigned i=0; i<operand->indexes.size(); i++)
o << "] in " << operand->base;
}
-void post_crement::print (ostream& o)
+void post_crement::print (ostream& o) const
{
o << '(' << *operand << ")" << op;
}
-void ternary_expression::print (ostream& o)
+void ternary_expression::print (ostream& o) const
{
o << "(" << *cond << ")?("
<< *truevalue << "):("
}
-void symbol::print (ostream& o)
+void symbol::print (ostream& o) const
{
o << name;
}
-void target_symbol::print (std::ostream& o)
+void target_symbol::print (std::ostream& o) const
{
o << base_name;
for (unsigned i = 0; i < components.size(); ++i)
}
-void vardecl::print (ostream& o)
+void vardecl::print (ostream& o) const
{
o << name;
if (arity > 0 || index_types.size() > 0)
}
-void vardecl::printsig (ostream& o)
+void vardecl::printsig (ostream& o) const
{
o << name << ":" << type;
if (index_types.size() > 0)
}
-void functiondecl::print (ostream& o)
+void functiondecl::print (ostream& o) const
{
o << "function " << name << " (";
for (unsigned i=0; i<formal_args.size(); i++)
}
-void functiondecl::printsig (ostream& o)
+void functiondecl::printsig (ostream& o) const
{
o << name << ":" << type << " (";
for (unsigned i=0; i<formal_args.size(); i++)
}
-void arrayindex::print (ostream& o)
+void arrayindex::print (ostream& o) const
{
o << base << "[";
for (unsigned i=0; i<indexes.size(); i++)
}
-void functioncall::print (ostream& o)
+void functioncall::print (ostream& o) const
{
o << function << "(";
for (unsigned i=0; i<args.size(); i++)
}
-ostream& operator << (ostream& o, statement& k)
+ostream& operator << (ostream& o, const statement& k)
{
k.print (o);
return o;
}
-void embeddedcode::print (ostream &o)
+void embeddedcode::print (ostream &o) const
{
o << "%{";
o << code;
o << "%}";
}
-void block::print (ostream& o)
+void block::print (ostream& o) const
{
o << "{" << endl;
for (unsigned i=0; i<statements.size(); i++)
}
-void for_loop::print (ostream& o)
+void for_loop::print (ostream& o) const
{
o << "for (";
init->print (o);
}
-void foreach_loop::print (ostream& o)
+void foreach_loop::print (ostream& o) const
{
o << "foreach ([";
for (unsigned i=0; i<indexes.size(); i++)
}
-void null_statement::print (ostream& o)
+void null_statement::print (ostream& o) const
{
o << ";";
}
-void expr_statement::print (ostream& o)
+void expr_statement::print (ostream& o) const
{
o << *value;
}
-void return_statement::print (ostream& o)
+void return_statement::print (ostream& o) const
{
o << "return " << *value;
}
-void delete_statement::print (ostream& o)
+void delete_statement::print (ostream& o) const
{
o << "delete " << *value;
}
-void next_statement::print (ostream& o)
+void next_statement::print (ostream& o) const
{
o << "next";
}
-void break_statement::print (ostream& o)
+void break_statement::print (ostream& o) const
{
o << "break";
}
-void continue_statement::print (ostream& o)
+void continue_statement::print (ostream& o) const
{
o << "continue";
}
-void if_statement::print (ostream& o)
+void if_statement::print (ostream& o) const
{
o << "if (" << *condition << ") "
<< *thenblock << endl;
}
-void stapfile::print (ostream& o)
+void stapfile::print (ostream& o) const
{
o << "# file " << name << endl;
}
-void probe::print (ostream& o)
+void probe::print (ostream& o) const
{
o << "probe ";
printsig (o);
}
-void probe::printsig (ostream& o)
+void probe::printsig (ostream& o) const
{
for (unsigned i=0; i<locations.size(); i++)
{
}
-void probe_point::print (ostream& o)
+void probe_point::print (ostream& o) const
{
for (unsigned i=0; i<components.size(); i++)
{
}
}
+
probe_alias::probe_alias(std::vector<probe_point*> const & aliases):
probe (), alias_names (aliases)
{
}
-void probe_alias::printsig (ostream& o)
+void probe_alias::printsig (ostream& o) const
{
for (unsigned i=0; i<alias_names.size(); i++)
{
}
-ostream& operator << (ostream& o, probe_point& k)
+ostream& operator << (ostream& o, const probe_point& k)
{
k.print (o);
return o;
}
-ostream& operator << (ostream& o, symboldecl& k)
+ostream& operator << (ostream& o, const symboldecl& k)
{
k.print (o);
return o;
const token* tok;
expression ();
virtual ~expression ();
- virtual void print (std::ostream& o) = 0;
+ virtual void print (std::ostream& o) const = 0;
virtual void visit (visitor* u) = 0;
};
-std::ostream& operator << (std::ostream& o, expression& k);
+std::ostream& operator << (std::ostream& o, const expression& k);
struct literal: public expression
{
std::string value;
literal_string (const std::string& v);
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
{
int64_t value;
literal_number (int64_t v);
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
expression* left;
std::string op;
expression* right;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
{
std::string op;
expression* operand;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct post_crement: public unary_expression
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct array_in: public expression
{
arrayindex* operand;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
expression* cond;
expression* truevalue;
expression* falsevalue;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
std::string name;
vardecl *referent;
symbol ();
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
};
std::string base_name;
std::vector<std::pair<component_type, std::string> > components;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
std::vector<expression*> indexes;
vardecl *referent;
arrayindex ();
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
std::vector<expression*> args;
functiondecl *referent;
functioncall ();
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
exp_type type;
symboldecl ();
virtual ~symboldecl ();
- virtual void print (std::ostream &o) = 0;
- virtual void printsig (std::ostream &o) = 0;
+ virtual void print (std::ostream &o) const = 0;
+ virtual void printsig (std::ostream &o) const = 0;
};
-std::ostream& operator << (std::ostream& o, symboldecl& k);
+std::ostream& operator << (std::ostream& o, const symboldecl& k);
struct vardecl: public symboldecl
{
- void print (std::ostream& o);
- void printsig (std::ostream& o);
+ void print (std::ostream& o) const;
+ void printsig (std::ostream& o) const;
vardecl ();
void set_arity (int arity);
bool compatible_arity (int a);
std::vector<vardecl*> locals;
statement* body;
functiondecl ();
- void print (std::ostream& o);
- void printsig (std::ostream& o);
+ void print (std::ostream& o) const;
+ void printsig (std::ostream& o) const;
};
struct statement
{
- virtual void print (std::ostream& o) = 0;
+ virtual void print (std::ostream& o) const = 0;
virtual void visit (visitor* u) = 0;
const token* tok;
statement ();
virtual ~statement ();
};
-std::ostream& operator << (std::ostream& o, statement& k);
+std::ostream& operator << (std::ostream& o, const statement& k);
struct embeddedcode: public statement
{
std::string code;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct block: public statement
{
std::vector<statement*> statements;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
expression* cond;
expr_statement* incr;
statement* block;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
vardecl* base_referent;
statement* block;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct null_statement: public statement
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct expr_statement: public statement
{
expression* value; // executed for side-effects
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
expression* condition;
statement* thenblock;
statement* elseblock;
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct return_statement: public expr_statement
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct delete_statement: public expr_statement
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct break_statement: public statement
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct continue_statement: public statement
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
struct next_statement: public statement
{
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
void visit (visitor* u);
};
std::vector<embeddedcode*> embeds;
bool privileged;
stapfile (): privileged (false) {}
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
};
};
std::vector<component*> components;
const token* tok; // points to first component's functor
- void print (std::ostream& o);
+ void print (std::ostream& o) const;
probe_point ();
probe_point(std::vector<component*> const & comps,const token * t);
};
-std::ostream& operator << (std::ostream& o, probe_point& k);
+std::ostream& operator << (std::ostream& o, const probe_point& k);
struct probe
const token* tok;
std::vector<vardecl*> locals;
probe ();
- void print (std::ostream& o);
- virtual void printsig (std::ostream &o);
+ void print (std::ostream& o) const;
+ virtual void printsig (std::ostream &o) const;
virtual ~probe() {}
};
{
probe_alias(std::vector<probe_point*> const & aliases);
std::vector<probe_point*> alias_names;
- virtual void printsig (std::ostream &o);
+ virtual void printsig (std::ostream &o) const;
};
tok = strsep(&ptr, " ");
}
%}
+
+function pp:string () %{
+ strlcpy (THIS->__retvalue, CONTEXT->probe_point, MAXSTRINGLEN);
+%}
using namespace std;
+
+// XXX: should standardize to these functions throughout translator
+
+template <typename OUT, typename IN> 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 <typename OUT, typename IN> 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 <typename IN> 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; i<out.length(); i++)
+ {
+ if (out[i] == '"') // XXX others?
+ out2 += '\\';
+ out2 += out[i];
+ }
+ out2 += '"';
+ return out2;
+}
+
+
// ------------------------------------------------------------------------
// begin/end probes are run right during registration / deregistration
// ------------------------------------------------------------------------
// 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()];";
+ 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
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;";
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;
}
}
static string TOK_RELATIVE("relative");
-// XXX: should standardize to these functions throughout translator
-template <typename OUT, typename IN> 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 <typename OUT, typename IN> 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
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();
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;";
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;
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
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) << "}";
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);";
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;
}
#! stap -p4
-probe kernel.function("uptime_read_proc") {
- print("NOW IN UPTIME\n")
+function print_stuff () {
print_regs()
print_backtrace()
bt = backtrace()
print("\n\n")
print_stack(bt)
print("\n\n")
- log("name is " . execname())
+ log("execname is \"" . execname() . "\"")
log("pid is " . string(pid()))
- log("parentname is " . pexecname())
+ log("pexecname is \"" . pexecname() . "\"")
log("ppid is " . string(ppid()))
log("uid is " . string(uid()))
log("euid is " . string(euid()))
log("gid is " . string(gid()))
log("egid is " . string(egid()))
+ log("pp is '" . pp() . "'")
+}
+
+probe kernel.function("uptime_read_proc") {
+ print("NOW IN UPTIME\n")
+ print_stuff ()
}
probe kernel.function("uptime_read_proc").return {
print("DONE WITH UPTIME\n")
- print_regs()
- print_backtrace()
- bt = backtrace()
- print("the stack is " . bt)
- print("\n\n")
- print_stack(bt)
- print("\n\n")
- log("name is " . execname())
- log("pid is " . string(pid()))
- log("parentname is " . pexecname())
- log("ppid is " . string(ppid()))
- log("uid is " . string(uid()))
- log("euid is " . string(euid()))
- log("gid is " . string(gid()))
- log("egid is " . string(egid()))
+ print_stuff ()
+ exit ()
}
probe begin {
return s.str ();
}
+// return as quoted string, with at least '"' backslash-escaped
+template <typename IN> 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; i<out.length(); i++)
+ {
+ if (out[i] == '"') // XXX others?
+ out2 += '\\';
+ out2 += out[i];
+ }
+ out2 += '"';
+ return out2;
+}
+
+
struct var;
struct tmpvar;
struct mapvar;
o->newline() << "atomic_t session_state = ATOMIC_INIT (STAP_SESSION_STARTING);";
o->newline();
o->newline() << "struct context {";
- o->newline(1) << "unsigned busy;"; // XXX: should be atomic_t ?
+ o->newline(1) << "atomic_t busy;";
+ o->newline() << "const char *probe_point;";
o->newline() << "unsigned actioncount;";
o->newline() << "unsigned nesting;";
o->newline() << "const char *last_error;";
o->newline() << "do {";
o->newline(1) << "int i;";
o->newline() << "holdon = 0;";
- o->newline() << "mb ();";
o->newline() << "for (i=0; i<NR_CPUS; i++)";
- o->newline(1) << "if (contexts[i].busy) holdon = 1;";
+ o->newline(1) << "if (atomic_read (&contexts[i].busy)) holdon = 1;";
// o->newline(-1) << "if (holdon) msleep (5);";
o->newline(-1) << "} while (holdon);";
o->newline(-1);
// XXX: might like to have an escape hatch, in case some probe is
- // genuinely stuck
+ // genuinely stuck somehow
for (int i=session->probes.size()-1; i>=0; i--)
session->probes[i]->emit_deregistrations (o, i);
if (v->index_types.size() > 0)
o->newline() << getmap (v).fini();
}
- // XXX: if anyrc, log badness
o->newline(-1) << "}" << endl;
}
o->newline() << "if (unlikely (c->last_error)) goto " << outlabel << ";";
assert (s->tok);
- o->newline() << "c->last_stmt = \"" << *s->tok << "\";";
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*s->tok) << ";";
if (actions > 0)
{
o->newline() << "c->actioncount += " << actions << ";";
tmpvar right = gensym (pe_long);
o->line() << "({";
-
- o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
-
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
o->newline(1) << left << " = ";
e->left->visit (this);
o->line() << ";";
vector<tmpvar> idx;
load_map_indices (e->operand, idx);
- o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
tmpvar res = gensym (pe_long);
o->line() << "({ ";
o->indent(1);
- o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
c_assign (t.qname(), e->left, "assignment");
c_strcat (t.qname(), e->right);
o->newline() << t << ";";
if (e->referent->index_types.size() != 0)
throw semantic_error ("unexpected reference to array", e->tok);
- parent->o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
+ parent->o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
tmpvar rval = parent->gensym (e->type);
tmpvar res = parent->gensym (e->type);
throw semantic_error ("array index type mismatch", e->indexes[i]->tok);
tmpvar ix = gensym (r->index_types[i]);
- o->newline() << "c->last_stmt = \"" << *e->indexes[i]->tok << "\";";
+ o->newline() << "c->last_stmt = "
+ << lex_cast_qstring(*e->indexes[i]->tok) << ";";
c_assign (ix.qname(), e->indexes[i], "array index copy");
idx.push_back (ix);
}
{ // block used to control varlock_r lifespan
mapvar mvar = getmap (e->referent, e->tok);
// XXX: should be varlock_r, but runtime arrays reads mutate
- o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
varlock_w guard (*this, mvar);
o->newline() << mvar.seek (idx) << ";";
c_assign (res, mvar.get(), e->tok);
{ // block used to control varlock_w lifespan
mapvar mvar = parent->getmap (e->referent, e->tok);
- o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
varlock_w guard (*parent, mvar);
o->newline() << mvar.seek (idx) << ";";
if (op != "=") // don't bother fetch slot if we will just overwrite it
throw semantic_error ("function argument type mismatch",
e->args[i]->tok, "vs", r->formal_args[i]->tok);
- o->newline() << "c->last_stmt = \"" << *e->args[i]->tok << "\";";
+ o->newline() << "c->last_stmt = "
+ << lex_cast_qstring(*e->args[i]->tok) << ";";
c_assign (t.qname(), e->args[i], "function actual argument evaluation");
}
o->newline();
o->newline() << "if (unlikely (c->nesting+2 >= MAXNESTING)) {";
o->newline(1) << "c->last_error = \"MAXNESTING exceeded\";";
- o->newline() << "c->last_stmt = \"" << *e->tok << "\";";
+ o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";";
o->newline(-1) << "} else if (likely (! c->last_error)) {";
o->indent(1);