Commit 66f066d8994bd146304bab72fa09c1e644c4b3ff
Committed by
Arnaldo Carvalho de Melo
1 parent
0cdccac6fe
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
perf callchain: Create an address space per thread
The unw_addr_space_t in libunwind represents an address space to be used for stack unwinding. It doesn't need to be create/destory everytime to unwind callchain (as in get_entries) and can have a same lifetime as thread (unless exec called). So move the address space construction/destruction logic to the thread lifetime handling functions. This is a preparation to enable caching in the unwind library. Note that it saves unw_addr_space_t object using thread__set_priv(). It seems currently only used by perf trace and perf kvm stat commands which don't use callchain. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Acked-by: Jean Pihet <jean.pihet@linaro.org> Acked-by: Jiri Olsa <jolsa@kernel.org> Cc: Arun Sharma <asharma@fb.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jean Pihet <jean.pihet@linaro.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1412556363-26229-3-git-send-email-namhyung@kernel.org [ Fixup unwind-libunwind.c missing CALLCHAIN_DWARF definition, added missing __maybe_unused on unused parameters in stubs at util/unwind.h ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Showing 3 changed files with 55 additions and 5 deletions Side-by-side Diff
tools/perf/util/thread.c
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | #include "util.h" |
8 | 8 | #include "debug.h" |
9 | 9 | #include "comm.h" |
10 | +#include "unwind.h" | |
10 | 11 | |
11 | 12 | int thread__init_map_groups(struct thread *thread, struct machine *machine) |
12 | 13 | { |
... | ... | @@ -37,6 +38,9 @@ |
37 | 38 | thread->cpu = -1; |
38 | 39 | INIT_LIST_HEAD(&thread->comm_list); |
39 | 40 | |
41 | + if (unwind__prepare_access(thread) < 0) | |
42 | + goto err_thread; | |
43 | + | |
40 | 44 | comm_str = malloc(32); |
41 | 45 | if (!comm_str) |
42 | 46 | goto err_thread; |
... | ... | @@ -48,6 +52,7 @@ |
48 | 52 | goto err_thread; |
49 | 53 | |
50 | 54 | list_add(&comm->list, &thread->comm_list); |
55 | + | |
51 | 56 | } |
52 | 57 | |
53 | 58 | return thread; |
... | ... | @@ -69,6 +74,7 @@ |
69 | 74 | list_del(&comm->list); |
70 | 75 | comm__free(comm); |
71 | 76 | } |
77 | + unwind__finish_access(thread); | |
72 | 78 | |
73 | 79 | free(thread); |
74 | 80 | } |
tools/perf/util/unwind-libunwind.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <linux/list.h> |
25 | 25 | #include <libunwind.h> |
26 | 26 | #include <libunwind-ptrace.h> |
27 | +#include "callchain.h" | |
27 | 28 | #include "thread.h" |
28 | 29 | #include "session.h" |
29 | 30 | #include "perf_regs.h" |
30 | 31 | |
31 | 32 | |
32 | 33 | |
... | ... | @@ -525,19 +526,46 @@ |
525 | 526 | .get_proc_name = get_proc_name, |
526 | 527 | }; |
527 | 528 | |
528 | -static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | |
529 | - void *arg, int max_stack) | |
529 | +int unwind__prepare_access(struct thread *thread) | |
530 | 530 | { |
531 | 531 | unw_addr_space_t addr_space; |
532 | - unw_cursor_t c; | |
533 | - int ret; | |
534 | 532 | |
533 | + if (callchain_param.record_mode != CALLCHAIN_DWARF) | |
534 | + return 0; | |
535 | + | |
535 | 536 | addr_space = unw_create_addr_space(&accessors, 0); |
536 | 537 | if (!addr_space) { |
537 | 538 | pr_err("unwind: Can't create unwind address space.\n"); |
538 | 539 | return -ENOMEM; |
539 | 540 | } |
540 | 541 | |
542 | + thread__set_priv(thread, addr_space); | |
543 | + | |
544 | + return 0; | |
545 | +} | |
546 | + | |
547 | +void unwind__finish_access(struct thread *thread) | |
548 | +{ | |
549 | + unw_addr_space_t addr_space; | |
550 | + | |
551 | + if (callchain_param.record_mode != CALLCHAIN_DWARF) | |
552 | + return; | |
553 | + | |
554 | + addr_space = thread__priv(thread); | |
555 | + unw_destroy_addr_space(addr_space); | |
556 | +} | |
557 | + | |
558 | +static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | |
559 | + void *arg, int max_stack) | |
560 | +{ | |
561 | + unw_addr_space_t addr_space; | |
562 | + unw_cursor_t c; | |
563 | + int ret; | |
564 | + | |
565 | + addr_space = thread__priv(ui->thread); | |
566 | + if (addr_space == NULL) | |
567 | + return -1; | |
568 | + | |
541 | 569 | ret = unw_init_remote(&c, addr_space, ui); |
542 | 570 | if (ret) |
543 | 571 | display_error(ret); |
... | ... | @@ -549,7 +577,6 @@ |
549 | 577 | ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; |
550 | 578 | } |
551 | 579 | |
552 | - unw_destroy_addr_space(addr_space); | |
553 | 580 | return ret; |
554 | 581 | } |
555 | 582 |
tools/perf/util/unwind.h
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | #include <linux/types.h> |
5 | 5 | #include "event.h" |
6 | 6 | #include "symbol.h" |
7 | +#include "thread.h" | |
7 | 8 | |
8 | 9 | struct unwind_entry { |
9 | 10 | struct map *map; |
... | ... | @@ -21,6 +22,15 @@ |
21 | 22 | /* libunwind specific */ |
22 | 23 | #ifdef HAVE_LIBUNWIND_SUPPORT |
23 | 24 | int libunwind__arch_reg_id(int regnum); |
25 | +int unwind__prepare_access(struct thread *thread); | |
26 | +void unwind__finish_access(struct thread *thread); | |
27 | +#else | |
28 | +static inline int unwind__prepare_access(struct thread *thread __maybe_unused) | |
29 | +{ | |
30 | + return 0; | |
31 | +} | |
32 | + | |
33 | +static inline void unwind__finish_access(struct thread *thread __maybe_unused) {} | |
24 | 34 | #endif |
25 | 35 | #else |
26 | 36 | static inline int |
... | ... | @@ -33,6 +43,13 @@ |
33 | 43 | { |
34 | 44 | return 0; |
35 | 45 | } |
46 | + | |
47 | +static inline int unwind__prepare_access(struct thread *thread __maybe_unused) | |
48 | +{ | |
49 | + return 0; | |
50 | +} | |
51 | + | |
52 | +static inline void unwind__finish_access(struct thread *thread __maybe_unused) {} | |
36 | 53 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ |
37 | 54 | #endif /* __UNWIND_H */ |