diff options
Diffstat (limited to 'tools/perf/util/thread-stack.c')
-rw-r--r-- | tools/perf/util/thread-stack.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c index c091635bf7dc..61a4286a74dc 100644 --- a/tools/perf/util/thread-stack.c +++ b/tools/perf/util/thread-stack.c | |||
@@ -310,20 +310,46 @@ void thread_stack__free(struct thread *thread) | |||
310 | } | 310 | } |
311 | } | 311 | } |
312 | 312 | ||
313 | static inline u64 callchain_context(u64 ip, u64 kernel_start) | ||
314 | { | ||
315 | return ip < kernel_start ? PERF_CONTEXT_USER : PERF_CONTEXT_KERNEL; | ||
316 | } | ||
317 | |||
313 | void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, | 318 | void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, |
314 | size_t sz, u64 ip) | 319 | size_t sz, u64 ip, u64 kernel_start) |
315 | { | 320 | { |
316 | size_t i; | 321 | u64 context = callchain_context(ip, kernel_start); |
322 | u64 last_context; | ||
323 | size_t i, j; | ||
317 | 324 | ||
318 | if (!thread || !thread->ts) | 325 | if (sz < 2) { |
319 | chain->nr = 1; | 326 | chain->nr = 0; |
320 | else | 327 | return; |
321 | chain->nr = min(sz, thread->ts->cnt + 1); | 328 | } |
322 | 329 | ||
323 | chain->ips[0] = ip; | 330 | chain->ips[0] = context; |
331 | chain->ips[1] = ip; | ||
332 | |||
333 | if (!thread || !thread->ts) { | ||
334 | chain->nr = 2; | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | last_context = context; | ||
339 | |||
340 | for (i = 2, j = 1; i < sz && j <= thread->ts->cnt; i++, j++) { | ||
341 | ip = thread->ts->stack[thread->ts->cnt - j].ret_addr; | ||
342 | context = callchain_context(ip, kernel_start); | ||
343 | if (context != last_context) { | ||
344 | if (i >= sz - 1) | ||
345 | break; | ||
346 | chain->ips[i++] = context; | ||
347 | last_context = context; | ||
348 | } | ||
349 | chain->ips[i] = ip; | ||
350 | } | ||
324 | 351 | ||
325 | for (i = 1; i < chain->nr; i++) | 352 | chain->nr = i; |
326 | chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr; | ||
327 | } | 353 | } |
328 | 354 | ||
329 | struct call_return_processor * | 355 | struct call_return_processor * |