diff options
Diffstat (limited to 'tools/perf/util/metricgroup.c')
-rw-r--r-- | tools/perf/util/metricgroup.c | 258 |
1 files changed, 193 insertions, 65 deletions
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 060454a17293..ee94d3e8dd65 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -279,7 +279,9 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist, * when then group is left. */ if (!has_constraint && - ev->leader != metric_events[i]->leader) + ev->leader != metric_events[i]->leader && + !strcmp(ev->leader->pmu_name, + metric_events[i]->leader->pmu_name)) break; if (!strcmp(metric_events[i]->name, ev->name)) { set_bit(ev->idx, evlist_used); @@ -413,6 +415,12 @@ static bool match_metric(const char *n, const char *list) return false; } +static bool match_pe_metric(struct pmu_event *pe, const char *metric) +{ + return match_metric(pe->metric_group, metric) || + match_metric(pe->metric_name, metric); +} + struct mep { struct rb_node nd; const char *name; @@ -491,6 +499,115 @@ static void metricgroup__print_strlist(struct strlist *metrics, bool raw) putchar('\n'); } +static int metricgroup__print_pmu_event(struct pmu_event *pe, + bool metricgroups, char *filter, + bool raw, bool details, + struct rblist *groups, + struct strlist *metriclist) +{ + const char *g; + char *omg, *mg; + + g = pe->metric_group; + if (!g && pe->metric_name) { + if (pe->name) + return 0; + g = "No_group"; + } + + if (!g) + return 0; + + mg = strdup(g); + + if (!mg) + return -ENOMEM; + omg = mg; + while ((g = strsep(&mg, ";")) != NULL) { + struct mep *me; + char *s; + + g = skip_spaces(g); + if (*g == 0) + g = "No_group"; + if (filter && !strstr(g, filter)) + continue; + if (raw) + s = (char *)pe->metric_name; + else { + if (asprintf(&s, "%s\n%*s%s]", + pe->metric_name, 8, "[", pe->desc) < 0) + return -1; + if (details) { + if (asprintf(&s, "%s\n%*s%s]", + s, 8, "[", pe->metric_expr) < 0) + return -1; + } + } + + if (!s) + continue; + + if (!metricgroups) { + strlist__add(metriclist, s); + } else { + me = mep_lookup(groups, g); + if (!me) + continue; + strlist__add(me->metrics, s); + } + + if (!raw) + free(s); + } + free(omg); + + return 0; +} + +struct metricgroup_print_sys_idata { + struct strlist *metriclist; + char *filter; + struct rblist *groups; + bool metricgroups; + bool raw; + bool details; +}; + +typedef int (*metricgroup_sys_event_iter_fn)(struct pmu_event *pe, void *); + +struct metricgroup_iter_data { + metricgroup_sys_event_iter_fn fn; + void *data; +}; + +static int metricgroup__sys_event_iter(struct pmu_event *pe, void *data) +{ + struct metricgroup_iter_data *d = data; + struct perf_pmu *pmu = NULL; + + if (!pe->metric_expr || !pe->compat) + return 0; + + while ((pmu = perf_pmu__scan(pmu))) { + + if (!pmu->id || strcmp(pmu->id, pe->compat)) + continue; + + return d->fn(pe, d->data); + } + + return 0; +} + +static int metricgroup__print_sys_event_iter(struct pmu_event *pe, void *data) +{ + struct metricgroup_print_sys_idata *d = data; + + return metricgroup__print_pmu_event(pe, d->metricgroups, d->filter, d->raw, + d->details, d->groups, d->metriclist); +} + void metricgroup__print(bool metrics, bool metricgroups, char *filter, bool raw, bool details) { @@ -501,9 +618,6 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, struct rb_node *node, *next; struct strlist *metriclist = NULL; - if (!map) - return; - if (!metricgroups) { metriclist = strlist__new(NULL, NULL); if (!metriclist) @@ -514,67 +628,33 @@ 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; ; i++) { - const char *g; + for (i = 0; map; i++) { pe = &map->table[i]; if (!pe->name && !pe->metric_group && !pe->metric_name) break; if (!pe->metric_expr) continue; - g = pe->metric_group; - if (!g && pe->metric_name) { - if (pe->name) - continue; - g = "No_group"; - } - if (g) { - char *omg; - char *mg = strdup(g); - - if (!mg) - return; - omg = mg; - while ((g = strsep(&mg, ";")) != NULL) { - struct mep *me; - char *s; - - g = skip_spaces(g); - if (*g == 0) - g = "No_group"; - if (filter && !strstr(g, filter)) - continue; - if (raw) - s = (char *)pe->metric_name; - else { - if (asprintf(&s, "%s\n%*s%s]", - pe->metric_name, 8, "[", pe->desc) < 0) - return; - - if (details) { - if (asprintf(&s, "%s\n%*s%s]", - s, 8, "[", pe->metric_expr) < 0) - return; - } - } - - if (!s) - continue; + if (metricgroup__print_pmu_event(pe, metricgroups, filter, + raw, details, &groups, + metriclist) < 0) + return; + } - if (!metricgroups) { - strlist__add(metriclist, s); - } else { - me = mep_lookup(&groups, g); - if (!me) - continue; - strlist__add(me->metrics, s); - } + { + struct metricgroup_iter_data data = { + .fn = metricgroup__print_sys_event_iter, + .data = (void *) &(struct metricgroup_print_sys_idata){ + .metriclist = metriclist, + .metricgroups = metricgroups, + .filter = filter, + .raw = raw, + .details = details, + .groups = &groups, + }, + }; - if (!raw) - free(s); - } - free(omg); - } + pmu_for_each_sys_event(metricgroup__sys_event_iter, &data); } if (!filter || !rblist__empty(&groups)) { @@ -683,6 +763,16 @@ int __weak arch_get_runtimeparam(struct pmu_event *pe __maybe_unused) return 1; } +struct metricgroup_add_iter_data { + struct list_head *metric_list; + const char *metric; + struct metric **m; + struct expr_ids *ids; + int *ret; + bool *has_match; + bool metric_no_group; +}; + static int __add_metric(struct list_head *metric_list, struct pmu_event *pe, bool metric_no_group, @@ -792,10 +882,11 @@ static int __add_metric(struct list_head *metric_list, return 0; } -#define map_for_each_event(__pe, __idx, __map) \ - for (__idx = 0, __pe = &__map->table[__idx]; \ - __pe->name || __pe->metric_group || __pe->metric_name; \ - __pe = &__map->table[++__idx]) +#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) \ @@ -833,7 +924,7 @@ static int recursion_check(struct metric *m, const char *id, struct expr_id **pa if (ret) return ret; - p = data->parent; + p = expr_id_data__parent(data); while (p->parent) { if (!strcmp(p->id, id)) { @@ -854,7 +945,7 @@ static int recursion_check(struct metric *m, const char *id, struct expr_id **pa } p->id = strdup(id); - p->parent = data->parent; + p->parent = expr_id_data__parent(data); *parent = p; return p->id ? 0 : -ENOMEM; @@ -963,6 +1054,29 @@ static int add_metric(struct list_head *metric_list, return ret; } +static int metricgroup__add_metric_sys_event_iter(struct pmu_event *pe, + void *data) +{ + struct metricgroup_add_iter_data *d = data; + int ret; + + if (!match_pe_metric(pe, d->metric)) + return 0; + + ret = add_metric(d->metric_list, pe, d->metric_no_group, d->m, NULL, d->ids); + if (ret) + return ret; + + ret = resolve_metric(d->metric_no_group, + d->metric_list, NULL, d->ids); + if (ret) + return ret; + + *(d->has_match) = true; + + return *d->ret; +} + static int metricgroup__add_metric(const char *metric, bool metric_no_group, struct strbuf *events, struct list_head *metric_list, @@ -993,6 +1107,22 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, goto out; } + { + struct metricgroup_iter_data data = { + .fn = metricgroup__add_metric_sys_event_iter, + .data = (void *) &(struct metricgroup_add_iter_data) { + .metric_list = &list, + .metric = metric, + .metric_no_group = metric_no_group, + .m = &m, + .ids = &ids, + .has_match = &has_match, + .ret = &ret, + }, + }; + + pmu_for_each_sys_event(metricgroup__sys_event_iter, &data); + } /* End of pmu events. */ if (!has_match) { ret = -EINVAL; @@ -1119,8 +1249,6 @@ int metricgroup__parse_groups(const struct option *opt, struct evlist *perf_evlist = *(struct evlist **)opt->value; struct pmu_events_map *map = perf_pmu__find_map(NULL); - if (!map) - return 0; return parse_groups(perf_evlist, str, metric_no_group, metric_no_merge, NULL, metric_events, map); |