From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4690CC433EF for ; Fri, 15 Jul 2022 06:39:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229945AbiGOGjB (ORCPT ); Fri, 15 Jul 2022 02:39:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231244AbiGOGiO (ORCPT ); Fri, 15 Jul 2022 02:38:14 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C744A77A4F for ; Thu, 14 Jul 2022 23:37:44 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-31decb2c9cbso19565327b3.17 for ; Thu, 14 Jul 2022 23:37:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=FKBmITwflNjUMeSv3iJ/EBya5U2H6wfrJ0UankXXrIY=; b=iaSXXv02hv6mVartLw/vJRJMdyzu27BLLFj+bFdce6uQZpgMhi/BKGkI80XrTI2VVJ VMmlVq+jybGea1ixd2LtrVOG90SjMlyHod6EV7zOZ8DSjYCd3g4mJO0GQ5hoqjwczyIm tqG4PlbVuGOdqR5t3f84tNWGWTunQ6RIt6C6VcozPvOd3hghcpgAf9aYeJJZdp4ep7OB TIMy1oFvfnyxkb8/DxkSQh1RabpV+s86A44PSpAIXaBMqU7kz4eFcCg3U8IYUKnheEwt Fw3XjGwcSAggeN+c3ieyv47l2gKsE2ssL18VPcSvpl8qAva3008HOifk8f05o4ht+69H udKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=FKBmITwflNjUMeSv3iJ/EBya5U2H6wfrJ0UankXXrIY=; b=cChSqj1LwvM7oSrCEjlV4CyPw/WCR/KsypZEPvJieobJ0nmW6PxOJd1nTq4lxpyL4l 6VT6wotfbJgw70X+YF9Y+zxbBz1OoBypDmJrgFHjtNns8MIv9n/LKYkbtCMRoXBgFshw QK963BulVn2L/VLaJuf+oJSsbAENt/p6qQzGQkikRPXnV7qVOxQUofUG8jGjnjXL4Ne4 393pY0SJ4m3kmJNjS8cceDXHVAR64H7uf74CgqZ+oFOUDvmujQR1n+YBxngNjPU+BOCN s1g4GC+T3jaT2Y4ZRB9d9Paf5A4b2645NlqV4a+pV7W0Lbi3eaZS8SCt2R/P2fYpE8ct CZnQ== X-Gm-Message-State: AJIora9197ineZWObCRW5haL2PXxNl6z2Z13p4AfBlmYquQVFF2qkepP 2rPktPEfvA18om8qCNTYP9Vlw0rMpHQP X-Google-Smtp-Source: AGRyM1v6cbe/lH7fDBMgXBU+//2Bqo3UkfQsnjZQoMzONHQ9akAApo48c55I5jImrL+qgs99kwLDocP5ByQw X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:e8fe:2a8e:e0f6:318d]) (user=irogers job=sendgmr) by 2002:a81:70e:0:b0:31c:8204:26ac with SMTP id 14-20020a81070e000000b0031c820426acmr13881197ywh.175.1657867063812; Thu, 14 Jul 2022 23:37:43 -0700 (PDT) Date: Thu, 14 Jul 2022 23:36:50 -0700 In-Reply-To: <20220715063653.3203761-1-irogers@google.com> Message-Id: <20220715063653.3203761-13-irogers@google.com> Mime-Version: 1.0 References: <20220715063653.3203761-1-irogers@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [PATCH v1 12/15] perf pmu-events: Don't assume pmu_event is an array From: Ian Rogers To: John Garry , Will Deacon , James Clark , Mike Leach , Leo Yan , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Zhengjun Xing , Ravi Bangoria , Kan Liang , Adrian Hunter , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Current code assumes that a struct pmu_event can be iterated over forward until a NULL pmu_event is encountered. This makes it difficult to refactor pmu_event. Add a loop function taking a callback function that's passed the struct pmu_event. This way the pmu_event is only needed for one element and not an entire array. Switch existing code iterating over the pmu_event arrays to use the new loop function pmu_events_table_for_each_event. Signed-off-by: Ian Rogers --- tools/perf/pmu-events/empty-pmu-events.c | 34 +++-- tools/perf/pmu-events/jevents.py | 34 +++-- tools/perf/pmu-events/pmu-events.h | 3 + tools/perf/tests/pmu-events.c | 136 +++++++++-------- tools/perf/util/metricgroup.c | 181 ++++++++++++++++------- tools/perf/util/pmu.c | 65 ++++---- tools/perf/util/s390-sample-raw.c | 42 ++++-- 7 files changed, 313 insertions(+), 182 deletions(-) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 028f44efe48d..bee1967baa2b 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -247,6 +247,20 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { }, }; +int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, + void *data) +{ + for (const struct pmu_event *pe = &table[0]; + pe->name || pe->metric_group || pe->metric_name; + pe++) { + int ret = fn(pe, table, data); + + if (ret) + return ret; + } + return 0; +} + const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu) { const struct pmu_event *table = NULL; @@ -291,14 +305,10 @@ int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->table; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } @@ -319,14 +329,10 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; tables->name; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 800db6364078..3cb8a196a76d 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -410,6 +410,20 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { \t}, }; +int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, + void *data) +{ + for (const struct pmu_event *pe = &table[0]; + pe->name || pe->metric_group || pe->metric_name; + pe++) { + int ret = fn(pe, table, data); + + if (ret) + return ret; + } + return 0; +} + const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu) { const struct pmu_event *table = NULL; @@ -453,14 +467,10 @@ int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->table; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } @@ -481,14 +491,10 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; tables->name; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h index 485e730f9922..70672842f77f 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -34,6 +34,9 @@ typedef int (*pmu_event_iter_fn)(const struct pmu_event *pe, const struct pmu_event *table, void *data); +int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, + void *data); + const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu); const struct pmu_event *find_core_events_table(const char *arch, const char *cpuid); int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data); diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ccbf1057ba4c..a9808932f9b5 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -423,84 +423,104 @@ static int compare_alias_to_test_event(struct perf_pmu_alias *alias, return 0; } -/* Verify generated events from pmu-events.c are as expected */ -static int test__pmu_event_table(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +static int test__pmu_event_table_core_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *data) { - const struct pmu_event *sys_event_tables = find_sys_events_table("pme_test_soc_sys"); - const struct pmu_event *table = find_core_events_table("testarch", "testcpu"); - int map_events = 0, expected_events; + int *map_events = data; + struct perf_pmu_test_event const **test_event_table; + bool found = false; - /* ignore 3x sentinels */ - expected_events = ARRAY_SIZE(core_events) + - ARRAY_SIZE(uncore_events) + - ARRAY_SIZE(sys_events) - 3; + if (!pe->name) + return 0; - if (!table || !sys_event_tables) - return -1; + if (pe->pmu) + test_event_table = &uncore_events[0]; + else + test_event_table = &core_events[0]; - for (; table->name; table++) { - struct perf_pmu_test_event const **test_event_table; - bool found = false; + for (; *test_event_table; test_event_table++) { + struct perf_pmu_test_event const *test_event = *test_event_table; + struct pmu_event const *event = &test_event->event; - if (table->pmu) - test_event_table = &uncore_events[0]; - else - test_event_table = &core_events[0]; + if (strcmp(pe->name, event->name)) + continue; + found = true; + (*map_events)++; - for (; *test_event_table; test_event_table++) { - struct perf_pmu_test_event const *test_event = *test_event_table; - struct pmu_event const *event = &test_event->event; + if (compare_pmu_events(pe, event)) + return -1; - if (strcmp(table->name, event->name)) - continue; - found = true; - map_events++; + pr_debug("testing event table %s: pass\n", pe->name); + } + if (!found) { + pr_err("testing event table: could not find event %s\n", pe->name); + return -1; + } + return 0; +} - if (compare_pmu_events(table, event)) - return -1; +static int test__pmu_event_table_sys_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *data) +{ + int *map_events = data; + struct perf_pmu_test_event const **test_event_table; + bool found = false; - pr_debug("testing event table %s: pass\n", table->name); - } + test_event_table = &sys_events[0]; - if (!found) { - pr_err("testing event table: could not find event %s\n", - table->name); - return -1; - } - } + for (; *test_event_table; test_event_table++) { + struct perf_pmu_test_event const *test_event = *test_event_table; + struct pmu_event const *event = &test_event->event; - for (table = sys_event_tables; table->name; table++) { - struct perf_pmu_test_event const **test_event_table; - bool found = false; + if (strcmp(pe->name, event->name)) + continue; + found = true; + (*map_events)++; - test_event_table = &sys_events[0]; + if (compare_pmu_events(pe, event)) + return TEST_FAIL; - for (; *test_event_table; test_event_table++) { - struct perf_pmu_test_event const *test_event = *test_event_table; - struct pmu_event const *event = &test_event->event; + pr_debug("testing sys event table %s: pass\n", pe->name); + } + if (!found) { + pr_debug("testing sys event table: could not find event %s\n", pe->name); + return TEST_FAIL; + } + return TEST_OK; +} - if (strcmp(table->name, event->name)) - continue; - found = true; - map_events++; +/* Verify generated events from pmu-events.c are as expected */ +static int test__pmu_event_table(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) +{ + const struct pmu_event *sys_event_table = find_sys_events_table("pme_test_soc_sys"); + const struct pmu_event *table = find_core_events_table("testarch", "testcpu"); + int map_events = 0, expected_events, err; - if (compare_pmu_events(table, event)) - return -1; + /* ignore 3x sentinels */ + expected_events = ARRAY_SIZE(core_events) + + ARRAY_SIZE(uncore_events) + + ARRAY_SIZE(sys_events) - 3; - pr_debug("testing sys event table %s: pass\n", table->name); - } - if (!found) { - pr_debug("testing event table: could not find event %s\n", - table->name); - return -1; - } - } + if (!table || !sys_event_table) + return -1; + + err = pmu_events_table_for_each_event(table, test__pmu_event_table_core_callback, + &map_events); + if (err) + return err; + + err = pmu_events_table_for_each_event(sys_event_table, test__pmu_event_table_sys_callback, + &map_events); + if (err) + return err; if (map_events != expected_events) { pr_err("testing event table: found %d, but expected %d\n", map_events, expected_events); - return -1; + return TEST_FAIL; } return 0; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 680f7c63838d..f702b73a7609 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -538,12 +538,40 @@ static int metricgroup__print_sys_event_iter(const struct pmu_event *pe, d->details, d->groups, d->metriclist); } +struct metricgroup_print_data { + const char *pmu_name; + struct strlist *metriclist; + char *filter; + struct rblist *groups; + bool metricgroups; + bool raw; + bool details; +}; + +static int metricgroup__print_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct metricgroup_print_data *data = vdata; + + if (!pe->metric_expr) + return 0; + + if (data->pmu_name && perf_pmu__is_hybrid(pe->pmu) && strcmp(data->pmu_name, pe->pmu)) + return 0; + + return metricgroup__print_pmu_event(pe, data->metricgroups, data->filter, + data->raw, data->details, data->groups, + data->metriclist); +} + void metricgroup__print(bool metrics, bool metricgroups, char *filter, bool raw, bool details, const char *pmu_name) { struct rblist groups; struct rb_node *node, *next; struct strlist *metriclist = NULL; + const struct pmu_event *table; if (!metricgroups) { metriclist = strlist__new(NULL, NULL); @@ -555,22 +583,22 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, groups.node_new = mep_new; groups.node_cmp = mep_cmp; groups.node_delete = mep_delete; - for (const struct pmu_event *pe = pmu_events_map__find(); pe; pe++) { + table = pmu_events_map__find(); + if (table) { + struct metricgroup_print_data data = { + .pmu_name = pmu_name, + .metriclist = metriclist, + .metricgroups = metricgroups, + .filter = filter, + .raw = raw, + .details = details, + .groups = &groups, + }; - if (!pe->name && !pe->metric_group && !pe->metric_name) - break; - if (!pe->metric_expr) - continue; - if (pmu_name && perf_pmu__is_hybrid(pe->pmu) && - strcmp(pmu_name, pe->pmu)) { - continue; - } - if (metricgroup__print_pmu_event(pe, metricgroups, filter, - raw, details, &groups, - metriclist) < 0) - return; + pmu_events_table_for_each_event(table, + metricgroup__print_callback, + &data); } - { struct metricgroup_iter_data data = { .fn = metricgroup__print_sys_event_iter, @@ -1043,30 +1071,35 @@ static int __add_metric(struct list_head *metric_list, return ret; } -#define table_for_each_event(__pe, __idx, __table) \ - if (__table) \ - for (__idx = 0, __pe = &__table[__idx]; \ - __pe->name || __pe->metric_group || __pe->metric_name; \ - __pe = &__table[++__idx]) +struct metricgroup__find_metric_data { + const char *metric; + const struct pmu_event *pe; +}; + +static int metricgroup__find_metric_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct metricgroup__find_metric_data *data = vdata; + + if (!match_metric(pe->metric_name, data->metric)) + return 0; -#define table_for_each_metric(__pe, __idx, __table, __metric) \ - table_for_each_event(__pe, __idx, __table) \ - if (__pe->metric_expr && \ - (match_metric(__pe->metric_group, __metric) || \ - match_metric(__pe->metric_name, __metric))) + data->pe = pe; + return -1; +} const struct pmu_event *metricgroup__find_metric(const char *metric, const struct pmu_event *table) { - const struct pmu_event *pe; - int i; + struct metricgroup__find_metric_data data = { + .metric = metric, + .pe = NULL, + }; - table_for_each_event(pe, i, table) { - if (match_metric(pe->metric_name, metric)) - return pe; - } + pmu_events_table_for_each_event(table, metricgroup__find_metric_callback, &data); - return NULL; + return data.pe; } static int add_metric(struct list_head *metric_list, @@ -1151,6 +1184,33 @@ static int metric_list_cmp(void *priv __maybe_unused, const struct list_head *l, return right_count - left_count; } +struct metricgroup__add_metric_data { + struct list_head *list; + const char *metric_name; + const char *modifier; + bool metric_no_group; + bool has_match; +}; + +static int metricgroup__add_metric_callback(const struct pmu_event *pe, + const struct pmu_event *table, + void *vdata) +{ + struct metricgroup__add_metric_data *data = vdata; + int ret = 0; + + if (pe->metric_expr && + (match_metric(pe->metric_group, data->metric_name) || + match_metric(pe->metric_name, data->metric_name))) { + + data->has_match = true; + ret = add_metric(data->list, pe, data->modifier, data->metric_no_group, + /*root_metric=*/NULL, + /*visited_metrics=*/NULL, table); + } + return ret; +} + /** * metricgroup__add_metric - Find and add a metric, or a metric group. * @metric_name: The name of the metric or metric group. For example, "IPC" @@ -1169,24 +1229,29 @@ static int metricgroup__add_metric(const char *metric_name, const char *modifier struct list_head *metric_list, const struct pmu_event *table) { - const struct pmu_event *pe; LIST_HEAD(list); - int i, ret; + int ret; bool has_match = false; - /* - * Iterate over all metrics seeing if metric matches either the name or - * group. When it does add the metric to the list. - */ - table_for_each_metric(pe, i, table, metric_name) { - has_match = true; - ret = add_metric(&list, pe, modifier, metric_no_group, - /*root_metric=*/NULL, - /*visited_metrics=*/NULL, table); + { + struct metricgroup__add_metric_data data = { + .list = &list, + .metric_name = metric_name, + .modifier = modifier, + .metric_no_group = metric_no_group, + .has_match = false, + }; + /* + * Iterate over all metrics seeing if metric matches either the + * name or group. When it does add the metric to the list. + */ + ret = pmu_events_table_for_each_event(table, metricgroup__add_metric_callback, + &data); if (ret) goto out; - } + has_match = data.has_match; + } { struct metricgroup_iter_data data = { .fn = metricgroup__add_metric_sys_event_iter, @@ -1602,26 +1667,30 @@ int metricgroup__parse_groups_test(struct evlist *evlist, metric_no_merge, &perf_pmu__fake, metric_events, table); } +static int metricgroup__has_metric_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + const char *metric = vdata; + + if (!pe->metric_expr) + return 0; + + if (match_metric(pe->metric_name, metric)) + return 1; + + return 0; +} + bool metricgroup__has_metric(const char *metric) { const struct pmu_event *table = pmu_events_map__find(); - const struct pmu_event *pe; - int i; if (!table) return false; - for (i = 0; ; i++) { - pe = &table[i]; - - if (!pe->name && !pe->metric_group && !pe->metric_name) - break; - if (!pe->metric_expr) - continue; - if (match_metric(pe->metric_name, metric)) - return true; - } - return false; + return pmu_events_table_for_each_event(table, metricgroup__has_metric_callback, + (void *)metric) ? true : false; } int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 893cc0ff7758..7398a277c742 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -791,6 +791,36 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) return res; } +struct pmu_add_cpu_aliases_map_data { + struct list_head *head; + const char *name; + const char *cpu_name; + struct perf_pmu *pmu; +}; + +static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct pmu_add_cpu_aliases_map_data *data = vdata; + const char *pname = pe->pmu ? pe->pmu : data->cpu_name; + + if (!pe->name) + return 0; + + if (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->name)) + goto new_alias; + + if (strcmp(pname, data->name)) + return 0; + +new_alias: + /* need type casts to override 'const' */ + __perf_pmu__new_alias(data->head, NULL, (char *)pe->name, (char *)pe->desc, + (char *)pe->event, pe); + return 0; +} + /* * From the pmu_events_map, find the table of PMU events that corresponds * to the current running CPU. Then, add all PMU events from that table @@ -799,35 +829,14 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, const struct pmu_event *table) { - int i; - const char *name = pmu->name; - /* - * Found a matching PMU events table. Create aliases - */ - i = 0; - while (1) { - const char *cpu_name = is_arm_pmu_core(name) ? name : "cpu"; - const struct pmu_event *pe = &table[i++]; - const char *pname = pe->pmu ? pe->pmu : cpu_name; - - if (!pe->name) { - if (pe->metric_group || pe->metric_name) - continue; - break; - } - - if (pmu->is_uncore && pmu_uncore_alias_match(pname, name)) - goto new_alias; - - if (strcmp(pname, name)) - continue; + struct pmu_add_cpu_aliases_map_data data = { + .head = head, + .name = pmu->name, + .cpu_name = is_arm_pmu_core(pmu->name) ? pmu->name : "cpu", + .pmu = pmu, + }; -new_alias: - /* need type casts to override 'const' */ - __perf_pmu__new_alias(head, NULL, (char *)pe->name, - (char *)pe->desc, (char *)pe->event, - pe); - } + pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); } static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 1ecb718fc0eb..b1c052c176bb 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -129,6 +129,28 @@ static int get_counterset_start(int setnr) } } +struct get_counter_name_data { + int wanted; + const char *result; +}; + +static int get_counter_name_callback(const struct pmu_event *evp, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct get_counter_name_data *data = vdata; + int rc, event_nr; + + if (evp->name == NULL || evp->event == NULL) + return 0; + rc = sscanf(evp->event, "event=%x", &event_nr); + if (rc == 1 && event_nr == data->wanted) { + data->result = evp->name; + return 1; /* Terminate the search. */ + } + return 0; +} + /* Scan the PMU table and extract the logical name of a counter from the * PMU events table. Input is the counter set and counter number with in the * set. Construct the event number and use this as key. If they match return @@ -137,20 +159,16 @@ static int get_counterset_start(int setnr) */ static const char *get_counter_name(int set, int nr, const struct pmu_event *table) { - int rc, event_nr, wanted = get_counterset_start(set) + nr; + struct get_counter_name_data data = { + .wanted = get_counterset_start(set) + nr, + .result = NULL, + }; - if (table) { - const struct pmu_event *evp = table; + if (!table) + return NULL; - for (; evp->name || evp->event || evp->desc; ++evp) { - if (evp->name == NULL || evp->event == NULL) - continue; - rc = sscanf(evp->event, "event=%x", &event_nr); - if (rc == 1 && event_nr == wanted) - return evp->name; - } - } - return NULL; + pmu_events_table_for_each_event(table, get_counter_name_callback, &data); + return data.result; } static void s390_cpumcfdg_dump(struct perf_sample *sample) -- 2.37.0.170.g444d1eabd0-goog From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A73D1C433EF for ; Fri, 15 Jul 2022 06:43:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=H37dk1cV77soM6L9kKmrgov9TE4kpcr0PqIZLVyj3ps=; b=3GeJWPu+l1JKbTYeV2gcvnjhwh yICKH6w1elW2jicCloOoS5xQll4u57buKBvuReFgQVDhPOtwvTdCyll1p9np6EiDM6Dr2huugWyo+ pEjaM4jZ/4qWm9idO1Ij7IxhIVmZQeI9VaC62F5Dc/ZDV5LTd5SCCAp84ibI/8z1T29fNJtMNXHf0 j31ggNoaICVwOmxvzgVT+8+ojX8osSZe/Zsx7v88OVP+v9tYpvWXsay8EWzJ4fHWalA5z0RiSBBG6 WIVkJ7GbJG8qnZGAFCIMZor2nyojJwXMb8k+n6vTWPQso5zh1m8oaqOQyBEzQz538QJF2QPQUuk+J 6geRk3Aw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1oCF1X-004fsh-DW; Fri, 15 Jul 2022 06:42:03 +0000 Received: from desiato.infradead.org ([90.155.92.199]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oCExV-004eAt-UX for linux-arm-kernel@bombadil.infradead.org; Fri, 15 Jul 2022 06:37:54 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:Cc:To:From:Subject: References:Mime-Version:Message-Id:In-Reply-To:Date:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description; bh=FKBmITwflNjUMeSv3iJ/EBya5U2H6wfrJ0UankXXrIY=; b=FLb9cyUBmmv6pRgBPKlyFuRKoU Up/3AWmCbhwUAqgbjClYwQep7LXjZGGkeC74XYTC3lhKrnpPUCojPEZcibIjw27NBAnHLKAi1Dfq8 RW7W+WLGw0vOAQ7oBReZudZNP1aZESPro9A7Pe40kZfEsbsG71B/BoWa9ZKjRas7cRvQNsq17iEuK feIhhC0jEhXhA46pYstJSlL/jOrbNMd0edeEXAeCnultYcsdh2/WoHvwMFZ/9IMuekB6+i+AHpNAR qCDe4OVxQdDMs7GAAjAjq00C2khxegIUo8Z5B+JtNBo4hYcDdpZV80Lv7x0D0Pm7QxqoZbsrfdG8M +MFKaqsg==; Received: from mail-yw1-x1149.google.com ([2607:f8b0:4864:20::1149]) by desiato.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1oCExP-0042O3-4w for linux-arm-kernel@lists.infradead.org; Fri, 15 Jul 2022 06:37:50 +0000 Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-317f6128c86so33990177b3.22 for ; Thu, 14 Jul 2022 23:37:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=FKBmITwflNjUMeSv3iJ/EBya5U2H6wfrJ0UankXXrIY=; b=iaSXXv02hv6mVartLw/vJRJMdyzu27BLLFj+bFdce6uQZpgMhi/BKGkI80XrTI2VVJ VMmlVq+jybGea1ixd2LtrVOG90SjMlyHod6EV7zOZ8DSjYCd3g4mJO0GQ5hoqjwczyIm tqG4PlbVuGOdqR5t3f84tNWGWTunQ6RIt6C6VcozPvOd3hghcpgAf9aYeJJZdp4ep7OB TIMy1oFvfnyxkb8/DxkSQh1RabpV+s86A44PSpAIXaBMqU7kz4eFcCg3U8IYUKnheEwt Fw3XjGwcSAggeN+c3ieyv47l2gKsE2ssL18VPcSvpl8qAva3008HOifk8f05o4ht+69H udKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=FKBmITwflNjUMeSv3iJ/EBya5U2H6wfrJ0UankXXrIY=; b=a3IyLhlwJP7VTqDrKB+GkkyNmCm/Ulaz6I79zuq26uClwSAxuFSoKsfpoEvpp/nwh4 IhA8BGKz60q38YWQUxoVHvuoH2eWFqls1W3EI1LopxDtju9kC5eGwXXTDn8pTROC/rNb urh/lwkJwgkm59nUklopwfuTJACV0GospRCZdNT2cTLNPPmM0OWOh3wf5vCmYmGHGHeG 9mKzGkAazvuuiaRsJt3wzsEjfCO9tDQf6U3h1C1hNd0WBwMPaOsqP4uYS9PSa6A9LtPv kuTrCbgOxLAN3kaI+KYYOLdmA1GjMAtz8R7GJVtKUzgx70j0j1275bSdgiUvWu2LsyFp 4L/A== X-Gm-Message-State: AJIora9T+l9P5mLEwNMnj/iXnvffFLw+ItA/KTXqpaHu612O0hrQWb11 vNFQAsr91MZ7VsXI9D5/4ygFmeCoi74q X-Google-Smtp-Source: AGRyM1v6cbe/lH7fDBMgXBU+//2Bqo3UkfQsnjZQoMzONHQ9akAApo48c55I5jImrL+qgs99kwLDocP5ByQw X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:e8fe:2a8e:e0f6:318d]) (user=irogers job=sendgmr) by 2002:a81:70e:0:b0:31c:8204:26ac with SMTP id 14-20020a81070e000000b0031c820426acmr13881197ywh.175.1657867063812; Thu, 14 Jul 2022 23:37:43 -0700 (PDT) Date: Thu, 14 Jul 2022 23:36:50 -0700 In-Reply-To: <20220715063653.3203761-1-irogers@google.com> Message-Id: <20220715063653.3203761-13-irogers@google.com> Mime-Version: 1.0 References: <20220715063653.3203761-1-irogers@google.com> X-Mailer: git-send-email 2.37.0.170.g444d1eabd0-goog Subject: [PATCH v1 12/15] perf pmu-events: Don't assume pmu_event is an array From: Ian Rogers To: John Garry , Will Deacon , James Clark , Mike Leach , Leo Yan , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Andi Kleen , Zhengjun Xing , Ravi Bangoria , Kan Liang , Adrian Hunter , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-perf-users@vger.kernel.org Cc: Stephane Eranian , Ian Rogers X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220715_073747_736860_A905DD1D X-CRM114-Status: GOOD ( 21.68 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Current code assumes that a struct pmu_event can be iterated over forward until a NULL pmu_event is encountered. This makes it difficult to refactor pmu_event. Add a loop function taking a callback function that's passed the struct pmu_event. This way the pmu_event is only needed for one element and not an entire array. Switch existing code iterating over the pmu_event arrays to use the new loop function pmu_events_table_for_each_event. Signed-off-by: Ian Rogers --- tools/perf/pmu-events/empty-pmu-events.c | 34 +++-- tools/perf/pmu-events/jevents.py | 34 +++-- tools/perf/pmu-events/pmu-events.h | 3 + tools/perf/tests/pmu-events.c | 136 +++++++++-------- tools/perf/util/metricgroup.c | 181 ++++++++++++++++------- tools/perf/util/pmu.c | 65 ++++---- tools/perf/util/s390-sample-raw.c | 42 ++++-- 7 files changed, 313 insertions(+), 182 deletions(-) diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c index 028f44efe48d..bee1967baa2b 100644 --- a/tools/perf/pmu-events/empty-pmu-events.c +++ b/tools/perf/pmu-events/empty-pmu-events.c @@ -247,6 +247,20 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { }, }; +int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, + void *data) +{ + for (const struct pmu_event *pe = &table[0]; + pe->name || pe->metric_group || pe->metric_name; + pe++) { + int ret = fn(pe, table, data); + + if (ret) + return ret; + } + return 0; +} + const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu) { const struct pmu_event *table = NULL; @@ -291,14 +305,10 @@ int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->table; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } @@ -319,14 +329,10 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; tables->name; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py index 800db6364078..3cb8a196a76d 100755 --- a/tools/perf/pmu-events/jevents.py +++ b/tools/perf/pmu-events/jevents.py @@ -410,6 +410,20 @@ static const struct pmu_sys_events pmu_sys_event_tables[] = { \t}, }; +int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, + void *data) +{ + for (const struct pmu_event *pe = &table[0]; + pe->name || pe->metric_group || pe->metric_name; + pe++) { + int ret = fn(pe, table, data); + + if (ret) + return ret; + } + return 0; +} + const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu) { const struct pmu_event *table = NULL; @@ -453,14 +467,10 @@ int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_events_map *tables = &pmu_events_map[0]; tables->table; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } @@ -481,14 +491,10 @@ int pmu_for_each_sys_event(pmu_event_iter_fn fn, void *data) for (const struct pmu_sys_events *tables = &pmu_sys_event_tables[0]; tables->name; tables++) { - for (const struct pmu_event *pe = &tables->table[0]; - pe->name || pe->metric_group || pe->metric_name; - pe++) { - int ret = fn(pe, &tables->table[0], data); + int ret = pmu_events_table_for_each_event(tables->table, fn, data); - if (ret) - return ret; - } + if (ret) + return ret; } return 0; } diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h index 485e730f9922..70672842f77f 100644 --- a/tools/perf/pmu-events/pmu-events.h +++ b/tools/perf/pmu-events/pmu-events.h @@ -34,6 +34,9 @@ typedef int (*pmu_event_iter_fn)(const struct pmu_event *pe, const struct pmu_event *table, void *data); +int pmu_events_table_for_each_event(const struct pmu_event *table, pmu_event_iter_fn fn, + void *data); + const struct pmu_event *perf_pmu__find_table(struct perf_pmu *pmu); const struct pmu_event *find_core_events_table(const char *arch, const char *cpuid); int pmu_for_each_core_event(pmu_event_iter_fn fn, void *data); diff --git a/tools/perf/tests/pmu-events.c b/tools/perf/tests/pmu-events.c index ccbf1057ba4c..a9808932f9b5 100644 --- a/tools/perf/tests/pmu-events.c +++ b/tools/perf/tests/pmu-events.c @@ -423,84 +423,104 @@ static int compare_alias_to_test_event(struct perf_pmu_alias *alias, return 0; } -/* Verify generated events from pmu-events.c are as expected */ -static int test__pmu_event_table(struct test_suite *test __maybe_unused, - int subtest __maybe_unused) +static int test__pmu_event_table_core_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *data) { - const struct pmu_event *sys_event_tables = find_sys_events_table("pme_test_soc_sys"); - const struct pmu_event *table = find_core_events_table("testarch", "testcpu"); - int map_events = 0, expected_events; + int *map_events = data; + struct perf_pmu_test_event const **test_event_table; + bool found = false; - /* ignore 3x sentinels */ - expected_events = ARRAY_SIZE(core_events) + - ARRAY_SIZE(uncore_events) + - ARRAY_SIZE(sys_events) - 3; + if (!pe->name) + return 0; - if (!table || !sys_event_tables) - return -1; + if (pe->pmu) + test_event_table = &uncore_events[0]; + else + test_event_table = &core_events[0]; - for (; table->name; table++) { - struct perf_pmu_test_event const **test_event_table; - bool found = false; + for (; *test_event_table; test_event_table++) { + struct perf_pmu_test_event const *test_event = *test_event_table; + struct pmu_event const *event = &test_event->event; - if (table->pmu) - test_event_table = &uncore_events[0]; - else - test_event_table = &core_events[0]; + if (strcmp(pe->name, event->name)) + continue; + found = true; + (*map_events)++; - for (; *test_event_table; test_event_table++) { - struct perf_pmu_test_event const *test_event = *test_event_table; - struct pmu_event const *event = &test_event->event; + if (compare_pmu_events(pe, event)) + return -1; - if (strcmp(table->name, event->name)) - continue; - found = true; - map_events++; + pr_debug("testing event table %s: pass\n", pe->name); + } + if (!found) { + pr_err("testing event table: could not find event %s\n", pe->name); + return -1; + } + return 0; +} - if (compare_pmu_events(table, event)) - return -1; +static int test__pmu_event_table_sys_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *data) +{ + int *map_events = data; + struct perf_pmu_test_event const **test_event_table; + bool found = false; - pr_debug("testing event table %s: pass\n", table->name); - } + test_event_table = &sys_events[0]; - if (!found) { - pr_err("testing event table: could not find event %s\n", - table->name); - return -1; - } - } + for (; *test_event_table; test_event_table++) { + struct perf_pmu_test_event const *test_event = *test_event_table; + struct pmu_event const *event = &test_event->event; - for (table = sys_event_tables; table->name; table++) { - struct perf_pmu_test_event const **test_event_table; - bool found = false; + if (strcmp(pe->name, event->name)) + continue; + found = true; + (*map_events)++; - test_event_table = &sys_events[0]; + if (compare_pmu_events(pe, event)) + return TEST_FAIL; - for (; *test_event_table; test_event_table++) { - struct perf_pmu_test_event const *test_event = *test_event_table; - struct pmu_event const *event = &test_event->event; + pr_debug("testing sys event table %s: pass\n", pe->name); + } + if (!found) { + pr_debug("testing sys event table: could not find event %s\n", pe->name); + return TEST_FAIL; + } + return TEST_OK; +} - if (strcmp(table->name, event->name)) - continue; - found = true; - map_events++; +/* Verify generated events from pmu-events.c are as expected */ +static int test__pmu_event_table(struct test_suite *test __maybe_unused, + int subtest __maybe_unused) +{ + const struct pmu_event *sys_event_table = find_sys_events_table("pme_test_soc_sys"); + const struct pmu_event *table = find_core_events_table("testarch", "testcpu"); + int map_events = 0, expected_events, err; - if (compare_pmu_events(table, event)) - return -1; + /* ignore 3x sentinels */ + expected_events = ARRAY_SIZE(core_events) + + ARRAY_SIZE(uncore_events) + + ARRAY_SIZE(sys_events) - 3; - pr_debug("testing sys event table %s: pass\n", table->name); - } - if (!found) { - pr_debug("testing event table: could not find event %s\n", - table->name); - return -1; - } - } + if (!table || !sys_event_table) + return -1; + + err = pmu_events_table_for_each_event(table, test__pmu_event_table_core_callback, + &map_events); + if (err) + return err; + + err = pmu_events_table_for_each_event(sys_event_table, test__pmu_event_table_sys_callback, + &map_events); + if (err) + return err; if (map_events != expected_events) { pr_err("testing event table: found %d, but expected %d\n", map_events, expected_events); - return -1; + return TEST_FAIL; } return 0; diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 680f7c63838d..f702b73a7609 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -538,12 +538,40 @@ static int metricgroup__print_sys_event_iter(const struct pmu_event *pe, d->details, d->groups, d->metriclist); } +struct metricgroup_print_data { + const char *pmu_name; + struct strlist *metriclist; + char *filter; + struct rblist *groups; + bool metricgroups; + bool raw; + bool details; +}; + +static int metricgroup__print_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct metricgroup_print_data *data = vdata; + + if (!pe->metric_expr) + return 0; + + if (data->pmu_name && perf_pmu__is_hybrid(pe->pmu) && strcmp(data->pmu_name, pe->pmu)) + return 0; + + return metricgroup__print_pmu_event(pe, data->metricgroups, data->filter, + data->raw, data->details, data->groups, + data->metriclist); +} + void metricgroup__print(bool metrics, bool metricgroups, char *filter, bool raw, bool details, const char *pmu_name) { struct rblist groups; struct rb_node *node, *next; struct strlist *metriclist = NULL; + const struct pmu_event *table; if (!metricgroups) { metriclist = strlist__new(NULL, NULL); @@ -555,22 +583,22 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, groups.node_new = mep_new; groups.node_cmp = mep_cmp; groups.node_delete = mep_delete; - for (const struct pmu_event *pe = pmu_events_map__find(); pe; pe++) { + table = pmu_events_map__find(); + if (table) { + struct metricgroup_print_data data = { + .pmu_name = pmu_name, + .metriclist = metriclist, + .metricgroups = metricgroups, + .filter = filter, + .raw = raw, + .details = details, + .groups = &groups, + }; - if (!pe->name && !pe->metric_group && !pe->metric_name) - break; - if (!pe->metric_expr) - continue; - if (pmu_name && perf_pmu__is_hybrid(pe->pmu) && - strcmp(pmu_name, pe->pmu)) { - continue; - } - if (metricgroup__print_pmu_event(pe, metricgroups, filter, - raw, details, &groups, - metriclist) < 0) - return; + pmu_events_table_for_each_event(table, + metricgroup__print_callback, + &data); } - { struct metricgroup_iter_data data = { .fn = metricgroup__print_sys_event_iter, @@ -1043,30 +1071,35 @@ static int __add_metric(struct list_head *metric_list, return ret; } -#define table_for_each_event(__pe, __idx, __table) \ - if (__table) \ - for (__idx = 0, __pe = &__table[__idx]; \ - __pe->name || __pe->metric_group || __pe->metric_name; \ - __pe = &__table[++__idx]) +struct metricgroup__find_metric_data { + const char *metric; + const struct pmu_event *pe; +}; + +static int metricgroup__find_metric_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct metricgroup__find_metric_data *data = vdata; + + if (!match_metric(pe->metric_name, data->metric)) + return 0; -#define table_for_each_metric(__pe, __idx, __table, __metric) \ - table_for_each_event(__pe, __idx, __table) \ - if (__pe->metric_expr && \ - (match_metric(__pe->metric_group, __metric) || \ - match_metric(__pe->metric_name, __metric))) + data->pe = pe; + return -1; +} const struct pmu_event *metricgroup__find_metric(const char *metric, const struct pmu_event *table) { - const struct pmu_event *pe; - int i; + struct metricgroup__find_metric_data data = { + .metric = metric, + .pe = NULL, + }; - table_for_each_event(pe, i, table) { - if (match_metric(pe->metric_name, metric)) - return pe; - } + pmu_events_table_for_each_event(table, metricgroup__find_metric_callback, &data); - return NULL; + return data.pe; } static int add_metric(struct list_head *metric_list, @@ -1151,6 +1184,33 @@ static int metric_list_cmp(void *priv __maybe_unused, const struct list_head *l, return right_count - left_count; } +struct metricgroup__add_metric_data { + struct list_head *list; + const char *metric_name; + const char *modifier; + bool metric_no_group; + bool has_match; +}; + +static int metricgroup__add_metric_callback(const struct pmu_event *pe, + const struct pmu_event *table, + void *vdata) +{ + struct metricgroup__add_metric_data *data = vdata; + int ret = 0; + + if (pe->metric_expr && + (match_metric(pe->metric_group, data->metric_name) || + match_metric(pe->metric_name, data->metric_name))) { + + data->has_match = true; + ret = add_metric(data->list, pe, data->modifier, data->metric_no_group, + /*root_metric=*/NULL, + /*visited_metrics=*/NULL, table); + } + return ret; +} + /** * metricgroup__add_metric - Find and add a metric, or a metric group. * @metric_name: The name of the metric or metric group. For example, "IPC" @@ -1169,24 +1229,29 @@ static int metricgroup__add_metric(const char *metric_name, const char *modifier struct list_head *metric_list, const struct pmu_event *table) { - const struct pmu_event *pe; LIST_HEAD(list); - int i, ret; + int ret; bool has_match = false; - /* - * Iterate over all metrics seeing if metric matches either the name or - * group. When it does add the metric to the list. - */ - table_for_each_metric(pe, i, table, metric_name) { - has_match = true; - ret = add_metric(&list, pe, modifier, metric_no_group, - /*root_metric=*/NULL, - /*visited_metrics=*/NULL, table); + { + struct metricgroup__add_metric_data data = { + .list = &list, + .metric_name = metric_name, + .modifier = modifier, + .metric_no_group = metric_no_group, + .has_match = false, + }; + /* + * Iterate over all metrics seeing if metric matches either the + * name or group. When it does add the metric to the list. + */ + ret = pmu_events_table_for_each_event(table, metricgroup__add_metric_callback, + &data); if (ret) goto out; - } + has_match = data.has_match; + } { struct metricgroup_iter_data data = { .fn = metricgroup__add_metric_sys_event_iter, @@ -1602,26 +1667,30 @@ int metricgroup__parse_groups_test(struct evlist *evlist, metric_no_merge, &perf_pmu__fake, metric_events, table); } +static int metricgroup__has_metric_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + const char *metric = vdata; + + if (!pe->metric_expr) + return 0; + + if (match_metric(pe->metric_name, metric)) + return 1; + + return 0; +} + bool metricgroup__has_metric(const char *metric) { const struct pmu_event *table = pmu_events_map__find(); - const struct pmu_event *pe; - int i; if (!table) return false; - for (i = 0; ; i++) { - pe = &table[i]; - - if (!pe->name && !pe->metric_group && !pe->metric_name) - break; - if (!pe->metric_expr) - continue; - if (match_metric(pe->metric_name, metric)) - return true; - } - return false; + return pmu_events_table_for_each_event(table, metricgroup__has_metric_callback, + (void *)metric) ? true : false; } int metricgroup__copy_metric_events(struct evlist *evlist, struct cgroup *cgrp, diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index 893cc0ff7758..7398a277c742 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c @@ -791,6 +791,36 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) return res; } +struct pmu_add_cpu_aliases_map_data { + struct list_head *head; + const char *name; + const char *cpu_name; + struct perf_pmu *pmu; +}; + +static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct pmu_add_cpu_aliases_map_data *data = vdata; + const char *pname = pe->pmu ? pe->pmu : data->cpu_name; + + if (!pe->name) + return 0; + + if (data->pmu->is_uncore && pmu_uncore_alias_match(pname, data->name)) + goto new_alias; + + if (strcmp(pname, data->name)) + return 0; + +new_alias: + /* need type casts to override 'const' */ + __perf_pmu__new_alias(data->head, NULL, (char *)pe->name, (char *)pe->desc, + (char *)pe->event, pe); + return 0; +} + /* * From the pmu_events_map, find the table of PMU events that corresponds * to the current running CPU. Then, add all PMU events from that table @@ -799,35 +829,14 @@ bool pmu_uncore_alias_match(const char *pmu_name, const char *name) void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, const struct pmu_event *table) { - int i; - const char *name = pmu->name; - /* - * Found a matching PMU events table. Create aliases - */ - i = 0; - while (1) { - const char *cpu_name = is_arm_pmu_core(name) ? name : "cpu"; - const struct pmu_event *pe = &table[i++]; - const char *pname = pe->pmu ? pe->pmu : cpu_name; - - if (!pe->name) { - if (pe->metric_group || pe->metric_name) - continue; - break; - } - - if (pmu->is_uncore && pmu_uncore_alias_match(pname, name)) - goto new_alias; - - if (strcmp(pname, name)) - continue; + struct pmu_add_cpu_aliases_map_data data = { + .head = head, + .name = pmu->name, + .cpu_name = is_arm_pmu_core(pmu->name) ? pmu->name : "cpu", + .pmu = pmu, + }; -new_alias: - /* need type casts to override 'const' */ - __perf_pmu__new_alias(head, NULL, (char *)pe->name, - (char *)pe->desc, (char *)pe->event, - pe); - } + pmu_events_table_for_each_event(table, pmu_add_cpu_aliases_map_callback, &data); } static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) diff --git a/tools/perf/util/s390-sample-raw.c b/tools/perf/util/s390-sample-raw.c index 1ecb718fc0eb..b1c052c176bb 100644 --- a/tools/perf/util/s390-sample-raw.c +++ b/tools/perf/util/s390-sample-raw.c @@ -129,6 +129,28 @@ static int get_counterset_start(int setnr) } } +struct get_counter_name_data { + int wanted; + const char *result; +}; + +static int get_counter_name_callback(const struct pmu_event *evp, + const struct pmu_event *table __maybe_unused, + void *vdata) +{ + struct get_counter_name_data *data = vdata; + int rc, event_nr; + + if (evp->name == NULL || evp->event == NULL) + return 0; + rc = sscanf(evp->event, "event=%x", &event_nr); + if (rc == 1 && event_nr == data->wanted) { + data->result = evp->name; + return 1; /* Terminate the search. */ + } + return 0; +} + /* Scan the PMU table and extract the logical name of a counter from the * PMU events table. Input is the counter set and counter number with in the * set. Construct the event number and use this as key. If they match return @@ -137,20 +159,16 @@ static int get_counterset_start(int setnr) */ static const char *get_counter_name(int set, int nr, const struct pmu_event *table) { - int rc, event_nr, wanted = get_counterset_start(set) + nr; + struct get_counter_name_data data = { + .wanted = get_counterset_start(set) + nr, + .result = NULL, + }; - if (table) { - const struct pmu_event *evp = table; + if (!table) + return NULL; - for (; evp->name || evp->event || evp->desc; ++evp) { - if (evp->name == NULL || evp->event == NULL) - continue; - rc = sscanf(evp->event, "event=%x", &event_nr); - if (rc == 1 && event_nr == wanted) - return evp->name; - } - } - return NULL; + pmu_events_table_for_each_event(table, get_counter_name_callback, &data); + return data.result; } static void s390_cpumcfdg_dump(struct perf_sample *sample) -- 2.37.0.170.g444d1eabd0-goog _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel