diff options
Diffstat (limited to 'tools/perf/util/pmu.c')
-rw-r--r-- | tools/perf/util/pmu.c | 154 |
1 files changed, 59 insertions, 95 deletions
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 9a1c7e63e663..89655d53117a 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -690,7 +690,7 @@ static int is_arm_pmu_core(const char *name) return file_available(path); } -static char *perf_pmu__getcpuid(struct perf_pmu *pmu) +char *perf_pmu__getcpuid(struct perf_pmu *pmu) { char *cpuid; static bool printed; @@ -710,36 +710,9 @@ static char *perf_pmu__getcpuid(struct perf_pmu *pmu) return cpuid; } -const struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu) +__weak const struct pmu_events_table *pmu_events_table__find(void) { - const struct pmu_events_map *map; - char *cpuid = perf_pmu__getcpuid(pmu); - int i; - - /* on some platforms which uses cpus map, cpuid can be NULL for - * PMUs other than CORE PMUs. - */ - if (!cpuid) - return NULL; - - i = 0; - for (;;) { - map = &pmu_events_map[i++]; - if (!map->table) { - map = NULL; - break; - } - - if (!strcmp_cpuid_str(map->cpuid, cpuid)) - break; - } - free(cpuid); - return map; -} - -const struct pmu_events_map *__weak pmu_events_map__find(void) -{ - return perf_pmu__find_map(NULL); + return perf_pmu__find_table(NULL); } /* @@ -818,81 +791,63 @@ out: return res; } -/* - * From the pmu_events_map, find the table of PMU events that corresponds - * to the current running CPU. Then, add all PMU events from that table - * as aliases. - */ -void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, - const struct pmu_events_map *map) +struct pmu_add_cpu_aliases_map_data { + struct list_head *head; + const char *name; + const char *cpu_name; + struct perf_pmu *pmu; +}; + +static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, + const struct pmu_events_table *table __maybe_unused, + void *vdata) { - int i; - const char *name = pmu->name; - /* - * Found a matching PMU events table. Create aliases - */ - i = 0; - while (1) { - const char *cpu_name = is_arm_pmu_core(name) ? name : "cpu"; - const struct pmu_event *pe = &map->table[i++]; - const char *pname = pe->pmu ? pe->pmu : cpu_name; + struct pmu_add_cpu_aliases_map_data *data = vdata; + const char *pname = pe->pmu ? pe->pmu : data->cpu_name; - if (!pe->name) { - if (pe->metric_group || pe->metric_name) - continue; - break; - } + if (!pe->name) + return 0; - if (pmu->is_uncore && pmu_uncore_alias_match(pname, name)) - goto new_alias; + if (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->name)) + goto new_alias; - if (strcmp(pname, name)) - continue; + if (strcmp(pname, data->name)) + return 0; new_alias: - /* need type casts to override 'const' */ - __perf_pmu__new_alias(head, NULL, (char *)pe->name, - (char *)pe->desc, (char *)pe->event, - pe); - } + /* need type casts to override 'const' */ + __perf_pmu__new_alias(data->head, NULL, (char *)pe->name, (char *)pe->desc, + (char *)pe->event, pe); + return 0; } -static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) +/* + * From the pmu_events_map, find the table of PMU events that corresponds + * to the current running CPU. Then, add all PMU events from that table + * as aliases. + */ +void pmu_add_cpu_aliases_table(struct list_head *head, struct perf_pmu *pmu, + const struct pmu_events_table *table) { - const struct pmu_events_map *map; - - map = perf_pmu__find_map(pmu); - if (!map) - return; + struct pmu_add_cpu_aliases_map_data data = { + .head = head, + .name = pmu->name, + .cpu_name = is_arm_pmu_core(pmu->name) ? pmu->name : "cpu", + .pmu = pmu, + }; - pmu_add_cpu_aliases_map(head, pmu, map); + pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); } -void pmu_for_each_sys_event(pmu_sys_event_iter_fn fn, void *data) +static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) { - int i = 0; - - while (1) { - const struct pmu_sys_events *event_table; - int j = 0; - - event_table = &pmu_sys_event_tables[i++]; - - if (!event_table->table) - break; + const struct pmu_events_table *table; - while (1) { - const struct pmu_event *pe = &event_table->table[j++]; - int ret; - - if (!pe->name && !pe->metric_group && !pe->metric_name) - break; + table = perf_pmu__find_table(pmu); + if (!table) + return; - ret = fn(pe, data); - if (ret) - break; - } - } + pmu_add_cpu_aliases_table(head, pmu, table); } struct pmu_sys_event_iter_data { @@ -900,7 +855,9 @@ struct pmu_sys_event_iter_data { struct perf_pmu *pmu; }; -static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, void *data) +static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe, + const struct pmu_events_table *table __maybe_unused, + void *data) { struct pmu_sys_event_iter_data *idata = data; struct perf_pmu *pmu = idata->pmu; @@ -1890,7 +1847,11 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu) const char *sysfs = sysfs__mountpoint(); DIR *caps_dir; struct dirent *evt_ent; - int nr_caps = 0; + + if (pmu->caps_initialized) + return pmu->nr_caps; + + pmu->nr_caps = 0; if (!sysfs) return -1; @@ -1898,8 +1859,10 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu) snprintf(caps_path, PATH_MAX, "%s" EVENT_SOURCE_DEVICE_PATH "%s/caps", sysfs, pmu->name); - if (stat(caps_path, &st) < 0) + if (stat(caps_path, &st) < 0) { + pmu->caps_initialized = true; return 0; /* no error if caps does not exist */ + } caps_dir = opendir(caps_path); if (!caps_dir) @@ -1926,13 +1889,14 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu) continue; } - nr_caps++; + pmu->nr_caps++; fclose(file); } closedir(caps_dir); - return nr_caps; + pmu->caps_initialized = true; + return pmu->nr_caps; } void perf_pmu__warn_invalid_config(struct perf_pmu *pmu, __u64 config, |