Skip to content

Commit 66f066d

Browse files
namhyungacmel
authored andcommitted
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 <[email protected]> Acked-by: Jean Pihet <[email protected]> Acked-by: Jiri Olsa <[email protected]> Cc: Arun Sharma <[email protected]> Cc: David Ahern <[email protected]> Cc: Frederic Weisbecker <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jean Pihet <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/r/[email protected] [ 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 <[email protected]>
1 parent 0cdccac commit 66f066d

File tree

3 files changed

+55
-5
lines changed

3 files changed

+55
-5
lines changed

tools/perf/util/thread.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "util.h"
88
#include "debug.h"
99
#include "comm.h"
10+
#include "unwind.h"
1011

1112
int thread__init_map_groups(struct thread *thread, struct machine *machine)
1213
{
@@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
3738
thread->cpu = -1;
3839
INIT_LIST_HEAD(&thread->comm_list);
3940

41+
if (unwind__prepare_access(thread) < 0)
42+
goto err_thread;
43+
4044
comm_str = malloc(32);
4145
if (!comm_str)
4246
goto err_thread;
@@ -48,6 +52,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
4852
goto err_thread;
4953

5054
list_add(&comm->list, &thread->comm_list);
55+
5156
}
5257

5358
return thread;
@@ -69,6 +74,7 @@ void thread__delete(struct thread *thread)
6974
list_del(&comm->list);
7075
comm__free(comm);
7176
}
77+
unwind__finish_access(thread);
7278

7379
free(thread);
7480
}

tools/perf/util/unwind-libunwind.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <linux/list.h>
2525
#include <libunwind.h>
2626
#include <libunwind-ptrace.h>
27+
#include "callchain.h"
2728
#include "thread.h"
2829
#include "session.h"
2930
#include "perf_regs.h"
@@ -525,19 +526,46 @@ static unw_accessors_t accessors = {
525526
.get_proc_name = get_proc_name,
526527
};
527528

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)
530530
{
531531
unw_addr_space_t addr_space;
532-
unw_cursor_t c;
533-
int ret;
532+
533+
if (callchain_param.record_mode != CALLCHAIN_DWARF)
534+
return 0;
534535

535536
addr_space = unw_create_addr_space(&accessors, 0);
536537
if (!addr_space) {
537538
pr_err("unwind: Can't create unwind address space.\n");
538539
return -ENOMEM;
539540
}
540541

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+
541569
ret = unw_init_remote(&c, addr_space, ui);
542570
if (ret)
543571
display_error(ret);
@@ -549,7 +577,6 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
549577
ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
550578
}
551579

552-
unw_destroy_addr_space(addr_space);
553580
return ret;
554581
}
555582

tools/perf/util/unwind.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/types.h>
55
#include "event.h"
66
#include "symbol.h"
7+
#include "thread.h"
78

89
struct unwind_entry {
910
struct map *map;
@@ -21,6 +22,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
2122
/* libunwind specific */
2223
#ifdef HAVE_LIBUNWIND_SUPPORT
2324
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) {}
2434
#endif
2535
#else
2636
static inline int
@@ -33,5 +43,12 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
3343
{
3444
return 0;
3545
}
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) {}
3653
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
3754
#endif /* __UNWIND_H */

0 commit comments

Comments
 (0)