summaryrefslogtreecommitdiff
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.c110
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;