Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf python: Improve leader copying from evlist

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>

authored by

Ian Rogers and committed by
Namhyung Kim
421c5f39 6183afcb

+57
+57
tools/perf/util/python.c
··· 1568 1568 return (PyObject *)pevsel; 1569 1569 } 1570 1570 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 + 1571 1597 static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist) 1572 1598 { 1573 1599 struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type); 1574 1600 struct evsel *pos; 1601 + struct rb_node *node; 1575 1602 1576 1603 if (!pevlist) 1577 1604 return NULL; ··· 1610 1583 1611 1584 evlist__add(&pevlist->evlist, &pevsel->evsel); 1612 1585 } 1586 + evlist__for_each_entry(&pevlist->evlist, pos) { 1587 + struct evsel *leader = evsel__leader(pos); 1588 + 1589 + if (pos != leader) { 1590 + int idx = evlist__pos(evlist, leader); 1591 + 1592 + if (idx >= 0) 1593 + evsel__set_leader(pos, evlist__at(&pevlist->evlist, idx)); 1594 + else if (leader == NULL) 1595 + evsel__set_leader(pos, pos); 1596 + } 1597 + } 1613 1598 metricgroup__copy_metric_events(&pevlist->evlist, /*cgrp=*/NULL, 1614 1599 &pevlist->evlist.metric_events, 1615 1600 &evlist->metric_events); 1601 + for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node; 1602 + node = rb_next(node)) { 1603 + struct metric_event *me = container_of(node, struct metric_event, nd); 1604 + struct list_head *mpos; 1605 + int idx = evlist__pos(evlist, me->evsel); 1606 + 1607 + if (idx >= 0) 1608 + me->evsel = evlist__at(&pevlist->evlist, idx); 1609 + list_for_each(mpos, &me->head) { 1610 + struct metric_expr *e = container_of(mpos, struct metric_expr, nd); 1611 + 1612 + for (int j = 0; e->metric_events[j]; j++) { 1613 + idx = evlist__pos(evlist, e->metric_events[j]); 1614 + if (idx >= 0) 1615 + e->metric_events[j] = evlist__at(&pevlist->evlist, idx); 1616 + } 1617 + } 1618 + } 1616 1619 return (PyObject *)pevlist; 1617 1620 } 1618 1621