diff options
-rw-r--r-- | tools/perf/arch/x86/util/evsel.c | 12 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 16 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 10 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 3 |
4 files changed, 39 insertions, 2 deletions
diff --git a/tools/perf/arch/x86/util/evsel.c b/tools/perf/arch/x86/util/evsel.c index ac2899a25b7a..00cb4466b4ca 100644 --- a/tools/perf/arch/x86/util/evsel.c +++ b/tools/perf/arch/x86/util/evsel.c @@ -3,6 +3,7 @@ #include <stdlib.h> #include "util/evsel.h" #include "util/env.h" +#include "util/pmu.h" #include "linux/string.h" void arch_evsel__set_sample_weight(struct evsel *evsel) @@ -29,3 +30,14 @@ void arch_evsel__fixup_new_cycles(struct perf_event_attr *attr) free(env.cpuid); } + +bool arch_evsel__must_be_in_group(const struct evsel *evsel) +{ + if ((evsel->pmu_name && strcmp(evsel->pmu_name, "cpu")) || + !pmu_have_event("cpu", "slots")) + return false; + + return evsel->name && + (!strcasecmp(evsel->name, "slots") || + strcasestr(evsel->name, "topdown")); +} diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 7ae56b062f44..91bbe4c069eb 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1742,8 +1742,17 @@ struct evsel *evlist__reset_weak_group(struct evlist *evsel_list, struct evsel * if (evsel__has_leader(c2, leader)) { if (is_open && close) perf_evsel__close(&c2->core); - evsel__set_leader(c2, c2); - c2->core.nr_members = 0; + /* + * We want to close all members of the group and reopen + * them. Some events, like Intel topdown, require being + * in a group and so keep these in the group. + */ + if (!evsel__must_be_in_group(c2) && c2 != leader) { + evsel__set_leader(c2, c2); + c2->core.nr_members = 0; + leader->core.nr_members--; + } + /* * Set this for all former members of the group * to indicate they get reopened. @@ -1751,6 +1760,9 @@ struct evsel *evlist__reset_weak_group(struct evlist *evsel_list, struct evsel * c2->reset_group = true; } } + /* Reset the leader count if all entries were removed. */ + if (leader->core.nr_members == 1) + leader->core.nr_members = 0; return leader; } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 5fd7924f8eb3..1cf967d689aa 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -3103,3 +3103,13 @@ int evsel__source_count(const struct evsel *evsel) } return count; } + +bool __weak arch_evsel__must_be_in_group(const struct evsel *evsel __maybe_unused) +{ + return false; +} + +bool evsel__must_be_in_group(const struct evsel *evsel) +{ + return arch_evsel__must_be_in_group(evsel); +} diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 52dc5fd106b1..84755fabc544 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -499,6 +499,9 @@ bool evsel__has_leader(struct evsel *evsel, struct evsel *leader); bool evsel__is_leader(struct evsel *evsel); void evsel__set_leader(struct evsel *evsel, struct evsel *leader); int evsel__source_count(const struct evsel *evsel); +bool evsel__must_be_in_group(const struct evsel *evsel); + +bool arch_evsel__must_be_in_group(const struct evsel *evsel); /* * Macro to swap the bit-field postition and size. |