summaryrefslogtreecommitdiffstats
path: root/tapset-perfmon.cxx
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2010-03-17 14:07:56 -0700
committerJosh Stone <jistone@redhat.com>2010-03-17 14:07:56 -0700
commit1f1b6bb1c1daa2a4257b3fcfc6b348608187efaa (patch)
tree460eb708da846a57df24e88db24988d76a1eaa38 /tapset-perfmon.cxx
parenta3cf75e6d0d589ab0922ccb0cecae6cdc480ecde (diff)
downloadsystemtap-steved-1f1b6bb1c1daa2a4257b3fcfc6b348608187efaa.tar.gz
systemtap-steved-1f1b6bb1c1daa2a4257b3fcfc6b348608187efaa.tar.xz
systemtap-steved-1f1b6bb1c1daa2a4257b3fcfc6b348608187efaa.zip
Translate perf events names into kernel names
* tapset-perfmon.cxx (perf_builder::translate_event): New. The event mapping is hard-copied from the current state of perf. (perf_builder::build): Call it.
Diffstat (limited to 'tapset-perfmon.cxx')
-rw-r--r--tapset-perfmon.cxx67
1 files changed, 63 insertions, 4 deletions
diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx
index a9f9f440..0a18a77d 100644
--- a/tapset-perfmon.cxx
+++ b/tapset-perfmon.cxx
@@ -148,6 +148,10 @@ struct perf_builder: public derived_probe_builder
vector<derived_probe *> & finished_results);
static void register_patterns(systemtap_session& s);
+private:
+ typedef map<string, pair<string, string> > event_map_t;
+ event_map_t events;
+ void translate_event(const string& name, string& type, string& config);
};
@@ -161,15 +165,23 @@ perf_builder::build(systemtap_session & sess,
string name, type, config;
bool has_name = get_param(parameters, TOK_EVENT, name);
assert(has_name);
-
- // TODO translate event name to a type and config
- type = "PERF_TYPE_HARDWARE";
- config = "PERF_COUNT_HW_CPU_CYCLES";
+ translate_event(name, type, config);
+ if (type.empty() || config.empty())
+ throw semantic_error("invalid perf event " + lex_cast_qstring(name),
+ parameters.find(TOK_EVENT)->second->tok);
+ // TODO support wildcards, e.g. stap -l 'perf.event("*")'
int64_t period;
bool has_period = get_param(parameters, TOK_SAMPLE, period);
if (!has_period)
period = 1000000;
+ else if (period < 1)
+ throw semantic_error("invalid perf sample period " + lex_cast(period),
+ parameters.find(TOK_SAMPLE)->second->tok);
+
+ if (sess.verbose > 1)
+ clog << "perf probe event=" << lex_cast_qstring(name) << " type=" << type
+ << " config=" << config << " period=" << period << endl;
finished_results.push_back
(new perf_derived_probe(base, location, name, type, config, period));
@@ -177,10 +189,57 @@ perf_builder::build(systemtap_session & sess,
void
+perf_builder::translate_event(const string& name, string& type, string& config)
+{
+ if (events.empty())
+ {
+ // XXX These are hard-coded in the perf tool, and we have to do the same.
+ // --- (see linux-2.6/tools/perf/util/parse-events.c)
+ // --- It would be much nicer to somehow generate this dynamically...
+
+#define CHW(event) event_map_t::mapped_type("PERF_TYPE_HARDWARE", "PERF_COUNT_HW_" #event)
+ events["cpu-cycles"] = CHW(CPU_CYCLES);
+ events["cycles"] = CHW(CPU_CYCLES);
+ events["instructions"] = CHW(INSTRUCTIONS);
+ events["cache-references"] = CHW(CACHE_REFERENCES);
+ events["cache-misses"] = CHW(CACHE_MISSES);
+ events["branch-instructions"] = CHW(BRANCH_INSTRUCTIONS);
+ events["branches"] = CHW(BRANCH_INSTRUCTIONS);
+ events["branch-misses"] = CHW(BRANCH_MISSES);
+ events["bus-cycles"] = CHW(BUS_CYCLES);
+#undef CHW
+
+#define CSW(event) event_map_t::mapped_type("PERF_TYPE_SOFTWARE", "PERF_COUNT_SW_" #event)
+ events["cpu-clock"] = CSW(CPU_CLOCK);
+ events["task-clock"] = CSW(TASK_CLOCK);
+ events["page-faults"] = CSW(PAGE_FAULTS);
+ events["faults"] = CSW(PAGE_FAULTS);
+ events["minor-faults"] = CSW(PAGE_FAULTS_MIN);
+ events["major-faults"] = CSW(PAGE_FAULTS_MAJ);
+ events["context-switches"] = CSW(CONTEXT_SWITCHES);
+ events["cs"] = CSW(CONTEXT_SWITCHES);
+ events["cpu-migrations"] = CSW(CPU_MIGRATIONS);
+ events["migrations"] = CSW(CPU_MIGRATIONS);
+ events["alignment-faults"] = CSW(ALIGNMENT_FAULTS);
+ events["emulation-faults"] = CSW(EMULATION_FAULTS);
+#undef CSW
+ }
+
+ event_map_t::iterator it = events.find(name);
+ if (it != events.end())
+ {
+ type = it->second.first;
+ config = it->second.second;
+ }
+}
+
+
+void
register_tapset_perf(systemtap_session& s)
{
// make sure we have support before registering anything
// XXX need additional version checks too?
+ // --- perhaps look for export of perf_event_create_kernel_counter
if (s.kernel_config["CONFIG_PERF_EVENTS"] != "y")
return;