diff options
Diffstat (limited to 'tools/perf/util/metricgroup.c')
-rw-r--r-- | tools/perf/util/metricgroup.c | 110 |
1 files changed, 60 insertions, 50 deletions
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c index 416a9015405e..a7c0424dbda3 100644 --- a/tools/perf/util/metricgroup.c +++ b/tools/perf/util/metricgroup.c @@ -6,22 +6,25 @@ /* Manage metrics and groups of metrics from JSON files */ #include "metricgroup.h" +#include "debug.h" #include "evlist.h" +#include "evsel.h" #include "strbuf.h" #include "pmu.h" #include "expr.h" #include "rblist.h" #include <string.h> -#include <stdbool.h> #include <errno.h> #include "pmu-events/pmu-events.h" #include "strlist.h" #include <assert.h> #include <linux/ctype.h> +#include <linux/string.h> #include <linux/zalloc.h> +#include <subcmd/parse-options.h> struct metric_event *metricgroup__lookup(struct rblist *metric_events, - struct perf_evsel *evsel, + struct evsel *evsel, bool create) { struct rb_node *nd; @@ -84,63 +87,68 @@ struct egroup { const char **ids; const char *metric_name; const char *metric_expr; + const char *metric_unit; }; -static bool record_evsel(int *ind, struct perf_evsel **start, - int idnum, - struct perf_evsel **metric_events, - struct perf_evsel *ev) +static struct evsel *find_evsel_group(struct evlist *perf_evlist, + const char **ids, + int idnum, + struct evsel **metric_events) { - metric_events[*ind] = ev; - if (*ind == 0) - *start = ev; - if (++*ind == idnum) { - metric_events[*ind] = NULL; - return true; - } - return false; -} - -static struct perf_evsel *find_evsel_group(struct perf_evlist *perf_evlist, - const char **ids, - int idnum, - struct perf_evsel **metric_events) -{ - struct perf_evsel *ev, *start = NULL; - int ind = 0; + struct evsel *ev; + int i = 0; + bool leader_found; evlist__for_each_entry (perf_evlist, ev) { - if (ev->collect_stat) - continue; - if (!strcmp(ev->name, ids[ind])) { - if (record_evsel(&ind, &start, idnum, - metric_events, ev)) - return start; + if (!strcmp(ev->name, ids[i])) { + if (!metric_events[i]) + metric_events[i] = ev; } else { - /* - * We saw some other event that is not - * in our list of events. Discard - * the whole match and start again. - */ - ind = 0; - start = NULL; - if (!strcmp(ev->name, ids[ind])) { - if (record_evsel(&ind, &start, idnum, - metric_events, ev)) - return start; + if (++i == idnum) { + /* Discard the whole match and start again */ + i = 0; + memset(metric_events, 0, + sizeof(struct evsel *) * idnum); + continue; + } + + if (!strcmp(ev->name, ids[i])) + metric_events[i] = ev; + else { + /* Discard the whole match and start again */ + i = 0; + memset(metric_events, 0, + sizeof(struct evsel *) * idnum); + continue; } } } - /* - * This can happen when an alias expands to multiple - * events, like for uncore events. - * We don't support this case for now. - */ - return NULL; + + if (i != idnum - 1) { + /* Not whole match */ + return NULL; + } + + metric_events[idnum] = NULL; + + for (i = 0; i < idnum; i++) { + leader_found = false; + evlist__for_each_entry(perf_evlist, ev) { + if (!leader_found && (ev == metric_events[i])) + leader_found = true; + + if (leader_found && + !strcmp(ev->name, metric_events[i]->name)) { + ev->metric_leader = metric_events[i]; + } + } + } + + return metric_events[0]; } static int metricgroup__setup_events(struct list_head *groups, - struct perf_evlist *perf_evlist, + struct evlist *perf_evlist, struct rblist *metric_events_list) { struct metric_event *me; @@ -148,10 +156,10 @@ static int metricgroup__setup_events(struct list_head *groups, int i = 0; int ret = 0; struct egroup *eg; - struct perf_evsel *evsel; + struct evsel *evsel; list_for_each_entry (eg, groups, nd) { - struct perf_evsel **metric_events; + struct evsel **metric_events; metric_events = calloc(sizeof(void *), eg->idnum + 1); if (!metric_events) { @@ -179,6 +187,7 @@ static int metricgroup__setup_events(struct list_head *groups, } expr->metric_expr = eg->metric_expr; expr->metric_name = eg->metric_name; + expr->metric_unit = eg->metric_unit; expr->metric_events = metric_events; list_add(&expr->nd, &me->head); } @@ -450,6 +459,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, eg->idnum = idnum; eg->metric_name = pe->metric_name; eg->metric_expr = pe->metric_expr; + eg->metric_unit = pe->unit; list_add_tail(&eg->nd, group_list); ret = 0; } @@ -502,7 +512,7 @@ int metricgroup__parse_groups(const struct option *opt, struct rblist *metric_events) { struct parse_events_error parse_error; - struct perf_evlist *perf_evlist = *(struct perf_evlist **)opt->value; + struct evlist *perf_evlist = *(struct evlist **)opt->value; struct strbuf extra_events; LIST_HEAD(group_list); int ret; |