Skip to content

Commit

Permalink
perf tool_pmu: Switch to standard pmu functions and json descriptions
Browse files Browse the repository at this point in the history
Use the regular PMU approaches with tool json events to reduce the
amount of special tool_pmu code - tool_pmu__config_terms and
tool_pmu__for_each_event_cb are removed. Some functions remain, like
tool_pmu__str_to_event, as conveniences to metricgroups. Add
tool_pmu__skip_event/tool_pmu__num_skip_events to handle the case that
tool json events shouldn't appear on certain architectures. This isn't
done in jevents.py due to complexity in the empty-pmu-events.c and
when all vendor json is built into the tool.

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20241002032016.333748-10-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
  • Loading branch information
Ian Rogers authored and Namhyung Kim committed Oct 11, 2024
1 parent c9b121b commit 609aa26
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 105 deletions.
26 changes: 10 additions & 16 deletions tools/perf/util/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1549,9 +1549,6 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
{
bool zero = !!pmu->perf_event_attr_init_default;

if (perf_pmu__is_tool(pmu))
return tool_pmu__config_terms(attr, head_terms, err);

/* Fake PMU doesn't have proper terms so nothing to configure in attr. */
if (perf_pmu__is_fake(pmu))
return 0;
Expand Down Expand Up @@ -1664,8 +1661,8 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_
info->scale = 0.0;
info->snapshot = false;

/* Tool/fake PMU doesn't rewrite terms. */
if (perf_pmu__is_tool(pmu) || perf_pmu__is_fake(pmu))
/* Fake PMU doesn't rewrite terms. */
if (perf_pmu__is_fake(pmu))
goto out;

list_for_each_entry_safe(term, h, &head_terms->terms, list) {
Expand Down Expand Up @@ -1835,8 +1832,8 @@ bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name)
{
if (!name)
return false;
if (perf_pmu__is_tool(pmu))
return tool_pmu__str_to_event(name) != TOOL_PMU__EVENT_NONE;
if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(name))
return false;
if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL)
return true;
if (pmu->cpu_aliases_added || !pmu->events_table)
Expand All @@ -1848,9 +1845,6 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
{
size_t nr;

if (perf_pmu__is_tool(pmu))
return tool_pmu__num_events();

pmu_aliases_parse(pmu);
nr = pmu->sysfs_aliases + pmu->sys_json_aliases;

Expand All @@ -1861,6 +1855,9 @@ size_t perf_pmu__num_events(struct perf_pmu *pmu)
else
assert(pmu->cpu_json_aliases == 0);

if (perf_pmu__is_tool(pmu))
nr -= tool_pmu__num_skip_events();

return pmu->selectable ? nr + 1 : nr;
}

Expand Down Expand Up @@ -1911,15 +1908,15 @@ int perf_pmu__for_each_event(struct perf_pmu *pmu, bool skip_duplicate_pmus,
int ret = 0;
struct strbuf sb;

if (perf_pmu__is_tool(pmu))
return tool_pmu__for_each_event_cb(pmu, state, cb);

strbuf_init(&sb, /*hint=*/ 0);
pmu_aliases_parse(pmu);
pmu_add_cpu_aliases(pmu);
list_for_each_entry(event, &pmu->aliases, list) {
size_t buf_used, pmu_name_len;

if (perf_pmu__is_tool(pmu) && tool_pmu__skip_event(event->name))
continue;

info.pmu_name = event->pmu_name ?: pmu->name;
pmu_name_len = pmu_deduped_name_len(pmu, info.pmu_name,
skip_duplicate_pmus);
Expand Down Expand Up @@ -2325,9 +2322,6 @@ const char *perf_pmu__name_from_config(struct perf_pmu *pmu, u64 config)
if (!pmu)
return NULL;

if (perf_pmu__is_tool(pmu))
return tool_pmu__event_to_str(config);

pmu_aliases_parse(pmu);
pmu_add_cpu_aliases(pmu);
list_for_each_entry(event, &pmu->aliases, list) {
Expand Down
4 changes: 1 addition & 3 deletions tools/perf/util/pmus.c
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ static int perf_pmus__print_pmu_events__callback(void *vstate,
pr_err("Unexpected event %s/%s/\n", info->pmu->name, info->name);
return 1;
}
assert(info->pmu != NULL || info->name != NULL);
s = &state->aliases[state->index];
s->pmu = info->pmu;
#define COPY_STR(str) s->str = info->str ? strdup(info->str) : NULL
Expand Down Expand Up @@ -590,9 +591,6 @@ void perf_pmus__print_raw_pmu_events(const struct print_callbacks *print_cb, voi
int len = pmu_name_len_no_suffix(pmu->name);
const char *desc = "(see 'man perf-list' or 'man perf-record' on how to encode it)";

if (perf_pmu__is_tool(pmu))
continue;

if (!pmu->is_core)
desc = NULL;

Expand Down
109 changes: 32 additions & 77 deletions tools/perf/util/tool_pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,101 +33,54 @@ static const char *const tool_pmu__event_names[TOOL_PMU__EVENT_MAX] = {
"system_tsc_freq",
};


const char *tool_pmu__event_to_str(enum tool_pmu_event ev)
{
if (ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX)
return tool_pmu__event_names[ev];

return NULL;
}

enum tool_pmu_event tool_pmu__str_to_event(const char *str)
bool tool_pmu__skip_event(const char *name __maybe_unused)
{
int i;

tool_pmu__for_each_event(i) {
if (!strcasecmp(str, tool_pmu__event_names[i])) {
#if !defined(__aarch64__)
/* The slots event should only appear on arm64. */
if (i == TOOL_PMU__EVENT_SLOTS)
return TOOL_PMU__EVENT_NONE;
/* The slots event should only appear on arm64. */
if (strcasecmp(name, "slots") == 0)
return true;
#endif
return i;
}
}
return TOOL_PMU__EVENT_NONE;
#if !defined(__i386__) && !defined(__x86_64__)
/* The system_tsc_freq event should only appear on x86. */
if (strcasecmp(name, "system_tsc_freq") == 0)
return true;
#endif
return false;
}

static int tool_pmu__config_term(struct perf_event_attr *attr,
struct parse_events_term *term,
struct parse_events_error *err)
int tool_pmu__num_skip_events(void)
{
if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) {
enum tool_pmu_event ev = tool_pmu__str_to_event(term->config);
int num = 0;

if (ev == TOOL_PMU__EVENT_NONE)
goto err_out;

attr->config = ev;
return 0;
}
err_out:
if (err) {
char *err_str;

parse_events_error__handle(err, term->err_val,
asprintf(&err_str,
"unexpected tool event term (%s) %s",
parse_events__term_type_str(term->type_term),
term->config) < 0
? strdup("unexpected tool event term")
: err_str,
NULL);
}
return -EINVAL;
#if !defined(__aarch64__)
num++;
#endif
#if !defined(__i386__) && !defined(__x86_64__)
num++;
#endif
return num;
}

int tool_pmu__config_terms(struct perf_event_attr *attr,
struct parse_events_terms *terms,
struct parse_events_error *err)
const char *tool_pmu__event_to_str(enum tool_pmu_event ev)
{
struct parse_events_term *term;

list_for_each_entry(term, &terms->terms, list) {
if (tool_pmu__config_term(attr, term, err))
return -EINVAL;
}

return 0;
if (ev > TOOL_PMU__EVENT_NONE && ev < TOOL_PMU__EVENT_MAX)
return tool_pmu__event_names[ev];

return NULL;
}

int tool_pmu__for_each_event_cb(struct perf_pmu *pmu, void *state, pmu_event_callback cb)
enum tool_pmu_event tool_pmu__str_to_event(const char *str)
{
struct pmu_event_info info = {
.pmu = pmu,
.event_type_desc = "Tool event",
};
int i;

if (tool_pmu__skip_event(str))
return TOOL_PMU__EVENT_NONE;

tool_pmu__for_each_event(i) {
int ret;

info.name = tool_pmu__event_to_str(i);
info.alias = NULL;
info.scale_unit = NULL;
info.desc = NULL;
info.long_desc = NULL;
info.encoding_desc = NULL;
info.topic = NULL;
info.pmu_name = pmu->name;
info.deprecated = false;
ret = cb(state, &info);
if (ret)
return ret;
if (!strcasecmp(str, tool_pmu__event_names[i]))
return i;
}
return 0;
return TOOL_PMU__EVENT_NONE;
}

bool perf_pmu__is_tool(const struct perf_pmu *pmu)
Expand Down Expand Up @@ -546,6 +499,8 @@ struct perf_pmu *perf_pmus__tool_pmu(void)
.caps = LIST_HEAD_INIT(tool.caps),
.format = LIST_HEAD_INIT(tool.format),
};
if (!tool.events_table)
tool.events_table = find_core_events_table("common", "common");

return &tool;
}
12 changes: 3 additions & 9 deletions tools/perf/util/tool_pmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,11 @@ enum tool_pmu_event {
#define tool_pmu__for_each_event(ev) \
for ((ev) = TOOL_PMU__EVENT_DURATION_TIME; (ev) < TOOL_PMU__EVENT_MAX; ev++)

static inline size_t tool_pmu__num_events(void)
{
return TOOL_PMU__EVENT_MAX - 1;
}

const char *tool_pmu__event_to_str(enum tool_pmu_event ev);
enum tool_pmu_event tool_pmu__str_to_event(const char *str);
int tool_pmu__config_terms(struct perf_event_attr *attr,
struct parse_events_terms *terms,
struct parse_events_error *err);
int tool_pmu__for_each_event_cb(struct perf_pmu *pmu, void *state, pmu_event_callback cb);
bool tool_pmu__skip_event(const char *name);
int tool_pmu__num_skip_events(void);

bool tool_pmu__read_event(enum tool_pmu_event ev, u64 *result);

u64 tool_pmu__cpu_slots_per_cycle(void);
Expand Down

0 comments on commit 609aa26

Please sign in to comment.