diff options
author | Namhyung Kim <namhyung@kernel.org> | 2014-10-05 20:46:00 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-10-15 16:38:23 -0400 |
commit | 66f066d8994bd146304bab72fa09c1e644c4b3ff (patch) | |
tree | 9e958638fe69c2df70107aab7015be8bc36da4f3 /tools | |
parent | 0cdccac6fe4b1316f04f0dbfcc4efab51932014a (diff) |
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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/thread.c | 6 | ||||
-rw-r--r-- | tools/perf/util/unwind-libunwind.c | 37 | ||||
-rw-r--r-- | tools/perf/util/unwind.h | 17 |
3 files changed, 55 insertions, 5 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index a9df7f2c6dc9..2b7b2d91c016 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include "util.h" | 7 | #include "util.h" |
8 | #include "debug.h" | 8 | #include "debug.h" |
9 | #include "comm.h" | 9 | #include "comm.h" |
10 | #include "unwind.h" | ||
10 | 11 | ||
11 | int thread__init_map_groups(struct thread *thread, struct machine *machine) | 12 | int thread__init_map_groups(struct thread *thread, struct machine *machine) |
12 | { | 13 | { |
@@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid) | |||
37 | thread->cpu = -1; | 38 | thread->cpu = -1; |
38 | INIT_LIST_HEAD(&thread->comm_list); | 39 | INIT_LIST_HEAD(&thread->comm_list); |
39 | 40 | ||
41 | if (unwind__prepare_access(thread) < 0) | ||
42 | goto err_thread; | ||
43 | |||
40 | comm_str = malloc(32); | 44 | comm_str = malloc(32); |
41 | if (!comm_str) | 45 | if (!comm_str) |
42 | goto err_thread; | 46 | goto err_thread; |
@@ -48,6 +52,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) | |||
48 | goto err_thread; | 52 | goto err_thread; |
49 | 53 | ||
50 | list_add(&comm->list, &thread->comm_list); | 54 | list_add(&comm->list, &thread->comm_list); |
55 | |||
51 | } | 56 | } |
52 | 57 | ||
53 | return thread; | 58 | return thread; |
@@ -69,6 +74,7 @@ void thread__delete(struct thread *thread) | |||
69 | list_del(&comm->list); | 74 | list_del(&comm->list); |
70 | comm__free(comm); | 75 | comm__free(comm); |
71 | } | 76 | } |
77 | unwind__finish_access(thread); | ||
72 | 78 | ||
73 | free(thread); | 79 | free(thread); |
74 | } | 80 | } |
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c index 92b56db52471..e060386165c5 100644 --- a/tools/perf/util/unwind-libunwind.c +++ b/tools/perf/util/unwind-libunwind.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <libunwind.h> | 25 | #include <libunwind.h> |
26 | #include <libunwind-ptrace.h> | 26 | #include <libunwind-ptrace.h> |
27 | #include "callchain.h" | ||
27 | #include "thread.h" | 28 | #include "thread.h" |
28 | #include "session.h" | 29 | #include "session.h" |
29 | #include "perf_regs.h" | 30 | #include "perf_regs.h" |
@@ -525,12 +526,12 @@ static unw_accessors_t accessors = { | |||
525 | .get_proc_name = get_proc_name, | 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 | int unwind__prepare_access(struct thread *thread) |
529 | void *arg, int max_stack) | ||
530 | { | 530 | { |
531 | unw_addr_space_t addr_space; | 531 | unw_addr_space_t addr_space; |
532 | unw_cursor_t c; | 532 | |
533 | int ret; | 533 | if (callchain_param.record_mode != CALLCHAIN_DWARF) |
534 | return 0; | ||
534 | 535 | ||
535 | addr_space = unw_create_addr_space(&accessors, 0); | 536 | addr_space = unw_create_addr_space(&accessors, 0); |
536 | if (!addr_space) { | 537 | if (!addr_space) { |
@@ -538,6 +539,33 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | |||
538 | return -ENOMEM; | 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 | ret = unw_init_remote(&c, addr_space, ui); | 569 | ret = unw_init_remote(&c, addr_space, ui); |
542 | if (ret) | 570 | if (ret) |
543 | display_error(ret); | 571 | display_error(ret); |
@@ -549,7 +577,6 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, | |||
549 | ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; | 577 | ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; |
550 | } | 578 | } |
551 | 579 | ||
552 | unw_destroy_addr_space(addr_space); | ||
553 | return ret; | 580 | return ret; |
554 | } | 581 | } |
555 | 582 | ||
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h index f03061260b4e..c17c4855bdbc 100644 --- a/tools/perf/util/unwind.h +++ b/tools/perf/util/unwind.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include "event.h" | 5 | #include "event.h" |
6 | #include "symbol.h" | 6 | #include "symbol.h" |
7 | #include "thread.h" | ||
7 | 8 | ||
8 | struct unwind_entry { | 9 | struct unwind_entry { |
9 | struct map *map; | 10 | struct map *map; |
@@ -21,6 +22,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg, | |||
21 | /* libunwind specific */ | 22 | /* libunwind specific */ |
22 | #ifdef HAVE_LIBUNWIND_SUPPORT | 23 | #ifdef HAVE_LIBUNWIND_SUPPORT |
23 | int libunwind__arch_reg_id(int regnum); | 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 | #endif | 34 | #endif |
25 | #else | 35 | #else |
26 | static inline int | 36 | static inline int |
@@ -33,5 +43,12 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, | |||
33 | { | 43 | { |
34 | return 0; | 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 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ | 53 | #endif /* HAVE_DWARF_UNWIND_SUPPORT */ |
37 | #endif /* __UNWIND_H */ | 54 | #endif /* __UNWIND_H */ |