[RFC PATCH v2 3/9] perf pmus: Expose duplicate uncore PMU scanning helpers
From: Ian Rogers
Date: Sat Oct 17 2026 - 14:55:42 EST
Export perf_pmus__scan_skip_duplicates() and add
perf_pmu__num_duplicates() to count numbered uncore PMU instances
sharing a common prefix.
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/util/pmus.c | 23 ++++++++++++++++++++++-
tools/perf/util/pmus.h | 2 ++
2 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/pmus.c b/tools/perf/util/pmus.c
index ea727d577c89..8657b36767ff 100644
--- a/tools/perf/util/pmus.c
+++ b/tools/perf/util/pmus.c
@@ -455,7 +455,7 @@ struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const c
return NULL;
}
-static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
+struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
{
bool use_core_pmus = !pmu || pmu->is_core;
int last_pmu_name_len = 0;
@@ -492,6 +492,27 @@ static struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu)
return NULL;
}
+size_t perf_pmu__num_duplicates(const struct perf_pmu *pmu)
+{
+ const struct perf_pmu *pos = pmu;
+ size_t base_len;
+ size_t count = 1;
+
+ if (!pmu || pmu->is_core)
+ return 1;
+
+ base_len = pmu_name_len_no_suffix(pmu->name ?: "");
+ list_for_each_entry_continue(pos, &other_pmus, list) {
+ size_t pos_len = pmu_name_len_no_suffix(pos->name ?: "");
+
+ if (pos_len != base_len ||
+ strncmp(pmu->name ?: "", pos->name ?: "", base_len))
+ break;
+ count++;
+ }
+ return count;
+}
+
struct perf_pmu *perf_pmus__scan_for_uncore_id(struct perf_pmu *pmu, const char *compat)
{
if (!pmu) {
diff --git a/tools/perf/util/pmus.h b/tools/perf/util/pmus.h
index d1646f91036e..58ecab3e3da3 100644
--- a/tools/perf/util/pmus.h
+++ b/tools/perf/util/pmus.h
@@ -23,6 +23,8 @@ struct perf_pmu *perf_pmus__find_by_attr(const struct perf_event_attr *attr);
struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu);
struct perf_pmu *perf_pmus__scan_core(struct perf_pmu *pmu);
+struct perf_pmu *perf_pmus__scan_skip_duplicates(struct perf_pmu *pmu);
+size_t perf_pmu__num_duplicates(const struct perf_pmu *pmu);
struct perf_pmu *perf_pmus__scan_for_event(struct perf_pmu *pmu, const char *event);
struct perf_pmu *perf_pmus__scan_matching_wildcard(struct perf_pmu *pmu, const char *wildcard);
struct perf_pmu *perf_pmus__scan_for_uncore_id(struct perf_pmu *pmu, const char *compat);
--
2.56.0.212.g129ede20d9-goog