diff options
Diffstat (limited to 'tapset-perfmon.cxx')
-rw-r--r-- | tapset-perfmon.cxx | 150 |
1 files changed, 149 insertions, 1 deletions
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 : */ |