diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2015-08-13 05:40:57 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-09-04 11:01:05 -0400 |
commit | 86c2786994bd7c0d4b525bbfbe42ac540d0b8166 (patch) | |
tree | d536022cb55f7d0d3d2d98e7b70ad39f84919dee /tools/perf/arch | |
parent | 1b29ac59b1d692c06ec543a5f35e0d9ebb98e003 (diff) |
perf intel-pt: Add support for PERF_RECORD_SWITCH
Add support for selecting and processing PERF_RECORD_SWITCH events for
use by Intel PT. If they are available, they will be used in preference
to sched_switch events.
This enables an unprivileged user to trace multi-threaded or
multi-process workloads with any level of perf_event_paranoid. However
it depends on kernel support for PERF_RECORD_SWITCH.
Without this patch, tracing a multi-threaded workload will decode
without error but all the data will be attributed to the main thread.
Without this patch, tracing a multi-process workload will result in
decoder errors because the decoder will not know which executable is
executing.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lkml.kernel.org/r/1439458857-30636-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/arch')
-rw-r--r-- | tools/perf/arch/x86/util/intel-pt.c | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index 2ca10d796c0b..b02af064f0f9 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c | |||
@@ -624,13 +624,49 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
624 | * threads. | 624 | * threads. |
625 | */ | 625 | */ |
626 | if (have_timing_info && !cpu_map__empty(cpus)) { | 626 | if (have_timing_info && !cpu_map__empty(cpus)) { |
627 | err = intel_pt_track_switches(evlist); | 627 | if (perf_can_record_switch_events()) { |
628 | if (err == -EPERM) | 628 | bool cpu_wide = !target__none(&opts->target) && |
629 | pr_debug2("Unable to select sched:sched_switch\n"); | 629 | !target__has_task(&opts->target); |
630 | else if (err) | 630 | |
631 | return err; | 631 | if (!cpu_wide && perf_can_record_cpu_wide()) { |
632 | else | 632 | struct perf_evsel *switch_evsel; |
633 | ptr->have_sched_switch = 1; | 633 | |
634 | err = parse_events(evlist, "dummy:u", NULL); | ||
635 | if (err) | ||
636 | return err; | ||
637 | |||
638 | switch_evsel = perf_evlist__last(evlist); | ||
639 | |||
640 | switch_evsel->attr.freq = 0; | ||
641 | switch_evsel->attr.sample_period = 1; | ||
642 | switch_evsel->attr.context_switch = 1; | ||
643 | |||
644 | switch_evsel->system_wide = true; | ||
645 | switch_evsel->no_aux_samples = true; | ||
646 | switch_evsel->immediate = true; | ||
647 | |||
648 | perf_evsel__set_sample_bit(switch_evsel, TID); | ||
649 | perf_evsel__set_sample_bit(switch_evsel, TIME); | ||
650 | perf_evsel__set_sample_bit(switch_evsel, CPU); | ||
651 | |||
652 | opts->record_switch_events = false; | ||
653 | ptr->have_sched_switch = 3; | ||
654 | } else { | ||
655 | opts->record_switch_events = true; | ||
656 | if (cpu_wide) | ||
657 | ptr->have_sched_switch = 3; | ||
658 | else | ||
659 | ptr->have_sched_switch = 2; | ||
660 | } | ||
661 | } else { | ||
662 | err = intel_pt_track_switches(evlist); | ||
663 | if (err == -EPERM) | ||
664 | pr_debug2("Unable to select sched:sched_switch\n"); | ||
665 | else if (err) | ||
666 | return err; | ||
667 | else | ||
668 | ptr->have_sched_switch = 1; | ||
669 | } | ||
634 | } | 670 | } |
635 | 671 | ||
636 | if (intel_pt_evsel) { | 672 | if (intel_pt_evsel) { |
@@ -663,8 +699,11 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, | |||
663 | tracking_evsel->attr.sample_period = 1; | 699 | tracking_evsel->attr.sample_period = 1; |
664 | 700 | ||
665 | /* In per-cpu case, always need the time of mmap events etc */ | 701 | /* In per-cpu case, always need the time of mmap events etc */ |
666 | if (!cpu_map__empty(cpus)) | 702 | if (!cpu_map__empty(cpus)) { |
667 | perf_evsel__set_sample_bit(tracking_evsel, TIME); | 703 | perf_evsel__set_sample_bit(tracking_evsel, TIME); |
704 | /* And the CPU for switch events */ | ||
705 | perf_evsel__set_sample_bit(tracking_evsel, CPU); | ||
706 | } | ||
668 | } | 707 | } |
669 | 708 | ||
670 | /* | 709 | /* |