summaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/hist.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index d923a5bb7b48..8efbf58dc3d0 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -2436,7 +2436,7 @@ void hists__match(struct hists *leader, struct hists *other)
{
struct rb_root_cached *root;
struct rb_node *nd;
- struct hist_entry *pos, *pair;
+ struct hist_entry *pos, *pair, *pos_pair, *tmp_pair;
if (symbol_conf.report_hierarchy) {
/* hierarchy report always collapses entries */
@@ -2453,8 +2453,24 @@ void hists__match(struct hists *leader, struct hists *other)
pos = rb_entry(nd, struct hist_entry, rb_node_in);
pair = hists__find_entry(other, pos);
- if (pair && list_empty(&pair->pairs.node))
+ if (pair && list_empty(&pair->pairs.node)) {
+ list_for_each_entry_safe(pos_pair, tmp_pair, &pos->pairs.head, pairs.node) {
+ if (pos_pair->hists == other) {
+ /*
+ * XXX maybe decayed entries can appear
+ * here? but then we would have use
+ * after free, as decayed entries are
+ * freed see hists__delete_entry
+ */
+ BUG_ON(!pos_pair->dummy);
+ list_del_init(&pos_pair->pairs.node);
+ hist_entry__delete(pos_pair);
+ break;
+ }
+ }
+
hist_entry__add_pair(pair, pos);
+ }
}
}