aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2016-06-23 09:40:57 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-06-23 16:02:59 -0400
commit50f736372d5ea0ce97ede698f957c9b141aa569e (patch)
treef12cd5756fdc9364c2cd0bd603167c37fb0f284b
parent055cd33d93ac310ce68e8b1ebcf88f829426adf5 (diff)
perf auxtrace: Add option to feed branches to the thread stack
In preparation for using the thread stack to print an indent representing the stack depth in perf script, add an option to tell decoders to feed branches to the thread stack. Add support for that option to Intel PT and Intel BTS. The advantage of using the decoder to feed the thread stack is that it happens before branch filtering and so can be used with different itrace options (e.g. it still works when only showing calls, even though the thread stack needs to see calls and returns). Also it does not conflict with using the thread stack to get callchains. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Acked-by: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Link: http://lkml.kernel.org/r/1466689258-28493-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/auxtrace.h2
-rw-r--r--tools/perf/util/intel-bts.c22
-rw-r--r--tools/perf/util/intel-pt.c5
3 files changed, 23 insertions, 6 deletions
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 767989e0e312..ac5f0d7167e6 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -63,6 +63,7 @@ enum itrace_period_type {
63 * @calls: limit branch samples to calls (can be combined with @returns) 63 * @calls: limit branch samples to calls (can be combined with @returns)
64 * @returns: limit branch samples to returns (can be combined with @calls) 64 * @returns: limit branch samples to returns (can be combined with @calls)
65 * @callchain: add callchain to 'instructions' events 65 * @callchain: add callchain to 'instructions' events
66 * @thread_stack: feed branches to the thread_stack
66 * @last_branch: add branch context to 'instruction' events 67 * @last_branch: add branch context to 'instruction' events
67 * @callchain_sz: maximum callchain size 68 * @callchain_sz: maximum callchain size
68 * @last_branch_sz: branch context size 69 * @last_branch_sz: branch context size
@@ -82,6 +83,7 @@ struct itrace_synth_opts {
82 bool calls; 83 bool calls;
83 bool returns; 84 bool returns;
84 bool callchain; 85 bool callchain;
86 bool thread_stack;
85 bool last_branch; 87 bool last_branch;
86 unsigned int callchain_sz; 88 unsigned int callchain_sz;
87 unsigned int last_branch_sz; 89 unsigned int last_branch_sz;
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index ecec73f6fe5a..749e6f2e37ca 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -422,7 +422,8 @@ static int intel_bts_get_branch_type(struct intel_bts_queue *btsq,
422} 422}
423 423
424static int intel_bts_process_buffer(struct intel_bts_queue *btsq, 424static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
425 struct auxtrace_buffer *buffer) 425 struct auxtrace_buffer *buffer,
426 struct thread *thread)
426{ 427{
427 struct branch *branch; 428 struct branch *branch;
428 size_t sz, bsz = sizeof(struct branch); 429 size_t sz, bsz = sizeof(struct branch);
@@ -444,6 +445,12 @@ static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
444 if (!branch->from && !branch->to) 445 if (!branch->from && !branch->to)
445 continue; 446 continue;
446 intel_bts_get_branch_type(btsq, branch); 447 intel_bts_get_branch_type(btsq, branch);
448 if (btsq->bts->synth_opts.thread_stack)
449 thread_stack__event(thread, btsq->sample_flags,
450 le64_to_cpu(branch->from),
451 le64_to_cpu(branch->to),
452 btsq->intel_pt_insn.length,
453 buffer->buffer_nr + 1);
447 if (filter && !(filter & btsq->sample_flags)) 454 if (filter && !(filter & btsq->sample_flags))
448 continue; 455 continue;
449 err = intel_bts_synth_branch_sample(btsq, branch); 456 err = intel_bts_synth_branch_sample(btsq, branch);
@@ -507,12 +514,13 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
507 goto out_put; 514 goto out_put;
508 } 515 }
509 516
510 if (!btsq->bts->synth_opts.callchain && thread && 517 if (!btsq->bts->synth_opts.callchain &&
518 !btsq->bts->synth_opts.thread_stack && thread &&
511 (!old_buffer || btsq->bts->sampling_mode || 519 (!old_buffer || btsq->bts->sampling_mode ||
512 (btsq->bts->snapshot_mode && !buffer->consecutive))) 520 (btsq->bts->snapshot_mode && !buffer->consecutive)))
513 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); 521 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1);
514 522
515 err = intel_bts_process_buffer(btsq, buffer); 523 err = intel_bts_process_buffer(btsq, buffer, thread);
516 524
517 auxtrace_buffer__drop_data(buffer); 525 auxtrace_buffer__drop_data(buffer);
518 526
@@ -905,10 +913,14 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
905 if (dump_trace) 913 if (dump_trace)
906 return 0; 914 return 0;
907 915
908 if (session->itrace_synth_opts && session->itrace_synth_opts->set) 916 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
909 bts->synth_opts = *session->itrace_synth_opts; 917 bts->synth_opts = *session->itrace_synth_opts;
910 else 918 } else {
911 itrace_synth_opts__set_default(&bts->synth_opts); 919 itrace_synth_opts__set_default(&bts->synth_opts);
920 if (session->itrace_synth_opts)
921 bts->synth_opts.thread_stack =
922 session->itrace_synth_opts->thread_stack;
923 }
912 924
913 if (bts->synth_opts.calls) 925 if (bts->synth_opts.calls)
914 bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | 926 bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index dc243b19197b..551ff6f640be 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1234,7 +1234,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1234 if (!(state->type & INTEL_PT_BRANCH)) 1234 if (!(state->type & INTEL_PT_BRANCH))
1235 return 0; 1235 return 0;
1236 1236
1237 if (pt->synth_opts.callchain) 1237 if (pt->synth_opts.callchain || pt->synth_opts.thread_stack)
1238 thread_stack__event(ptq->thread, ptq->flags, state->from_ip, 1238 thread_stack__event(ptq->thread, ptq->flags, state->from_ip,
1239 state->to_ip, ptq->insn_len, 1239 state->to_ip, ptq->insn_len,
1240 state->trace_nr); 1240 state->trace_nr);
@@ -2137,6 +2137,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2137 pt->synth_opts.branches = false; 2137 pt->synth_opts.branches = false;
2138 pt->synth_opts.callchain = true; 2138 pt->synth_opts.callchain = true;
2139 } 2139 }
2140 if (session->itrace_synth_opts)
2141 pt->synth_opts.thread_stack =
2142 session->itrace_synth_opts->thread_stack;
2140 } 2143 }
2141 2144
2142 if (pt->synth_opts.log) 2145 if (pt->synth_opts.log)