Skip to content

Commit 8d9f514

Browse files
captain5050acmel
authored andcommitted
perf pmus: Sort pmus by name then suffix
Sort PMUs by name. If two PMUs have the same name but differ by suffix, sort the suffixes numerically. For example, "breakpoint" comes before "cpu", "uncore_imc_free_running_0" comes before "uncore_imc_free_running_1". Suffixes need to be treated specially as otherwise they will be ordered like 0, 1, 10, 11, .., 2, 20, 21, .., etc. Only PMUs starting 'uncore_' are considered to have a potential suffix. Sorting of PMUs is done so that later patches can skip duplicate uncore PMUs that differ only by there suffix. Committer notes: Used the more compact, intention revealing strstarts() function we got from the kernel sources: - if (strncmp(str, "uncore_", 7)) + if (!strstarts(str, "uncore_")) Also in pmus_cmp() the lhs_num and rhs_num variables may end up not being set for non "uncore_" prefixed PMUs in pmu_name_len_no_suffix(), or at least gcc 7.5 in some distros (opensuse 15.5, to be EOLed in Dec/2024) thins so, so initialize both to zero. Reviewed-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: John Garry <john.g.garry@oracle.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Link: https://lore.kernel.org/r/20230825135237.921058-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent f703073 commit 8d9f514

File tree

1 file changed

+49
-0
lines changed

1 file changed

+49
-0
lines changed

tools/perf/util/pmus.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <linux/list.h>
3+
#include <linux/list_sort.h>
4+
#include <linux/string.h>
35
#include <linux/zalloc.h>
46
#include <subcmd/pager.h>
57
#include <sys/types.h>
8+
#include <ctype.h>
69
#include <dirent.h>
710
#include <pthread.h>
811
#include <string.h>
@@ -33,6 +36,31 @@ static LIST_HEAD(other_pmus);
3336
static bool read_sysfs_core_pmus;
3437
static bool read_sysfs_all_pmus;
3538

39+
static int pmu_name_len_no_suffix(const char *str, unsigned long *num)
40+
{
41+
int orig_len, len;
42+
43+
orig_len = len = strlen(str);
44+
45+
/* Non-uncore PMUs have their full length, for example, i915. */
46+
if (!strstarts(str, "uncore_"))
47+
return len;
48+
49+
/*
50+
* Count trailing digits and '_', if '_{num}' suffix isn't present use
51+
* the full length.
52+
*/
53+
while (len > 0 && isdigit(str[len - 1]))
54+
len--;
55+
56+
if (len > 0 && len != orig_len && str[len - 1] == '_') {
57+
if (num)
58+
*num = strtoul(&str[len], NULL, 10);
59+
return len - 1;
60+
}
61+
return orig_len;
62+
}
63+
3664
void perf_pmus__destroy(void)
3765
{
3866
struct perf_pmu *pmu, *tmp;
@@ -122,6 +150,25 @@ static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name)
122150
return perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name);
123151
}
124152

153+
static int pmus_cmp(void *priv __maybe_unused,
154+
const struct list_head *lhs, const struct list_head *rhs)
155+
{
156+
unsigned long lhs_num = 0, rhs_num = 0;
157+
struct perf_pmu *lhs_pmu = container_of(lhs, struct perf_pmu, list);
158+
struct perf_pmu *rhs_pmu = container_of(rhs, struct perf_pmu, list);
159+
const char *lhs_pmu_name = lhs_pmu->name ?: "";
160+
const char *rhs_pmu_name = rhs_pmu->name ?: "";
161+
int lhs_pmu_name_len = pmu_name_len_no_suffix(lhs_pmu_name, &lhs_num);
162+
int rhs_pmu_name_len = pmu_name_len_no_suffix(rhs_pmu_name, &rhs_num);
163+
int ret = strncmp(lhs_pmu_name, rhs_pmu_name,
164+
lhs_pmu_name_len < rhs_pmu_name_len ? lhs_pmu_name_len : rhs_pmu_name_len);
165+
166+
if (lhs_pmu_name_len != rhs_pmu_name_len || ret != 0 || lhs_pmu_name_len == 0)
167+
return ret;
168+
169+
return lhs_num < rhs_num ? -1 : (lhs_num > rhs_num ? 1 : 0);
170+
}
171+
125172
/* Add all pmus in sysfs to pmu list: */
126173
static void pmu_read_sysfs(bool core_only)
127174
{
@@ -156,6 +203,8 @@ static void pmu_read_sysfs(bool core_only)
156203
if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
157204
pr_err("Failure to set up any core PMUs\n");
158205
}
206+
list_sort(NULL, &core_pmus, pmus_cmp);
207+
list_sort(NULL, &other_pmus, pmus_cmp);
159208
if (!list_empty(&core_pmus)) {
160209
read_sysfs_core_pmus = true;
161210
if (!core_only)

0 commit comments

Comments
 (0)