diff options
Diffstat (limited to 'tools/perf/util/metricgroup.c')
-rw-r--r-- | tools/perf/util/metricgroup.c | 275 |
1 files changed, 173 insertions, 102 deletions
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 8f7baeabc5cf..464475fd6b9a 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -502,14 +502,14 @@ struct metricgroup_print_sys_idata { bool details; }; -typedef int (*metricgroup_sys_event_iter_fn)(const struct pmu_event *pe, void *); - struct metricgroup_iter_data { - metricgroup_sys_event_iter_fn fn; + pmu_event_iter_fn fn; void *data; }; -static int metricgroup__sys_event_iter(const struct pmu_event *pe, void *data) +static int metricgroup__sys_event_iter(const struct pmu_event *pe, + const struct pmu_events_table *table, + void *data) { struct metricgroup_iter_data *d = data; struct perf_pmu *pmu = NULL; @@ -522,13 +522,15 @@ static int metricgroup__sys_event_iter(const struct pmu_event *pe, void *data) if (!pmu->id || strcmp(pmu->id, pe->compat)) continue; - return d->fn(pe, d->data); + return d->fn(pe, table, d->data); } return 0; } -static int metricgroup__print_sys_event_iter(const struct pmu_event *pe, void *data) +static int metricgroup__print_sys_event_iter(const struct pmu_event *pe, + const struct pmu_events_table *table __maybe_unused, + void *data) { struct metricgroup_print_sys_idata *d = data; @@ -536,15 +538,40 @@ static int metricgroup__print_sys_event_iter(const struct pmu_event *pe, void *d 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_events_table *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) { - const struct pmu_events_map *map = pmu_events_map__find(); - const struct pmu_event *pe; - int i; struct rblist groups; struct rb_node *node, *next; struct strlist *metriclist = NULL; + const struct pmu_events_table *table; if (!metricgroups) { metriclist = strlist__new(NULL, NULL); @@ -556,23 +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 (i = 0; map; i++) { - pe = &map->table[i]; + table = pmu_events_table__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, @@ -850,16 +876,20 @@ struct metricgroup_add_iter_data { bool metric_no_group; struct metric *root_metric; const struct visited_metric *visited; - const struct pmu_events_map *map; + const struct pmu_events_table *table; }; +static bool metricgroup__find_metric(const char *metric, + const struct pmu_events_table *table, + struct pmu_event *pe); + static int add_metric(struct list_head *metric_list, const struct pmu_event *pe, const char *modifier, bool metric_no_group, struct metric *root_metric, const struct visited_metric *visited, - const struct pmu_events_map *map); + const struct pmu_events_table *table); /** * resolve_metric - Locate metrics within the root metric and recursively add @@ -874,7 +904,7 @@ static int add_metric(struct list_head *metric_list, * metrics. When adding a root this argument is NULL. * @visited: A singly linked list of metric names being added that is used to * detect recursion. - * @map: The map that is searched for metrics, most commonly the table for the + * @table: The table that is searched for metrics, most commonly the table for the * architecture perf is running upon. */ static int resolve_metric(struct list_head *metric_list, @@ -882,13 +912,13 @@ static int resolve_metric(struct list_head *metric_list, bool metric_no_group, struct metric *root_metric, const struct visited_metric *visited, - const struct pmu_events_map *map) + const struct pmu_events_table *table) { struct hashmap_entry *cur; size_t bkt; struct to_resolve { /* The metric to resolve. */ - const struct pmu_event *pe; + struct pmu_event pe; /* * The key in the IDs map, this may differ from in case, * etc. from pe->metric_name. @@ -902,16 +932,15 @@ static int resolve_metric(struct list_head *metric_list, * the pending array. */ hashmap__for_each_entry(root_metric->pctx->ids, cur, bkt) { - const struct pmu_event *pe; + struct pmu_event pe; - pe = metricgroup__find_metric(cur->key, map); - if (pe) { + if (metricgroup__find_metric(cur->key, table, &pe)) { pending = realloc(pending, (pending_cnt + 1) * sizeof(struct to_resolve)); if (!pending) return -ENOMEM; - pending[pending_cnt].pe = pe; + memcpy(&pending[pending_cnt].pe, &pe, sizeof(pe)); pending[pending_cnt].key = cur->key; pending_cnt++; } @@ -926,8 +955,8 @@ static int resolve_metric(struct list_head *metric_list, * context. */ for (i = 0; i < pending_cnt; i++) { - ret = add_metric(metric_list, pending[i].pe, modifier, metric_no_group, - root_metric, visited, map); + ret = add_metric(metric_list, &pending[i].pe, modifier, metric_no_group, + root_metric, visited, table); if (ret) break; } @@ -950,7 +979,7 @@ static int resolve_metric(struct list_head *metric_list, * metrics. When adding a root this argument is NULL. * @visited: A singly linked list of metric names being added that is used to * detect recursion. - * @map: The map that is searched for metrics, most commonly the table for the + * @table: The table that is searched for metrics, most commonly the table for the * architecture perf is running upon. */ static int __add_metric(struct list_head *metric_list, @@ -960,7 +989,7 @@ static int __add_metric(struct list_head *metric_list, int runtime, struct metric *root_metric, const struct visited_metric *visited, - const struct pmu_events_map *map) + const struct pmu_events_table *table) { const struct visited_metric *vm; int ret; @@ -1032,7 +1061,7 @@ static int __add_metric(struct list_head *metric_list, } else { /* Resolve referenced metrics. */ ret = resolve_metric(metric_list, modifier, metric_no_group, root_metric, - &visited_node, map); + &visited_node, table); } if (ret) { @@ -1045,30 +1074,35 @@ static int __add_metric(struct list_head *metric_list, return ret; } -#define map_for_each_event(__pe, __idx, __map) \ - if (__map) \ - for (__idx = 0, __pe = &__map->table[__idx]; \ - __pe->name || __pe->metric_group || __pe->metric_name; \ - __pe = &__map->table[++__idx]) - -#define map_for_each_metric(__pe, __idx, __map, __metric) \ - map_for_each_event(__pe, __idx, __map) \ - if (__pe->metric_expr && \ - (match_metric(__pe->metric_group, __metric) || \ - match_metric(__pe->metric_name, __metric))) +struct metricgroup__find_metric_data { + const char *metric; + struct pmu_event *pe; +}; -const struct pmu_event *metricgroup__find_metric(const char *metric, - const struct pmu_events_map *map) +static int metricgroup__find_metric_callback(const struct pmu_event *pe, + const struct pmu_events_table *table __maybe_unused, + void *vdata) { - const struct pmu_event *pe; - int i; + struct metricgroup__find_metric_data *data = vdata; - map_for_each_event(pe, i, map) { - if (match_metric(pe->metric_name, metric)) - return pe; - } + if (!match_metric(pe->metric_name, data->metric)) + return 0; - return NULL; + memcpy(data->pe, pe, sizeof(*pe)); + return 1; +} + +static bool metricgroup__find_metric(const char *metric, + const struct pmu_events_table *table, + struct pmu_event *pe) +{ + struct metricgroup__find_metric_data data = { + .metric = metric, + .pe = pe, + }; + + return pmu_events_table_for_each_event(table, metricgroup__find_metric_callback, &data) + ? true : false; } static int add_metric(struct list_head *metric_list, @@ -1077,7 +1111,7 @@ static int add_metric(struct list_head *metric_list, bool metric_no_group, struct metric *root_metric, const struct visited_metric *visited, - const struct pmu_events_map *map) + const struct pmu_events_table *table) { int ret = 0; @@ -1085,7 +1119,7 @@ static int add_metric(struct list_head *metric_list, if (!strstr(pe->metric_expr, "?")) { ret = __add_metric(metric_list, pe, modifier, metric_no_group, 0, - root_metric, visited, map); + root_metric, visited, table); } else { int j, count; @@ -1098,14 +1132,15 @@ static int add_metric(struct list_head *metric_list, for (j = 0; j < count && !ret; j++) ret = __add_metric(metric_list, pe, modifier, metric_no_group, j, - root_metric, visited, map); + root_metric, visited, table); } return ret; } static int metricgroup__add_metric_sys_event_iter(const struct pmu_event *pe, - void *data) + const struct pmu_events_table *table __maybe_unused, + void *data) { struct metricgroup_add_iter_data *d = data; int ret; @@ -1114,7 +1149,7 @@ static int metricgroup__add_metric_sys_event_iter(const struct pmu_event *pe, return 0; ret = add_metric(d->metric_list, pe, d->modifier, d->metric_no_group, - d->root_metric, d->visited, d->map); + d->root_metric, d->visited, d->table); if (ret) goto out; @@ -1152,6 +1187,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_events_table *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" @@ -1162,32 +1224,37 @@ static int metric_list_cmp(void *priv __maybe_unused, const struct list_head *l, * global. Grouping is the default but due to multiplexing the * user may override. * @metric_list: The list that the metric or metric group are added to. - * @map: The map that is searched for metrics, most commonly the table for the + * @table: The table that is searched for metrics, most commonly the table for the * architecture perf is running upon. */ static int metricgroup__add_metric(const char *metric_name, const char *modifier, bool metric_no_group, struct list_head *metric_list, - const struct pmu_events_map *map) + const struct pmu_events_table *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. - */ - map_for_each_metric(pe, i, map, metric_name) { - has_match = true; - ret = add_metric(&list, pe, modifier, metric_no_group, - /*root_metric=*/NULL, - /*visited_metrics=*/NULL, map); + { + 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, @@ -1198,7 +1265,7 @@ static int metricgroup__add_metric(const char *metric_name, const char *modifier .metric_no_group = metric_no_group, .has_match = &has_match, .ret = &ret, - .map = map, + .table = table, }, }; @@ -1227,12 +1294,12 @@ out: * global. Grouping is the default but due to multiplexing the * user may override. * @metric_list: The list that metrics are added to. - * @map: The map that is searched for metrics, most commonly the table for the + * @table: The table that is searched for metrics, most commonly the table for the * architecture perf is running upon. */ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, struct list_head *metric_list, - const struct pmu_events_map *map) + const struct pmu_events_table *table) { char *list_itr, *list_copy, *metric_name, *modifier; int ret, count = 0; @@ -1249,7 +1316,7 @@ static int metricgroup__add_metric_list(const char *list, bool metric_no_group, ret = metricgroup__add_metric(metric_name, modifier, metric_no_group, metric_list, - map); + table); if (ret == -EINVAL) pr_err("Cannot find metric or group `%s'\n", metric_name); @@ -1440,7 +1507,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, bool metric_no_merge, struct perf_pmu *fake_pmu, struct rblist *metric_events_list, - const struct pmu_events_map *map) + const struct pmu_events_table *table) { struct evlist *combined_evlist = NULL; LIST_HEAD(metric_list); @@ -1451,7 +1518,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, if (metric_events_list->nr_entries == 0) metricgroup__rblist_init(metric_events_list); ret = metricgroup__add_metric_list(str, metric_no_group, - &metric_list, map); + &metric_list, table); if (ret) goto out; @@ -1586,43 +1653,47 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct evlist *perf_evlist = *(struct evlist **)opt->value; - const struct pmu_events_map *map = pmu_events_map__find(); + const struct pmu_events_table *table = pmu_events_table__find(); return parse_groups(perf_evlist, str, metric_no_group, - metric_no_merge, NULL, metric_events, map); + metric_no_merge, NULL, metric_events, table); } int metricgroup__parse_groups_test(struct evlist *evlist, - const struct pmu_events_map *map, + const struct pmu_events_table *table, const char *str, bool metric_no_group, bool metric_no_merge, struct rblist *metric_events) { return parse_groups(evlist, str, metric_no_group, - metric_no_merge, &perf_pmu__fake, metric_events, map); + metric_no_merge, &perf_pmu__fake, metric_events, table); +} + +static int metricgroup__has_metric_callback(const struct pmu_event *pe, + const struct pmu_events_table *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_events_map *map = pmu_events_map__find(); - const struct pmu_event *pe; - int i; + const struct pmu_events_table *table = pmu_events_table__find(); - if (!map) + if (!table) return false; - for (i = 0; ; i++) { - pe = &map->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, |