summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Cohen <wcohen@redhat.com>2010-03-17 11:15:24 -0400
committerJosh Stone <jistone@redhat.com>2010-03-17 12:07:15 -0700
commit83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7 (patch)
treec79b32282224889f13ac0170500bdd7d5eac5d82
parent28c8b46a9fe4de0d5fc1f5a8b54760f5f8081fa5 (diff)
downloadsystemtap-steved-83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7.tar.gz
systemtap-steved-83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7.tar.xz
systemtap-steved-83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7.zip
Start of perf tapset parsing
-rw-r--r--elaborate.cxx1
-rw-r--r--session.h2
-rw-r--r--tapset-perfmon.cxx150
-rw-r--r--tapsets.cxx6
-rw-r--r--tapsets.h1
5 files changed, 159 insertions, 1 deletions
diff --git a/elaborate.cxx b/elaborate.cxx
index f656ff92..ba156b2b 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -1539,6 +1539,7 @@ systemtap_session::systemtap_session ():
dwarf_derived_probes(0),
kprobe_derived_probes(0),
hwbkpt_derived_probes(0),
+ perf_derived_probes(0),
uprobe_derived_probes(0),
utrace_derived_probes(0),
itrace_derived_probes(0),
diff --git a/session.h b/session.h
index eb1d82c0..1a1a2c9c 100644
--- a/session.h
+++ b/session.h
@@ -33,6 +33,7 @@ struct be_derived_probe_group;
struct dwarf_derived_probe_group;
struct kprobe_derived_probe_group;
struct hwbkpt_derived_probe_group;
+struct perf_derived_probe_group;
struct uprobe_derived_probe_group;
struct utrace_derived_probe_group;
struct itrace_derived_probe_group;
@@ -181,6 +182,7 @@ struct systemtap_session
dwarf_derived_probe_group* dwarf_derived_probes;
kprobe_derived_probe_group* kprobe_derived_probes;
hwbkpt_derived_probe_group* hwbkpt_derived_probes;
+ perf_derived_probe_group* perf_derived_probes;
uprobe_derived_probe_group* uprobe_derived_probes;
utrace_derived_probe_group* utrace_derived_probes;
itrace_derived_probe_group* itrace_derived_probes;
diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx
index e97ec5e6..0188439c 100644
--- a/tapset-perfmon.cxx
+++ b/tapset-perfmon.cxx
@@ -10,6 +10,7 @@
#include "session.h"
#include "tapsets.h"
+#include "translate.h"
#include "util.h"
#include <string>
@@ -18,11 +19,158 @@ using namespace std;
using namespace __gnu_cxx;
+static const string TOK_PERF("perf");
+
// ------------------------------------------------------------------------
-// perfmon derived probes
+// perf event derived probes
// ------------------------------------------------------------------------
// This is a new interface to the perfmon hw.
//
+struct perf_derived_probe: public derived_probe
+{
+ int64_t interval;
+ perf_derived_probe (probe* p, probe_point* l, int64_t i);
+ virtual void join_group (systemtap_session& s);
+};
+
+
+struct perf_derived_probe_group: public generic_dpg<perf_derived_probe>
+{
+ void emit_interval (translator_output* o);
+public:
+ void emit_module_decls (systemtap_session& s);
+ void emit_module_init (systemtap_session& s);
+ void emit_module_exit (systemtap_session& s);
+};
+
+
+perf_derived_probe::perf_derived_probe (probe* p, probe_point* l,
+ int64_t i):
+ derived_probe (p, l), interval (i)
+{
+}
+
+
+void
+perf_derived_probe::join_group (systemtap_session& s)
+{
+ if (! s.perf_derived_probes)
+ s.perf_derived_probes = new perf_derived_probe_group ();
+ s.perf_derived_probes->enroll (this);
+}
+
+
+void
+perf_derived_probe_group::emit_interval (translator_output* o)
+{
+}
+
+void
+perf_derived_probe_group::emit_module_decls (systemtap_session& s)
+{
+ if (probes.empty()) return;
+
+ s.op->newline() << "/* ---- perf probes ---- */";
+ s.op->newline() << "#include \"perf.c\"";
+ /* declarations */
+ for (unsigned i=0; i < probes.size(); i++)
+ {
+ }
+ s.op->newline();
+
+ /* wrapper functions */
+ for (unsigned i=0; i < probes.size(); i++) {
+ s.op->newline() << "void enter_perf_probe_" << i <<" (struct perf_event *e, int nmi,";
+ s.op->newline(1) << "struct perf_sample_data *data,";
+ s.op->newline() << "struct pt_regs *regs)";
+ s.op->newline(-1) << "{";
+ s.op->newline(1) << "/* handle_perf_probe(pp, &probe_NNN, regs); */";
+ s.op->newline(-1) << "}";
+ }
+
+ s.op->newline() << "static void handle_perf_probe (const char *pp,";
+ s.op->newline(1) << "void (*ph) (struct context*),";
+ s.op->newline() << "struct pt_regs *regs)";
+ s.op->newline(-1) << "{";
+
+ s.op->newline(1) << "if ((atomic_read (&session_state) == STAP_SESSION_STARTING) ||";
+ s.op->newline(1) << " (atomic_read (&session_state) == STAP_SESSION_RUNNING)) {";
+ s.op->newline(-1) << "}";
+ s.op->newline() << "{";
+ s.op->indent(1);
+ common_probe_entryfn_prologue (s.op, "STAP_SESSION_RUNNING", "pp");
+ s.op->newline() << "c->regs = regs;";
+ s.op->newline() << "(*ph) (c);";
+ common_probe_entryfn_epilogue (s.op);
+ s.op->newline(-1) << "}";
+ s.op->newline(-1) << "}";
+}
+
+
+void
+perf_derived_probe_group::emit_module_init (systemtap_session& s)
+{
+ if (probes.empty()) return;
+
+ s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
+ s.op->newline(1) << "/* struct stap_perf_probe* stp = & stap_perf_probes [i]; */";
+ s.op->newline(-1) << "}"; // for loop
+}
+
+
+void
+perf_derived_probe_group::emit_module_exit (systemtap_session& s)
+{
+ if (probes.empty()) return;
+
+ s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)";
+ s.op->newline(1) << "/* FIXME */;";
+ s.op->indent(-1);
+}
+
+
+struct perf_builder: public derived_probe_builder
+{
+ virtual void build(systemtap_session & sess,
+ probe * base, probe_point * location,
+ literal_map_t const & parameters,
+ vector<derived_probe *> & finished_results);
+
+ static void register_patterns(systemtap_session& s);
+};
+
+
+void
+perf_builder::build(systemtap_session & sess,
+ probe * base,
+ probe_point * location,
+ literal_map_t const & parameters,
+ vector<derived_probe *> & finished_results)
+{
+ int64_t period;
+ /* FIXME */
+ if (get_param(parameters, "cycles", period))
+ {
+ }
+ else
+ throw semantic_error ("unrecognized perf variant");
+ finished_results.push_back
+ (new perf_derived_probe(base, location, period));
+}
+
+
+void
+register_tapset_perf(systemtap_session& s)
+{
+ match_node* root = s.pattern_root;
+ derived_probe_builder *builder = new perf_builder();
+
+ root = root->bind(TOK_PERF);
+
+ root->bind_num("cycles")
+ ->bind(builder);
+}
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/tapsets.cxx b/tapsets.cxx
index 73959768..a1474617 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -6722,6 +6722,11 @@ register_standard_tapsets(systemtap_session & s)
s.pattern_root->bind(TOK_KERNEL)->bind_num(TOK_HWBKPT)
->bind_num(TOK_LENGTH)->bind(TOK_HWBKPT_RW)->bind(new hwbkpt_builder());
// length supported with address only, not symbol names
+
+ //perf event based probe
+ if (s.kernel_config["CONFIG_PERF_EVENTS"] == string("y") ) {
+ register_tapset_perf(s);
+ }
}
@@ -6749,6 +6754,7 @@ all_session_groups(systemtap_session& s)
DOONE(tracepoint);
DOONE(kprobe);
DOONE(hwbkpt);
+ DOONE(perf);
DOONE(hrtimer);
DOONE(procfs);
diff --git a/tapsets.h b/tapsets.h
index 9d12ee7d..06b3ab98 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -24,6 +24,7 @@ void register_tapset_itrace(systemtap_session& sess);
void register_tapset_mark(systemtap_session& sess);
void register_tapset_procfs(systemtap_session& sess);
void register_tapset_timers(systemtap_session& sess);
+void register_tapset_perf(systemtap_session& sess);
void register_tapset_utrace(systemtap_session& sess);