diff options
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r-- | tools/perf/util/pmu.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 65d0eb9a740a..ad209c88a124 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -33,6 +33,7 @@ #include "strbuf.h" #include "fncache.h" #include "pmu-hybrid.h" +#include "util/evsel_config.h" struct perf_pmu perf_pmu__fake; @@ -1056,6 +1057,35 @@ bool evsel__is_aux_event(const struct evsel *evsel) return pmu && pmu->auxtrace; } +/* + * Set @config_name to @val as long as the user hasn't already set or cleared it + * by passing a config term on the command line. + * + * @val is the value to put into the bits specified by @config_name rather than + * the bit pattern. It is shifted into position by this function, so to set + * something to true, pass 1 for val rather than a pre shifted value. + */ +#define field_prep(_mask, _val) (((_val) << (ffsll(_mask) - 1)) & (_mask)) +void evsel__set_config_if_unset(struct perf_pmu *pmu, struct evsel *evsel, + const char *config_name, u64 val) +{ + u64 user_bits = 0, bits; + struct evsel_config_term *term = evsel__get_config_term(evsel, CFG_CHG); + + if (term) + user_bits = term->val.cfg_chg; + + bits = perf_pmu__format_bits(&pmu->format, config_name); + + /* Do nothing if the user changed the value */ + if (bits & user_bits) + return; + + /* Otherwise replace it */ + evsel->core.attr.config &= ~bits; + evsel->core.attr.config |= field_prep(bits, val); +} + struct perf_pmu *perf_pmu__find(const char *name) { struct perf_pmu *pmu; |