Commit 8d9f5146 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo

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: default avatarKan Liang <kan.liang@linux.intel.com>
Signed-off-by: default avatarIan 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.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f703073e
// SPDX-License-Identifier: GPL-2.0
#include <linux/list.h>
#include <linux/list_sort.h>
#include <linux/string.h>
#include <linux/zalloc.h>
#include <subcmd/pager.h>
#include <sys/types.h>
#include <ctype.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
......@@ -33,6 +36,31 @@ static LIST_HEAD(other_pmus);
static bool read_sysfs_core_pmus;
static bool read_sysfs_all_pmus;
static int pmu_name_len_no_suffix(const char *str, unsigned long *num)
{
int orig_len, len;
orig_len = len = strlen(str);
/* Non-uncore PMUs have their full length, for example, i915. */
if (!strstarts(str, "uncore_"))
return len;
/*
* Count trailing digits and '_', if '_{num}' suffix isn't present use
* the full length.
*/
while (len > 0 && isdigit(str[len - 1]))
len--;
if (len > 0 && len != orig_len && str[len - 1] == '_') {
if (num)
*num = strtoul(&str[len], NULL, 10);
return len - 1;
}
return orig_len;
}
void perf_pmus__destroy(void)
{
struct perf_pmu *pmu, *tmp;
......@@ -122,6 +150,25 @@ static struct perf_pmu *perf_pmu__find2(int dirfd, const char *name)
return perf_pmu__lookup(core_pmu ? &core_pmus : &other_pmus, dirfd, name);
}
static int pmus_cmp(void *priv __maybe_unused,
const struct list_head *lhs, const struct list_head *rhs)
{
unsigned long lhs_num = 0, rhs_num = 0;
struct perf_pmu *lhs_pmu = container_of(lhs, struct perf_pmu, list);
struct perf_pmu *rhs_pmu = container_of(rhs, struct perf_pmu, list);
const char *lhs_pmu_name = lhs_pmu->name ?: "";
const char *rhs_pmu_name = rhs_pmu->name ?: "";
int lhs_pmu_name_len = pmu_name_len_no_suffix(lhs_pmu_name, &lhs_num);
int rhs_pmu_name_len = pmu_name_len_no_suffix(rhs_pmu_name, &rhs_num);
int ret = strncmp(lhs_pmu_name, rhs_pmu_name,
lhs_pmu_name_len < rhs_pmu_name_len ? lhs_pmu_name_len : rhs_pmu_name_len);
if (lhs_pmu_name_len != rhs_pmu_name_len || ret != 0 || lhs_pmu_name_len == 0)
return ret;
return lhs_num < rhs_num ? -1 : (lhs_num > rhs_num ? 1 : 0);
}
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(bool core_only)
{
......@@ -156,6 +203,8 @@ static void pmu_read_sysfs(bool core_only)
if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
pr_err("Failure to set up any core PMUs\n");
}
list_sort(NULL, &core_pmus, pmus_cmp);
list_sort(NULL, &other_pmus, pmus_cmp);
if (!list_empty(&core_pmus)) {
read_sysfs_core_pmus = true;
if (!core_only)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment