Merge tag 'topic/phy-compliance-2020-04-08' of git://anongit.freedesktop.org/drm...
[linux-2.6-microblaze.git] / tools / perf / util / metricgroup.c
index c3a8c70..926449a 100644 (file)
@@ -95,13 +95,16 @@ struct egroup {
 static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                                      const char **ids,
                                      int idnum,
-                                     struct evsel **metric_events)
+                                     struct evsel **metric_events,
+                                     bool *evlist_used)
 {
        struct evsel *ev;
-       int i = 0;
+       int i = 0, j = 0;
        bool leader_found;
 
        evlist__for_each_entry (perf_evlist, ev) {
+               if (evlist_used[j++])
+                       continue;
                if (!strcmp(ev->name, ids[i])) {
                        if (!metric_events[i])
                                metric_events[i] = ev;
@@ -109,22 +112,17 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                        if (i == idnum)
                                break;
                } else {
-                       if (i + 1 == 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;
+                       /* Discard the whole match and start again */
+                       i = 0;
+                       memset(metric_events, 0,
+                               sizeof(struct evsel *) * idnum);
+
+                       if (!strcmp(ev->name, ids[i])) {
+                               if (!metric_events[i])
+                                       metric_events[i] = ev;
+                               i++;
+                               if (i == idnum)
+                                       break;
                        }
                }
        }
@@ -146,7 +144,10 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                            !strcmp(ev->name, metric_events[i]->name)) {
                                ev->metric_leader = metric_events[i];
                        }
+                       j++;
                }
+               ev = metric_events[i];
+               evlist_used[ev->idx] = true;
        }
 
        return metric_events[0];
@@ -162,6 +163,13 @@ static int metricgroup__setup_events(struct list_head *groups,
        int ret = 0;
        struct egroup *eg;
        struct evsel *evsel;
+       bool *evlist_used;
+
+       evlist_used = calloc(perf_evlist->core.nr_entries, sizeof(bool));
+       if (!evlist_used) {
+               ret = -ENOMEM;
+               return ret;
+       }
 
        list_for_each_entry (eg, groups, nd) {
                struct evsel **metric_events;
@@ -172,7 +180,7 @@ static int metricgroup__setup_events(struct list_head *groups,
                        break;
                }
                evsel = find_evsel_group(perf_evlist, eg->ids, eg->idnum,
-                                        metric_events);
+                                        metric_events, evlist_used);
                if (!evsel) {
                        pr_debug("Cannot resolve %s: %s\n",
                                        eg->metric_name, eg->metric_expr);
@@ -196,6 +204,9 @@ static int metricgroup__setup_events(struct list_head *groups,
                expr->metric_events = metric_events;
                list_add(&expr->nd, &me->head);
        }
+
+       free(evlist_used);
+
        return ret;
 }