Commit 3d504549 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo

perf pmu-events: Add pmu_events_table__find_event()

jevents stores events sorted by name. Add a find function that will
binary search event names avoiding the need to linearly search through
events.

Add a test in tests/pmu-events.c. If the PMU or event aren't found -1000
is returned. If the event is found but no callback function given, 0 is
returned.

This allows the find function also act as a test for existence.
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: Gaosheng Cui <cuigaosheng1@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.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>
Cc: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20230824041330.266337-9-irogers@google.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e3edd6cf
...@@ -282,6 +282,22 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, struc ...@@ -282,6 +282,22 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, struc
return 0; return 0;
} }
int pmu_events_table__find_event(const struct pmu_events_table *table,
struct perf_pmu *pmu,
const char *name,
pmu_event_iter_fn fn,
void *data)
{
for (const struct pmu_event *pe = &table->entries[0]; pe->name; pe++) {
if (pmu && !pmu__name_match(pmu, pe->pmu))
continue;
if (!strcasecmp(pe->name, name))
return fn(pe, table, data);
}
return -1000;
}
int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
void *data) void *data)
{ {
......
...@@ -825,6 +825,49 @@ static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *t ...@@ -825,6 +825,49 @@ static int pmu_events_table__for_each_event_pmu(const struct pmu_events_table *t
return 0; return 0;
} }
static int pmu_events_table__find_event_pmu(const struct pmu_events_table *table,
const struct pmu_table_entry *pmu,
const char *name,
pmu_event_iter_fn fn,
void *data)
{
struct pmu_event pe = {
.pmu = &big_c_string[pmu->pmu_name.offset],
};
int low = 0, high = pmu->num_entries - 1;
while (low <= high) {
int cmp, mid = (low + high) / 2;
decompress_event(pmu->entries[mid].offset, &pe);
if (!pe.name && !name)
goto do_call;
if (!pe.name && name) {
low = mid + 1;
continue;
}
if (pe.name && !name) {
high = mid - 1;
continue;
}
cmp = strcasecmp(pe.name, name);
if (cmp < 0) {
low = mid + 1;
continue;
}
if (cmp > 0) {
high = mid - 1;
continue;
}
do_call:
return fn ? fn(&pe, table, data) : 0;
}
return -1000;
}
int pmu_events_table__for_each_event(const struct pmu_events_table *table, int pmu_events_table__for_each_event(const struct pmu_events_table *table,
struct perf_pmu *pmu, struct perf_pmu *pmu,
pmu_event_iter_fn fn, pmu_event_iter_fn fn,
...@@ -845,6 +888,27 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, ...@@ -845,6 +888,27 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table,
return 0; return 0;
} }
int pmu_events_table__find_event(const struct pmu_events_table *table,
struct perf_pmu *pmu,
const char *name,
pmu_event_iter_fn fn,
void *data)
{
for (size_t i = 0; i < table->num_pmus; i++) {
const struct pmu_table_entry *table_pmu = &table->pmus[i];
const char *pmu_name = &big_c_string[table_pmu->pmu_name.offset];
int ret;
if (!pmu__name_match(pmu, pmu_name))
continue;
ret = pmu_events_table__find_event_pmu(table, table_pmu, name, fn, data);
if (ret != -1000)
return ret;
}
return -1000;
}
static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table, static int pmu_metrics_table__for_each_metric_pmu(const struct pmu_metrics_table *table,
const struct pmu_table_entry *pmu, const struct pmu_table_entry *pmu,
pmu_metric_iter_fn fn, pmu_metric_iter_fn fn,
......
...@@ -81,6 +81,11 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table, ...@@ -81,6 +81,11 @@ int pmu_events_table__for_each_event(const struct pmu_events_table *table,
struct perf_pmu *pmu, struct perf_pmu *pmu,
pmu_event_iter_fn fn, pmu_event_iter_fn fn,
void *data); void *data);
int pmu_events_table__find_event(const struct pmu_events_table *table,
struct perf_pmu *pmu,
const char *name,
pmu_event_iter_fn fn,
void *data);
int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn, int pmu_metrics_table__for_each_metric(const struct pmu_metrics_table *table, pmu_metric_iter_fn fn,
void *data); void *data);
......
...@@ -546,6 +546,11 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count) ...@@ -546,6 +546,11 @@ static int __test_core_pmu_event_aliases(char *pmu_name, int *count)
pmu_add_cpu_aliases_table(pmu, table); pmu_add_cpu_aliases_table(pmu, table);
res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL);
if (res != 0) {
pr_debug("Missing test event in test architecture");
return res;
}
for (; *test_event_table; test_event_table++) { for (; *test_event_table; test_event_table++) {
struct perf_pmu_test_event test_event = **test_event_table; struct perf_pmu_test_event test_event = **test_event_table;
struct pmu_event const *event = &test_event.event; struct pmu_event const *event = &test_event.event;
......
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