Commit 66f066d8994bd146304bab72fa09c1e644c4b3ff

Authored by Namhyung Kim
Committed by Arnaldo Carvalho de Melo
1 parent 0cdccac6fe

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 */