perf record: Fix duplicated sideband events with Intel PT system wide tracing
Commit 0a892c1c94
("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>
This commit is contained in:
parent
640432e6be
commit
442ad2254a
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user