[PATCH 5/7] perf evlist: Use hybrid default attrs whenever extended type is supported
From: James Clark <james.clark@linaro.org>
Date: 2024-08-13 13:25:30
Also in:
linux-perf-users, lkml
Subsystem:
performance events subsystem, the rest · Maintainers:
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Linus Torvalds
For x86, a hybrid version of ___evlist__add_default_attrs() was added to
support default perf stat events. This can actually be used whenever
perf_pmus__supports_extended_type() is true, which now makes default
perf stat arguments work properly on Arm big.LITTLE:
$ perf stat
...
3347093940 armv8_cortex_a53/cycles/ # 0.563 GHz (98.99%)
3295523067 armv8_cortex_a57/cycles/ # 0.554 GHz (67.07%)
...
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/perf/arch/x86/util/evlist.c | 65 -------------------------------
tools/perf/util/evlist.c | 65 +++++++++++++++++++++++++++----
tools/perf/util/evlist.h | 6 +--
3 files changed, 59 insertions(+), 77 deletions(-)
diff --git a/tools/perf/arch/x86/util/evlist.c b/tools/perf/arch/x86/util/evlist.c
index b1ce0c52d88d..bbe6240c7f71 100644
--- a/tools/perf/arch/x86/util/evlist.c
+++ b/tools/perf/arch/x86/util/evlist.c@@ -8,71 +8,6 @@ #include "topdown.h" #include "evsel.h" -static int ___evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, - size_t nr_attrs) -{ - LIST_HEAD(head); - size_t i = 0; - - for (i = 0; i < nr_attrs; i++) - event_attr_init(attrs + i); - - if (perf_pmus__num_core_pmus() == 1) - return evlist__add_attrs(evlist, attrs, nr_attrs); - - for (i = 0; i < nr_attrs; i++) { - struct perf_pmu *pmu = NULL; - - if (attrs[i].type == PERF_TYPE_SOFTWARE) { - struct evsel *evsel = evsel__new(attrs + i); - - if (evsel == NULL) - goto out_delete_partial_list; - list_add_tail(&evsel->core.node, &head); - continue; - } - - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { - struct perf_cpu_map *cpus; - struct evsel *evsel; - - evsel = evsel__new(attrs + i); - if (evsel == NULL) - goto out_delete_partial_list; - evsel->core.attr.config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; - cpus = perf_cpu_map__get(pmu->cpus); - evsel->core.cpus = cpus; - evsel->core.own_cpus = perf_cpu_map__get(cpus); - evsel->pmu_name = strdup(pmu->name); - list_add_tail(&evsel->core.node, &head); - } - } - - evlist__splice_list_tail(evlist, &head); - - return 0; - -out_delete_partial_list: - { - struct evsel *evsel, *n; - - __evlist__for_each_entry_safe(&head, n, evsel) - evsel__delete(evsel); - } - return -1; -} - -int arch_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, - size_t nr_attrs) -{ - if (!nr_attrs) - return 0; - - return ___evlist__add_default_attrs(evlist, attrs, nr_attrs); -} - int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs) { if (topdown_sys_has_perf_metrics() &&
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 1417f9a23083..e0c31399beb6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c@@ -5,6 +5,7 @@ * Parts came from builtin-{top,stat,record}.c, see those files for further * copyright notes. */ +#include "pmus.h" #include <api/fs/fs.h> #include <errno.h> #include <inttypes.h>
@@ -338,24 +339,74 @@ int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size return -1; } -int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs) + +static int __evlist__add_default_attrs_ext_type(struct evlist *evlist, + struct perf_event_attr *attrs, + size_t nr_attrs) { - size_t i; + LIST_HEAD(head); + size_t i = 0; for (i = 0; i < nr_attrs; i++) event_attr_init(attrs + i); - return evlist__add_attrs(evlist, attrs, nr_attrs); + for (i = 0; i < nr_attrs; i++) { + struct perf_pmu *pmu = NULL; + + if (attrs[i].type == PERF_TYPE_SOFTWARE) { + struct evsel *evsel = evsel__new(attrs + i); + + if (evsel == NULL) + goto out_delete_partial_list; + list_add_tail(&evsel->core.node, &head); + continue; + } + + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { + struct perf_cpu_map *cpus; + struct evsel *evsel; + + evsel = evsel__new(attrs + i); + if (evsel == NULL) + goto out_delete_partial_list; + evsel->core.attr.config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; + cpus = perf_cpu_map__get(pmu->cpus); + evsel->core.cpus = cpus; + evsel->core.own_cpus = perf_cpu_map__get(cpus); + evsel->pmu_name = strdup(pmu->name); + list_add_tail(&evsel->core.node, &head); + } + } + + evlist__splice_list_tail(evlist, &head); + + return 0; + +out_delete_partial_list: + { + struct evsel *evsel, *n; + + __evlist__for_each_entry_safe(&head, n, evsel) + evsel__delete(evsel); + } + return -1; } -__weak int arch_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, - size_t nr_attrs) +int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, + size_t nr_attrs) { + size_t i; + if (!nr_attrs) return 0; - return __evlist__add_default_attrs(evlist, attrs, nr_attrs); + if (perf_pmus__supports_extended_type()) + return __evlist__add_default_attrs_ext_type(evlist, attrs, nr_attrs); + + for (i = 0; i < nr_attrs; i++) + event_attr_init(attrs + i); + + return evlist__add_attrs(evlist, attrs, nr_attrs); } struct evsel *evlist__find_tracepoint_by_id(struct evlist *evlist, int id)
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index cccc34da5a02..06d1eeacc0d1 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h@@ -106,12 +106,8 @@ int evlist__add_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size int __evlist__add_default_attrs(struct evlist *evlist, struct perf_event_attr *attrs, size_t nr_attrs); -int arch_evlist__add_default_attrs(struct evlist *evlist, - struct perf_event_attr *attrs, - size_t nr_attrs); - #define evlist__add_default_attrs(evlist, array) \ - arch_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) + __evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs);
--
2.34.1