Skip to content

Commit 5f3e37d

Browse files
committed
perf python: Improve leader copying from evlist
JIRA: https://issues.redhat.com/browse/RHEL-78198 upstream ======== commit 421c5f3 Author: Ian Rogers <irogers@google.com> Date: Thu Jul 10 16:51:25 2025 -0700 description =========== The struct pyrf_evlist embeds the evlist requiring the copying from things like parsed events. The copying logic handles the leader being the event itself, but if the leader group event is a different in the list it will cause an evsel to point to the evsel in the list that was copied from which is bad. Fix this by adding another pass over the evlist rewriting leaders, simplified by the introductin of two evlist helpers. Signed-off-by: Ian Rogers <irogers@google.com> Link: https://lore.kernel.org/r/20250710235126.1086011-13-irogers@google.com Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Michael Petlan <mpetlan@redhat.com>
1 parent 44e7c20 commit 5f3e37d

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

tools/perf/util/python.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,10 +1568,37 @@ static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
15681568
return (PyObject *)pevsel;
15691569
}
15701570

1571+
static int evlist__pos(struct evlist *evlist, struct evsel *evsel)
1572+
{
1573+
struct evsel *pos;
1574+
int idx = 0;
1575+
1576+
evlist__for_each_entry(evlist, pos) {
1577+
if (evsel == pos)
1578+
return idx;
1579+
idx++;
1580+
}
1581+
return -1;
1582+
}
1583+
1584+
static struct evsel *evlist__at(struct evlist *evlist, int idx)
1585+
{
1586+
struct evsel *pos;
1587+
int idx2 = 0;
1588+
1589+
evlist__for_each_entry(evlist, pos) {
1590+
if (idx == idx2)
1591+
return pos;
1592+
idx2++;
1593+
}
1594+
return NULL;
1595+
}
1596+
15711597
static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
15721598
{
15731599
struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type);
15741600
struct evsel *pos;
1601+
struct rb_node *node;
15751602

15761603
if (!pevlist)
15771604
return NULL;
@@ -1583,9 +1610,39 @@ static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
15831610

15841611
evlist__add(&pevlist->evlist, &pevsel->evsel);
15851612
}
1613+
evlist__for_each_entry(&pevlist->evlist, pos) {
1614+
struct evsel *leader = evsel__leader(pos);
1615+
1616+
if (pos != leader) {
1617+
int idx = evlist__pos(evlist, leader);
1618+
1619+
if (idx >= 0)
1620+
evsel__set_leader(pos, evlist__at(&pevlist->evlist, idx));
1621+
else if (leader == NULL)
1622+
evsel__set_leader(pos, pos);
1623+
}
1624+
}
15861625
metricgroup__copy_metric_events(&pevlist->evlist, /*cgrp=*/NULL,
15871626
&pevlist->evlist.metric_events,
15881627
&evlist->metric_events);
1628+
for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node;
1629+
node = rb_next(node)) {
1630+
struct metric_event *me = container_of(node, struct metric_event, nd);
1631+
struct list_head *mpos;
1632+
int idx = evlist__pos(evlist, me->evsel);
1633+
1634+
if (idx >= 0)
1635+
me->evsel = evlist__at(&pevlist->evlist, idx);
1636+
list_for_each(mpos, &me->head) {
1637+
struct metric_expr *e = container_of(mpos, struct metric_expr, nd);
1638+
1639+
for (int j = 0; e->metric_events[j]; j++) {
1640+
idx = evlist__pos(evlist, e->metric_events[j]);
1641+
if (idx >= 0)
1642+
e->metric_events[j] = evlist__at(&pevlist->evlist, idx);
1643+
}
1644+
}
1645+
}
15891646
return (PyObject *)pevlist;
15901647
}
15911648

0 commit comments

Comments
 (0)