summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--elaborate.cxx2
-rw-r--r--parse.cxx40
-rw-r--r--stapprobes.5.in18
-rw-r--r--staptree.cxx6
-rw-r--r--staptree.h1
-rw-r--r--tapsets.cxx52
-rwxr-xr-xtestsuite/buildok/six.stp6
-rwxr-xr-xtestsuite/parseok/five.stp1
-rw-r--r--translate.cxx2
10 files changed, 116 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 874105ff..83cf9f80 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2006-06-02 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 2645.
+ * stapprobes.5.in: Document "?" probe point suffix.
+ * parse.cxx (parse_probe_point): Recognize "?" optional suffix.
+ * elaborate.cxx (derive_probes): Observe probe_point->optional.
+ * staptree.h, staptree.cxx: Corresponding changes.
+ * tapsets.cxx (never_derived_probe, never_builder): New classes.
+ (register_standard_tapsets): Support "never" probe point.
+ * testsuite/buildok/six.stp, parseok/five.stp: Modifed tests.
+
+ * translate.cxx (emit_module_init): Format "-t" (benchmarking)
+ cycle-time reports similarly to "-v" (verbose) times.
+
2006-06-02 David Smith <dsmith@redhat.com>
* .cvsignore: Added more files to ignore.
diff --git a/elaborate.cxx b/elaborate.cxx
index 82e767e5..73ac6591 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -494,7 +494,7 @@ derive_probes (systemtap_session& s,
s.pattern_root->find_and_build (s, p, loc, 0, dps);
unsigned num_atend = dps.size();
- if (num_atbegin == num_atend) // nothing new derived!
+ if (! loc->optional && num_atbegin == num_atend) // nothing new derived!
throw semantic_error ("no match for probe point");
}
catch (const semantic_error& e)
diff --git a/parse.cxx b/parse.cxx
index cc1638fa..a6a90412 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -1140,7 +1140,7 @@ parser::parse_probe_point ()
probe_point::component* c = new probe_point::component;
c->functor = t->content;
pl->components.push_back (c);
- // NB though we still may add c->arg soon
+ // NB we may add c->arg soon
const token* last_t = t;
t = peek ();
@@ -1164,11 +1164,7 @@ parser::parse_probe_point ()
t = peek ();
}
- if (t && t->type == tok_operator
- && (t->content == "{" || t->content == "," || t->content == "="
- || t->content == "+=" ))
- break;
-
+ // consume optional parameter
if (t && t->type == tok_operator && t->content == "(")
{
next (); // consume "("
@@ -1179,19 +1175,31 @@ parser::parse_probe_point ()
throw parse_error ("expected ')'");
t = peek ();
- if (t && t->type == tok_operator
- && (t->content == "{" || t->content == "," || t->content == "="))
- break;
- else if (t && t->type == tok_operator &&
- t->content == "(")
- throw parse_error ("unexpected '.' or ',' or '{'");
}
- // fall through
if (t && t->type == tok_operator && t->content == ".")
- next ();
- else
- throw parse_error ("expected '.' or ',' or '(' or '{' or '=' or '+='");
+ {
+ next ();
+ continue;
+ }
+
+ // We only fall through here at the end of a probe point (past
+ // all the dotted/parametrized components).
+
+ if (t && t->type == tok_operator && t->content == "?")
+ {
+ pl->optional = true;
+ next ();
+ t = peek ();
+ // fall through
+ }
+
+ if (t && t->type == tok_operator
+ && (t->content == "{" || t->content == "," ||
+ t->content == "=" || t->content == "+=" ))
+ break;
+
+ throw parse_error ("expected '.' or ',' or '(' or '?' or '{' or '=' or '+='");
}
return pl;
diff --git a/stapprobes.5.in b/stapprobes.5.in
index d05d35c0..f1744d2f 100644
--- a/stapprobes.5.in
+++ b/stapprobes.5.in
@@ -25,15 +25,19 @@ The general probe point syntax is a dotted-symbol sequence. This
allows a breakdown of the event namespace into parts, somewhat like
the Domain Name System does on the Internet. Each component
identifier may be parametrized by a string or number literal, with a
-syntax like a function call. A component may be replaced by a "*"
-character, to expand to other matching probe points. These are all
-syntactically valid probe points:
+syntax like a function call. A component may include a "*"
+character, to expand to other matching probe points. A probe point
+may be followed by a "?" character, to indicate that it is optional,
+and that no error should result if it fails to expand.
+
+These are all syntactically valid probe points:
.SAMPLE
kernel.function("foo").return
syscall(22)
user.inode("/bin/vi").statement(0x2222)
end
kernel.syscall.*
+kernel.function("no_such_function") ?
.ESAMPLE
Probes may be broadly classified into "synchronous" and
@@ -64,6 +68,14 @@ function call, or an interruption from the user. In the case of an
error-triggered shutdown, "end" probes are not run. There are no
target variables available in either context.
+.SS NEVER
+The probe point
+.IR never
+is specially defined by the translator to mean "never". Its probe
+handler is never run, though its statements are analyzed for symbol /
+type correctness as usual. This probe point may be useful in
+conjunction with optional probes.
+
.SS TIMERS
Intervals defined by the standard kernel "jiffies" timer may be used
diff --git a/staptree.cxx b/staptree.cxx
index 5ccbc26b..5b9798df 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -102,12 +102,12 @@ symboldecl::~symboldecl ()
probe_point::probe_point (std::vector<component*> const & comps,
const token * t):
- components(comps), tok(t)
+ components(comps), tok(t), optional (false)
{
}
probe_point::probe_point ():
- tok (0)
+ tok (0), optional (false)
{
}
@@ -867,6 +867,8 @@ void probe_point::print (ostream& o) const
if (c->arg)
o << "(" << *c->arg << ")";
}
+ if (optional)
+ o << "?";
}
diff --git a/staptree.h b/staptree.h
index b2512054..fc5c590f 100644
--- a/staptree.h
+++ b/staptree.h
@@ -561,6 +561,7 @@ struct probe_point
};
std::vector<component*> components;
const token* tok; // points to first component's functor
+ bool optional;
void print (std::ostream& o) const;
probe_point ();
probe_point(std::vector<component*> const & comps,const token * t);
diff --git a/tapsets.cxx b/tapsets.cxx
index 048243bb..866c6757 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -187,7 +187,6 @@ derived_probe::emit_probe_epilogue (translator_output* o)
-
// ------------------------------------------------------------------------
// begin/end probes are run right during registration / deregistration
// ------------------------------------------------------------------------
@@ -272,6 +271,54 @@ be_derived_probe::emit_probe_entries (translator_output* o)
// ------------------------------------------------------------------------
+// never probes are never run
+// ------------------------------------------------------------------------
+
+struct never_derived_probe: public derived_probe
+{
+ never_derived_probe (probe* p): derived_probe (p) {}
+ never_derived_probe (probe* p, probe_point* l): derived_probe (p, l) {}
+
+ void emit_registrations (translator_output* o);
+ void emit_deregistrations (translator_output* o);
+ void emit_probe_entries (translator_output* o);
+};
+
+
+struct never_builder: public derived_probe_builder
+{
+ never_builder() {}
+ virtual void build(systemtap_session & sess,
+ probe * base,
+ probe_point * location,
+ std::map<std::string, literal *> const & parameters,
+ vector<derived_probe *> & finished_results)
+ {
+ finished_results.push_back(new never_derived_probe(base, location));
+ }
+};
+
+
+void
+never_derived_probe::emit_registrations (translator_output* o)
+{
+}
+
+
+void
+never_derived_probe::emit_deregistrations (translator_output* o)
+{
+}
+
+
+void
+never_derived_probe::emit_probe_entries (translator_output* o)
+{
+}
+
+
+
+// ------------------------------------------------------------------------
// Dwarf derived probes.
// ------------------------------------------------------------------------
@@ -4150,10 +4197,11 @@ bad_time:
void
register_standard_tapsets(systemtap_session & s)
{
- // Rudimentary binders for begin and end targets
s.pattern_root->bind("begin")->bind(new be_builder(true));
s.pattern_root->bind("end")->bind(new be_builder(false));
+ s.pattern_root->bind("never")->bind(new never_builder());
+
s.pattern_root->bind("timer")->bind_num("jiffies")->bind(new timer_builder());
s.pattern_root->bind("timer")->bind_num("jiffies")->bind_num("randomize")->bind(new timer_builder());
s.pattern_root->bind("timer")->bind_num("ms")->bind(new timer_builder(true));
diff --git a/testsuite/buildok/six.stp b/testsuite/buildok/six.stp
index 589a8b44..2d9a40aa 100755
--- a/testsuite/buildok/six.stp
+++ b/testsuite/buildok/six.stp
@@ -4,6 +4,10 @@
# listed in PR 1155 we cannot resolve the parameters of the inline
# at the moment.
-probe kernel.inline("context_switch") {
+probe kernel.inline("context_switch")? {
log ("found an inline function")
}
+
+probe never {
+ log ("or not ...")
+}
diff --git a/testsuite/parseok/five.stp b/testsuite/parseok/five.stp
index b7690943..29ff5990 100755
--- a/testsuite/parseok/five.stp
+++ b/testsuite/parseok/five.stp
@@ -17,3 +17,4 @@ probe time.virtual.jiffies(100) {}
probe perfcounter("tlbmiss").count(4000) {}
probe resource.freemembelow(50) {} # pages?
probe begin {}
+probe something?, or?, nothing? {}
diff --git a/translate.cxx b/translate.cxx
index 2ee2aac2..eb64d9d0 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -1037,7 +1037,7 @@ c_unparser::emit_module_init ()
o->newline() << "const char *error;";
o->newline() << "if (stats->count) {";
o->newline(1) << "int64_t avg = _stp_div64 (&error, stats->sum, stats->count);";
- o->newline() << "_stp_printf (\"probe %s (%s), %lld hits, %lld min %lld avg %lld max cycles\\n\",";
+ o->newline() << "_stp_printf (\"probe %s (%s), %lld hits taking %lldmin/%lldavg/%lldmax cycles.\\n\",";
o->newline() << "probe_point, decl_location, (long long) stats->count, (long long) stats->min, (long long) avg, (long long) stats->max);";
o->newline() << "_stp_print_flush();";
o->newline(-1) << "}";