perf record: Fix duplicated sideband events with Intel PT system wide tracing
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 29 Jun 2020 09:19:51 +0000 (12:19 +0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 3 Jul 2020 11:16:51 +0000 (08:16 -0300)
Commit 0a892c1c9472 ("perf record: Add dummy event during system wide
synthesis") reveals an issue with Intel PT system wide tracing.
Specifically that Intel PT already adds a dummy tracking event, and it
is not the first event.  Adding another dummy tracking event causes
duplicated sideband events.  Fix by checking for an existing dummy
tracking event first.

Example showing duplicated switch events:

 Before:

   # perf record -a -e intel_pt//u uname
   Linux
   [ perf record: Woken up 1 times to write data ]
   [ perf record: Captured and wrote 0.895 MB perf.data ]
   # perf script --no-itrace --show-switch-events | head
            swapper     0 [007]  6390.516222: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:    11/11
            swapper     0 [007]  6390.516222: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:    11/11
          rcu_sched    11 [007]  6390.516223: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:     0/0
          rcu_sched    11 [007]  6390.516224: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:     0/0
          rcu_sched    11 [007]  6390.516227: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid:     0/0
          rcu_sched    11 [007]  6390.516227: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid:     0/0
            swapper     0 [007]  6390.516228: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:    11/11
            swapper     0 [007]  6390.516228: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:    11/11
            swapper     0 [002]  6390.516415: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:  5556/5559
            swapper     0 [002]  6390.516416: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:  5556/5559

 After:

   # perf record -a -e intel_pt//u uname
   Linux
   [ perf record: Woken up 1 times to write data ]
   [ perf record: Captured and wrote 0.868 MB perf.data ]
   #  perf script --no-itrace --show-switch-events | head
            swapper     0 [005]  6450.567013: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:  7179/7181
               perf  7181 [005]  6450.567014: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:     0/0
               perf  7181 [005]  6450.567028: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid:     0/0
            swapper     0 [005]  6450.567029: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:  7179/7181
            swapper     0 [005]  6450.571699: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:    11/11
          rcu_sched    11 [005]  6450.571700: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:     0/0
          rcu_sched    11 [005]  6450.571702: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid:     0/0
            swapper     0 [005]  6450.571703: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:    11/11
            swapper     0 [005]  6450.579703: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid:    11/11
          rcu_sched    11 [005]  6450.579704: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid:     0/0

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lore.kernel.org/lkml/20200629091955.17090-3-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-record.c
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index e108d90ae2edf8704818a7e7c17e70afecddd335..a37e7910e9e90bf8c6bf5edd00b42e78a7593d66 100644 (file)
@@ -852,20 +852,20 @@ static int record__open(struct record *rec)
         * event synthesis.
         */
        if (opts->initial_delay || target__has_cpu(&opts->target)) {
-               if (perf_evlist__add_dummy(evlist))
-                       return -ENOMEM;
+               pos = perf_evlist__get_tracking_event(evlist);
+               if (!evsel__is_dummy_event(pos)) {
+                       /* Set up dummy event. */
+                       if (perf_evlist__add_dummy(evlist))
+                               return -ENOMEM;
+                       pos = evlist__last(evlist);
+                       perf_evlist__set_tracking_event(evlist, pos);
+               }
 
-               /* Disable tracking of mmaps on lead event. */
-               pos = evlist__first(evlist);
-               pos->tracking = 0;
-               /* Set up dummy event. */
-               pos = evlist__last(evlist);
-               pos->tracking = 1;
                /*
                 * Enable the dummy event when the process is forked for
                 * initial_delay, immediately for system wide.
                 */
-               if (opts->initial_delay)
+               if (opts->initial_delay && !pos->immediate)
                        pos->core.attr.enable_on_exec = 1;
                else
                        pos->immediate = 1;
index 173b4f0e0e6e6158c77ea1dcf15e43ddcfae9a8f..ab48be4cf2584a036b4a9bacfcd0e8e5bee7e2b7 100644 (file)
@@ -1566,6 +1566,18 @@ void perf_evlist__to_front(struct evlist *evlist,
        list_splice(&move, &evlist->core.entries);
 }
 
+struct evsel *perf_evlist__get_tracking_event(struct evlist *evlist)
+{
+       struct evsel *evsel;
+
+       evlist__for_each_entry(evlist, evsel) {
+               if (evsel->tracking)
+                       return evsel;
+       }
+
+       return evlist__first(evlist);
+}
+
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel)
 {
index b6f325dfb4d24d8481421be75c98b9567a9b610a..a8081dfc19cf5b4e10131f59d05e42ac22599efd 100644 (file)
@@ -335,6 +335,7 @@ void perf_evlist__to_front(struct evlist *evlist,
        evlist__cpu_iter_start(evlist);                 \
        perf_cpu_map__for_each_cpu (cpu, index, (evlist)->core.all_cpus)
 
+struct evsel *perf_evlist__get_tracking_event(struct evlist *evlist);
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel);
 
index 96e5171dce41e458a897fbae387bc78ef37276f7..a68ac3632ae6881a43b76e9f9c20f1a17b023cc0 100644 (file)
@@ -898,12 +898,6 @@ static void evsel__apply_config_terms(struct evsel *evsel,
        }
 }
 
-static bool is_dummy_event(struct evsel *evsel)
-{
-       return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
-              (evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
-}
-
 struct evsel_config_term *__evsel__get_config_term(struct evsel *evsel, enum evsel_term_type type)
 {
        struct evsel_config_term *term, *found_term = NULL;
@@ -1161,7 +1155,7 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
         * The software event will trigger -EOPNOTSUPP error out,
         * if BRANCH_STACK bit is set.
         */
-       if (is_dummy_event(evsel))
+       if (evsel__is_dummy_event(evsel))
                evsel__reset_sample_bit(evsel, BRANCH_STACK);
 }
 
index 0f963c2a88a5d3d1734189d5774823a0238de6db..35e3f6d66085b3885290e315e7268f0852f2bb1c 100644 (file)
@@ -399,6 +399,12 @@ static inline bool evsel__has_br_stack(const struct evsel *evsel)
               evsel->synth_sample_type & PERF_SAMPLE_BRANCH_STACK;
 }
 
+static inline bool evsel__is_dummy_event(struct evsel *evsel)
+{
+       return (evsel->core.attr.type == PERF_TYPE_SOFTWARE) &&
+              (evsel->core.attr.config == PERF_COUNT_SW_DUMMY);
+}
+
 struct perf_env *evsel__env(struct evsel *evsel);
 
 int evsel__store_ids(struct evsel *evsel, struct evlist *evlist);