Skip to content

Commit e1ec69e

Browse files
captain5050namhyung
authored andcommitted
perf parse-events: Avoid scanning PMUs that can't contain events
Add perf_pmus__scan_for_event that only reads sysfs for pmus that could contain a given event. Signed-off-by: Ian Rogers <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent 9c9f4a2 commit e1ec69e

File tree

3 files changed

+97
-15
lines changed

3 files changed

+97
-15
lines changed

tools/perf/util/parse-events.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, const char *name,
490490
int ret = 0;
491491
struct evsel *first_wildcard_match = NULL;
492492

493-
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
493+
while ((pmu = perf_pmus__scan_for_event(pmu, name)) != NULL) {
494494
LIST_HEAD(config_terms);
495495
struct perf_event_attr attr;
496496

@@ -1681,7 +1681,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
16811681

16821682
INIT_LIST_HEAD(list);
16831683

1684-
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
1684+
while ((pmu = perf_pmus__scan_for_event(pmu, event_name)) != NULL) {
1685+
16851686
if (parse_events__filter_pmu(parse_state, pmu))
16861687
continue;
16871688

@@ -1760,19 +1761,21 @@ int parse_events_multi_pmu_add_or_add_pmu(struct parse_events_state *parse_state
17601761

17611762
pmu = NULL;
17621763
/* Failed to add, try wildcard expansion of event_or_pmu as a PMU name. */
1763-
while ((pmu = perf_pmus__scan(pmu)) != NULL) {
1764-
if (!parse_events__filter_pmu(parse_state, pmu) &&
1765-
perf_pmu__wildcard_match(pmu, event_or_pmu)) {
1766-
if (!parse_events_add_pmu(parse_state, *listp, pmu,
1767-
const_parsed_terms,
1768-
first_wildcard_match,
1769-
/*alternate_hw_config=*/PERF_COUNT_HW_MAX)) {
1770-
ok++;
1771-
parse_state->wild_card_pmus = true;
1772-
}
1773-
if (first_wildcard_match == NULL)
1774-
first_wildcard_match =
1775-
container_of((*listp)->prev, struct evsel, core.node);
1764+
while ((pmu = perf_pmus__scan_matching_wildcard(pmu, event_or_pmu)) != NULL) {
1765+
1766+
if (parse_events__filter_pmu(parse_state, pmu))
1767+
continue;
1768+
1769+
if (!parse_events_add_pmu(parse_state, *listp, pmu,
1770+
const_parsed_terms,
1771+
first_wildcard_match,
1772+
/*alternate_hw_config=*/PERF_COUNT_HW_MAX)) {
1773+
ok++;
1774+
parse_state->wild_card_pmus = true;
1775+
}
1776+
if (first_wildcard_match == NULL) {
1777+
first_wildcard_match =
1778+
container_of((*listp)->prev, struct evsel, core.node);
17761779
}
17771780
}
17781781
if (ok)

tools/perf/util/pmus.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "tool_pmu.h"
2020
#include "print-events.h"
2121
#include "strbuf.h"
22+
#include "string2.h"
2223

2324
/*
2425
* core_pmus: A PMU belongs to core_pmus if it's name is "cpu" or it's sysfs
@@ -350,6 +351,82 @@ struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu)
350351
return NULL;
351352
}
352353

354+
struct perf_pmu *perf_pmus__scan_for_event(struct perf_pmu *pmu, const char *event)
355+
{
356+
bool use_core_pmus = !pmu || pmu->is_core;
357+
358+
if (!pmu) {
359+
/* Hwmon filename values that aren't used. */
360+
enum hwmon_type type;
361+
int number;
362+
/*
363+
* Core PMUs, other sysfs PMUs and tool PMU can take all event
364+
* types or aren't wother optimizing for.
365+
*/
366+
unsigned int to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
367+
PERF_TOOL_PMU_TYPE_PE_OTHER_MASK |
368+
PERF_TOOL_PMU_TYPE_TOOL_MASK;
369+
370+
/* Could the event be a hwmon event? */
371+
if (parse_hwmon_filename(event, &type, &number, /*item=*/NULL, /*alarm=*/NULL))
372+
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK;
373+
374+
pmu_read_sysfs(to_read_pmus);
375+
pmu = list_prepare_entry(pmu, &core_pmus, list);
376+
}
377+
if (use_core_pmus) {
378+
list_for_each_entry_continue(pmu, &core_pmus, list)
379+
return pmu;
380+
381+
pmu = NULL;
382+
pmu = list_prepare_entry(pmu, &other_pmus, list);
383+
}
384+
list_for_each_entry_continue(pmu, &other_pmus, list)
385+
return pmu;
386+
return NULL;
387+
}
388+
389+
struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const char *wildcard)
390+
{
391+
bool use_core_pmus = !pmu || pmu->is_core;
392+
393+
if (!pmu) {
394+
/*
395+
* Core PMUs, other sysfs PMUs and tool PMU can have any name or
396+
* aren't wother optimizing for.
397+
*/
398+
unsigned int to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
399+
PERF_TOOL_PMU_TYPE_PE_OTHER_MASK |
400+
PERF_TOOL_PMU_TYPE_TOOL_MASK;
401+
402+
/*
403+
* Hwmon PMUs have an alias from a sysfs name like hwmon0,
404+
* hwmon1, etc. or have a name of hwmon_<name>. They therefore
405+
* can only have a wildcard match if the wildcard begins with
406+
* "hwmon".
407+
*/
408+
if (strisglob(wildcard) ||
409+
(strlen(wildcard) >= 5 && strncmp("hwmon", wildcard, 5) == 0))
410+
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK;
411+
412+
pmu_read_sysfs(to_read_pmus);
413+
pmu = list_prepare_entry(pmu, &core_pmus, list);
414+
}
415+
if (use_core_pmus) {
416+
list_for_each_entry_continue(pmu, &core_pmus, list) {
417+
if (perf_pmu__wildcard_match(pmu, wildcard))
418+
return pmu;
419+
}
420+
pmu = NULL;
421+
pmu = list_prepare_entry(pmu, &other_pmus, list);
422+
}
423+
list_for_each_entry_continue(pmu, &other_pmus, list) {
424+
if (perf_pmu__wildcard_match(pmu, wildcard))
425+
return pmu;
426+
}
427+
return NULL;
428+
}
429+
353430
static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
354431
{
355432
bool use_core_pmus = !pmu || pmu->is_core;

tools/perf/util/pmus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ struct perf_pmu *perf_pmus__find_by_type(unsigned int type);
1919

2020
struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu);
2121
struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu);
22+
struct perf_pmu *perf_pmus__scan_for_event(struct perf_pmu *pmu, const char *event);
23+
struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const char *wildcard);
2224

2325
const struct perf_pmu *perf_pmus__pmu_for_pmu_filter(const char *str);
2426

0 commit comments

Comments
 (0)