summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/metricgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/metricgroup.c')
-rw-r--r--tools/perf/util/metricgroup.c258
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);