diff options
author | Will Cohen <wcohen@redhat.com> | 2010-03-17 11:15:24 -0400 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2010-03-17 12:07:15 -0700 |
commit | 83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7 (patch) | |
tree | c79b32282224889f13ac0170500bdd7d5eac5d82 | |
parent | 28c8b46a9fe4de0d5fc1f5a8b54760f5f8081fa5 (diff) | |
download | systemtap-steved-83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7.tar.gz systemtap-steved-83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7.tar.xz systemtap-steved-83ea76b1c27ffd25dfcec5805f54cc5e29d80bf7.zip |
Start of perf tapset parsing
-rw-r--r-- | elaborate.cxx | 1 | ||||
-rw-r--r-- | session.h | 2 | ||||
-rw-r--r-- | tapset-perfmon.cxx | 150 | ||||
-rw-r--r-- | tapsets.cxx | 6 | ||||
-rw-r--r-- | tapsets.h | 1 |
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), @@ -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); @@ -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); |