perf tools: Add evlist__disable_evsel/evlist__enable_evsel
authorJiri Olsa <jolsa@kernel.org>
Thu, 10 Dec 2020 20:43:28 +0000 (21:43 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 17 Dec 2020 17:36:17 +0000 (14:36 -0300)
Adding interface to enable/disable single event in the evlist based on
its name. It will be used later in new control enable/disable interface.

Keeping the evlist::enabled true when one or more events are enabled so
the toggle can work properly and toggle evlist to disabled state.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Alexei Budankov <abudankov@huawei.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: https://lore.kernel.org/r/20201210204330.233864-2-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evlist.c
tools/perf/util/evlist.h

index 89286f1..05363a7 100644 (file)
@@ -381,7 +381,30 @@ bool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
        return true;
 }
 
-void evlist__disable(struct evlist *evlist)
+static int evsel__strcmp(struct evsel *pos, char *evsel_name)
+{
+       if (!evsel_name)
+               return 0;
+       if (evsel__is_dummy_event(pos))
+               return 1;
+       return strcmp(pos->name, evsel_name);
+}
+
+static int evlist__is_enabled(struct evlist *evlist)
+{
+       struct evsel *pos;
+
+       evlist__for_each_entry(evlist, pos) {
+               if (!evsel__is_group_leader(pos) || !pos->core.fd)
+                       continue;
+               /* If at least one event is enabled, evlist is enabled. */
+               if (!pos->disabled)
+                       return true;
+       }
+       return false;
+}
+
+static void __evlist__disable(struct evlist *evlist, char *evsel_name)
 {
        struct evsel *pos;
        struct affinity affinity;
@@ -397,6 +420,8 @@ void evlist__disable(struct evlist *evlist)
                        affinity__set(&affinity, cpu);
 
                        evlist__for_each_entry(evlist, pos) {
+                               if (evsel__strcmp(pos, evsel_name))
+                                       continue;
                                if (evsel__cpu_iter_skip(pos, cpu))
                                        continue;
                                if (pos->disabled || !evsel__is_group_leader(pos) || !pos->core.fd)
@@ -414,15 +439,34 @@ void evlist__disable(struct evlist *evlist)
 
        affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
+               if (evsel__strcmp(pos, evsel_name))
+                       continue;
                if (!evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
                pos->disabled = true;
        }
 
-       evlist->enabled = false;
+       /*
+        * If we disabled only single event, we need to check
+        * the enabled state of the evlist manually.
+        */
+       if (evsel_name)
+               evlist->enabled = evlist__is_enabled(evlist);
+       else
+               evlist->enabled = false;
+}
+
+void evlist__disable(struct evlist *evlist)
+{
+       __evlist__disable(evlist, NULL);
+}
+
+void evlist__disable_evsel(struct evlist *evlist, char *evsel_name)
+{
+       __evlist__disable(evlist, evsel_name);
 }
 
-void evlist__enable(struct evlist *evlist)
+static void __evlist__enable(struct evlist *evlist, char *evsel_name)
 {
        struct evsel *pos;
        struct affinity affinity;
@@ -435,6 +479,8 @@ void evlist__enable(struct evlist *evlist)
                affinity__set(&affinity, cpu);
 
                evlist__for_each_entry(evlist, pos) {
+                       if (evsel__strcmp(pos, evsel_name))
+                               continue;
                        if (evsel__cpu_iter_skip(pos, cpu))
                                continue;
                        if (!evsel__is_group_leader(pos) || !pos->core.fd)
@@ -444,14 +490,31 @@ void evlist__enable(struct evlist *evlist)
        }
        affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
+               if (evsel__strcmp(pos, evsel_name))
+                       continue;
                if (!evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
                pos->disabled = false;
        }
 
+       /*
+        * Even single event sets the 'enabled' for evlist,
+        * so the toggle can work properly and toggle to
+        * 'disabled' state.
+        */
        evlist->enabled = true;
 }
 
+void evlist__enable(struct evlist *evlist)
+{
+       __evlist__enable(evlist, NULL);
+}
+
+void evlist__enable_evsel(struct evlist *evlist, char *evsel_name)
+{
+       __evlist__enable(evlist, evsel_name);
+}
+
 void evlist__toggle_enable(struct evlist *evlist)
 {
        (evlist->enabled ? evlist__disable : evlist__enable)(evlist);
index 9b0c795..1aae758 100644 (file)
@@ -186,6 +186,8 @@ size_t evlist__mmap_size(unsigned long pages);
 void evlist__disable(struct evlist *evlist);
 void evlist__enable(struct evlist *evlist);
 void evlist__toggle_enable(struct evlist *evlist);
+void evlist__disable_evsel(struct evlist *evlist, char *evsel_name);
+void evlist__enable_evsel(struct evlist *evlist, char *evsel_name);
 
 int evlist__enable_event_idx(struct evlist *evlist, struct evsel *evsel, int idx);