X-Git-Url: https://sourceware.org/git/?a=blobdiff_plain;f=tapset-perfmon.cxx;h=d00d97edeac3b2b5a72f49df1dcd56b6291d776e;hb=53bb3d39c77f08d5620f9f4ff0b8a352285eaec8;hp=2d9b6555be1a356c7bbc3f66790e14ff0f2663a1;hpb=ef36f781a74605e18d3b2f7c28edd0968ac511f7;p=systemtap.git diff --git a/tapset-perfmon.cxx b/tapset-perfmon.cxx index 2d9b6555b..d00d97ede 100644 --- a/tapset-perfmon.cxx +++ b/tapset-perfmon.cxx @@ -28,6 +28,7 @@ static const string TOK_PERF("perf"); static const string TOK_TYPE("type"); static const string TOK_CONFIG("config"); static const string TOK_SAMPLE("sample"); +static const string TOK_HZ("hz"); static const string TOK_PROCESS("process"); static const string TOK_COUNTER("counter"); @@ -45,16 +46,20 @@ struct perf_derived_probe: public derived_probe int64_t interval; bool has_process; bool has_counter; + bool has_freq; string process_name; string counter; perf_derived_probe (probe* p, probe_point* l, int64_t type, int64_t config, - int64_t i, bool pp, bool cp, string pn, string cv); + int64_t i, bool pp, bool cp, bool freq, string pn, string cv); virtual void join_group (systemtap_session& s); }; struct perf_derived_probe_group: public generic_dpg { + friend bool sort_for_bpf(perf_derived_probe_group *pg, + sort_for_bpf_probe_arg_vector &v); + void emit_module_decls (systemtap_session& s); void emit_module_init (systemtap_session& s); void emit_module_exit (systemtap_session& s); @@ -67,13 +72,14 @@ perf_derived_probe::perf_derived_probe (probe* p, probe_point* l, int64_t i, bool process_p, bool counter_p, + bool freq, string process_n, string counter): derived_probe (p, l, true /* .components soon rewritten */), event_type (type), event_config (config), interval (i), - has_process (process_p), has_counter (counter_p), process_name (process_n), - counter (counter) + has_process (process_p), has_counter (counter_p), has_freq(freq), + process_name (process_n), counter (counter) { vector& comps = this->sole_location()->components; comps.clear(); @@ -94,6 +100,7 @@ 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); + this->group = s.perf_derived_probes; if (has_process && !has_counter) enable_task_finder(s); @@ -164,8 +171,17 @@ perf_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "{"; s.op->newline(1) << ".attr={ " << ".type=" << probes[i]->event_type << "ULL, " - << ".config=" << probes[i]->event_config << "ULL, " - << "{ .sample_period=" << probes[i]->interval << "ULL }},"; + << ".config=" << probes[i]->event_config << "ULL, "; + if (probes[i]->has_freq) + { + s.op->line() << "{ .sample_freq=" << probes[i]->interval << "ULL }, "; + s.op->line() << ".freq=1, "; + } + else + { + s.op->line() << "{ .sample_period=" << probes[i]->interval << "ULL }, "; + } + s.op->line() << "},"; s.op->newline() << ".callback=enter_perf_probe_" << i << ", "; s.op->newline() << ".probe=" << common_probe_init (probes[i]) << ", "; @@ -228,7 +244,7 @@ perf_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; s.op->newline() << "(*stp->probe->ph) (c);"; - common_probe_entryfn_epilogue (s, true); + common_probe_entryfn_epilogue (s, true, otf_safe_context(s)); s.op->newline(-1) << "}"; s.op->newline(); if (have_a_process_tag) @@ -266,6 +282,8 @@ struct perf_builder: public derived_probe_builder vector & finished_results); static void register_patterns(systemtap_session& s); + + virtual string name() { return "perf builder"; } }; @@ -299,7 +317,10 @@ perf_builder::build(systemtap_session & sess, throw SEMANTIC_ERROR(_("invalid perf sample period ") + lex_cast(period), parameters.find(TOK_SAMPLE)->second->tok); - string var; + int64_t freq; + bool has_freq = get_param(parameters, TOK_HZ, freq); + + interned_string var; bool has_counter = get_param(parameters, TOK_COUNTER, var); if (var.find_first_of("*?[") != string::npos) throw SEMANTIC_ERROR(_("wildcard not allowed with perf probe counter component")); @@ -309,7 +330,12 @@ perf_builder::build(systemtap_session & sess, throw SEMANTIC_ERROR(_("missing perf probe counter component name")); period = 0; // perf_event_attr.sample_freq should be 0 - if (sess.perf_counters.count(var) > 0) + vector >:: iterator it; + for (it=sess.perf_counters.begin() ; + it != sess.perf_counters.end(); it++) + if ((*it).first == var) + break; + if (it != sess.perf_counters.end()) throw SEMANTIC_ERROR(_("duplicate counter name")); // Splice a 'next' into the probe body, and then elaborate.cxx's @@ -320,12 +346,21 @@ perf_builder::build(systemtap_session & sess, } bool proc_p; - string proc_n; + interned_string proc_n; if ((proc_p = has_null_param(parameters, TOK_PROCESS))) { - proc_n = sess.cmd_file(); + try + { + proc_n = sess.cmd_file(); + } + catch (semantic_error& e) + { + throw SEMANTIC_ERROR(_("invalid -c command for unspecified process" + " probe [man stapprobes]"), NULL, NULL, &e); + } if (proc_n.empty()) - throw SEMANTIC_ERROR(_("process probe is invalid without a -c COMMAND")); + throw SEMANTIC_ERROR(_("unspecified process probe is invalid without a " + "-c COMMAND [man stapprobes]")); } else proc_p = get_param(parameters, TOK_PROCESS, proc_n); @@ -333,14 +368,22 @@ perf_builder::build(systemtap_session & sess, proc_n = find_executable (proc_n, sess.sysroot, sess.sysenv); if (sess.verbose > 1) - clog << _F("perf probe type=%" PRId64 " config=%" PRId64 " period=%" PRId64 " process=%s counter=%s", - type, config, period, proc_n.c_str(), var.c_str()) << endl; + clog << _F("perf probe type=%" PRId64 " config=%" PRId64 " %s=%" PRId64 " process=%s counter=%s", + type, config, has_freq ? "freq" : "period", has_freq ? freq : period, + proc_n.to_string().c_str(), var.to_string().c_str()) << endl; + + // The user-provided pp is already well-formed. Let's add a copy on the chain + // and set it as the new base + probe_point *new_location = new probe_point(*location); + new_location->well_formed = true; + probe *new_base = new probe(base, new_location); finished_results.push_back - (new perf_derived_probe(base, location, type, config, period, proc_p, - has_counter, proc_n, var)); + (new perf_derived_probe(new_base, location, type, config, + has_freq ? freq : period, proc_p, + has_counter, has_freq, proc_n, var)); if (!var.empty()) - sess.perf_counters[var] = make_pair(proc_n,finished_results.back()); + sess.perf_counters.push_back(make_pair (var, proc_n)); } @@ -355,10 +398,35 @@ register_tapset_perf(systemtap_session& s) match_node* event = perf->bind_num(TOK_TYPE)->bind_num(TOK_CONFIG); event->bind(builder); event->bind_num(TOK_SAMPLE)->bind(builder); + event->bind_num(TOK_HZ)->bind(builder); event->bind_str(TOK_PROCESS)->bind(builder); event->bind(TOK_PROCESS)->bind(builder); event->bind_str(TOK_COUNTER)->bind(builder); event->bind_str(TOK_PROCESS)->bind_str(TOK_COUNTER)->bind(builder); } +bool +sort_for_bpf(perf_derived_probe_group *pg, sort_for_bpf_probe_arg_vector &v) +{ + if (!pg) + return false; + + for (auto i = pg->probes.begin(); i != pg->probes.end(); ++i) + { + perf_derived_probe *p = *i; + std::stringstream o; + + o << "perf/" << p->event_type << "/" << p->event_config << "/"; + if (p->has_freq) + o << "f/" << p->interval; // uses sample_freq (hz) + else + o << "p/" << p->interval; // uses sample_period + + // XXX .process, .counter + v.push_back(std::pair(p, o.str())); + } + + return v.empty(); +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */