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.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/tools/perf/util/metricgroup.c b/tools/perf/util/metricgroup.c
index 699e020737d9..d8164574cb16 100644
--- a/tools/perf/util/metricgroup.c
+++ b/tools/perf/util/metricgroup.c
@@ -17,7 +17,7 @@
#include "pmu-events/pmu-events.h"
#include "strlist.h"
#include <assert.h>
-#include <ctype.h>
+#include <linux/ctype.h>
struct metric_event *metricgroup__lookup(struct rblist *metric_events,
struct perf_evsel *evsel,
@@ -85,26 +85,49 @@ struct egroup {
const char *metric_expr;
};
-static struct perf_evsel *find_evsel(struct perf_evlist *perf_evlist,
- const char **ids,
- int idnum,
- struct perf_evsel **metric_events)
+static bool record_evsel(int *ind, struct perf_evsel **start,
+ int idnum,
+ struct perf_evsel **metric_events,
+ struct perf_evsel *ev)
+{
+ 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;
evlist__for_each_entry (perf_evlist, ev) {
+ if (ev->collect_stat)
+ continue;
if (!strcmp(ev->name, ids[ind])) {
- metric_events[ind] = ev;
- if (ind == 0)
- start = ev;
- if (++ind == idnum) {
- metric_events[ind] = NULL;
+ if (record_evsel(&ind, &start, idnum,
+ metric_events, ev))
return start;
- }
} 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;
+ }
}
}
/*
@@ -134,8 +157,8 @@ static int metricgroup__setup_events(struct list_head *groups,
ret = -ENOMEM;
break;
}
- evsel = find_evsel(perf_evlist, eg->ids, eg->idnum,
- metric_events);
+ evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum,
+ metric_events);
if (!evsel) {
pr_debug("Cannot resolve %s: %s\n",
eg->metric_name, eg->metric_expr);
@@ -308,10 +331,9 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
struct mep *me;
char *s;
+ g = skip_spaces(g);
if (*g == 0)
g = "No_group";
- while (isspace(*g))
- g++;
if (filter && !strstr(g, filter))
continue;
if (raw)
@@ -353,7 +375,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
struct mep *me = container_of(node, struct mep, nd);
if (metricgroups)
- printf("%s%s%s", me->name, metrics ? ":" : "", raw ? " " : "\n");
+ printf("%s%s%s", me->name, metrics && !raw ? ":" : "", raw ? " " : "\n");
if (metrics)
metricgroup__print_strlist(me->metrics, raw);
next = rb_next(node);
@@ -387,6 +409,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
const char **ids;
int idnum;
struct egroup *eg;
+ bool no_group = false;
pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
@@ -397,11 +420,25 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
strbuf_addf(events, ",");
for (j = 0; j < idnum; j++) {
pr_debug("found event %s\n", ids[j]);
+ /*
+ * Duration time maps to a software event and can make
+ * groups not count. Always use it outside a
+ * group.
+ */
+ if (!strcmp(ids[j], "duration_time")) {
+ if (j > 0)
+ strbuf_addf(events, "}:W,");
+ strbuf_addf(events, "duration_time");
+ no_group = true;
+ continue;
+ }
strbuf_addf(events, "%s%s",
- j == 0 ? "{" : ",",
+ j == 0 || no_group ? "{" : ",",
ids[j]);
+ no_group = false;
}
- strbuf_addf(events, "}:W");
+ if (!no_group)
+ strbuf_addf(events, "}:W");
eg = malloc(sizeof(struct egroup));
if (!eg) {