diff options
67 files changed, 2118 insertions, 504 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index f2989c525e48..5a824e355d04 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -174,7 +174,7 @@ static int cmdline_init(struct pevent *pevent) | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | 176 | ||
177 | static char *find_cmdline(struct pevent *pevent, int pid) | 177 | static const char *find_cmdline(struct pevent *pevent, int pid) |
178 | { | 178 | { |
179 | const struct cmdline *comm; | 179 | const struct cmdline *comm; |
180 | struct cmdline key; | 180 | struct cmdline key; |
@@ -2637,7 +2637,7 @@ process_func_handler(struct event_format *event, struct pevent_function_handler | |||
2637 | struct print_arg *farg; | 2637 | struct print_arg *farg; |
2638 | enum event_type type; | 2638 | enum event_type type; |
2639 | char *token; | 2639 | char *token; |
2640 | char *test; | 2640 | const char *test; |
2641 | int i; | 2641 | int i; |
2642 | 2642 | ||
2643 | arg->type = PRINT_FUNC; | 2643 | arg->type = PRINT_FUNC; |
@@ -3889,7 +3889,7 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, | |||
3889 | struct event_format *event, struct print_arg *arg) | 3889 | struct event_format *event, struct print_arg *arg) |
3890 | { | 3890 | { |
3891 | unsigned char *buf; | 3891 | unsigned char *buf; |
3892 | char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; | 3892 | const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; |
3893 | 3893 | ||
3894 | if (arg->type == PRINT_FUNC) { | 3894 | if (arg->type == PRINT_FUNC) { |
3895 | process_defined_func(s, data, size, event, arg); | 3895 | process_defined_func(s, data, size, event, arg); |
@@ -3931,7 +3931,8 @@ static int is_printable_array(char *p, unsigned int len) | |||
3931 | return 1; | 3931 | return 1; |
3932 | } | 3932 | } |
3933 | 3933 | ||
3934 | static void print_event_fields(struct trace_seq *s, void *data, int size, | 3934 | static void print_event_fields(struct trace_seq *s, void *data, |
3935 | int size __maybe_unused, | ||
3935 | struct event_format *event) | 3936 | struct event_format *event) |
3936 | { | 3937 | { |
3937 | struct format_field *field; | 3938 | struct format_field *field; |
@@ -4408,7 +4409,7 @@ void pevent_event_info(struct trace_seq *s, struct event_format *event, | |||
4408 | void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | 4409 | void pevent_print_event(struct pevent *pevent, struct trace_seq *s, |
4409 | struct pevent_record *record) | 4410 | struct pevent_record *record) |
4410 | { | 4411 | { |
4411 | static char *spaces = " "; /* 20 spaces */ | 4412 | static const char *spaces = " "; /* 20 spaces */ |
4412 | struct event_format *event; | 4413 | struct event_format *event; |
4413 | unsigned long secs; | 4414 | unsigned long secs; |
4414 | unsigned long usecs; | 4415 | unsigned long usecs; |
@@ -5070,8 +5071,8 @@ static const char * const pevent_error_str[] = { | |||
5070 | }; | 5071 | }; |
5071 | #undef _PE | 5072 | #undef _PE |
5072 | 5073 | ||
5073 | int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, | 5074 | int pevent_strerror(struct pevent *pevent __maybe_unused, |
5074 | char *buf, size_t buflen) | 5075 | enum pevent_errno errnum, char *buf, size_t buflen) |
5075 | { | 5076 | { |
5076 | int idx; | 5077 | int idx; |
5077 | const char *msg; | 5078 | const char *msg; |
@@ -5100,6 +5101,7 @@ int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, | |||
5100 | case PEVENT_ERRNO__READ_FORMAT_FAILED: | 5101 | case PEVENT_ERRNO__READ_FORMAT_FAILED: |
5101 | case PEVENT_ERRNO__READ_PRINT_FAILED: | 5102 | case PEVENT_ERRNO__READ_PRINT_FAILED: |
5102 | case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: | 5103 | case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED: |
5104 | case PEVENT_ERRNO__INVALID_ARG_TYPE: | ||
5103 | snprintf(buf, buflen, "%s", msg); | 5105 | snprintf(buf, buflen, "%s", msg); |
5104 | break; | 5106 | break; |
5105 | 5107 | ||
@@ -5362,7 +5364,7 @@ int pevent_register_print_function(struct pevent *pevent, | |||
5362 | if (type == PEVENT_FUNC_ARG_VOID) | 5364 | if (type == PEVENT_FUNC_ARG_VOID) |
5363 | break; | 5365 | break; |
5364 | 5366 | ||
5365 | if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) { | 5367 | if (type >= PEVENT_FUNC_ARG_MAX_TYPES) { |
5366 | do_warning("Invalid argument type %d", type); | 5368 | do_warning("Invalid argument type %d", type); |
5367 | ret = PEVENT_ERRNO__INVALID_ARG_TYPE; | 5369 | ret = PEVENT_ERRNO__INVALID_ARG_TYPE; |
5368 | goto out_free; | 5370 | goto out_free; |
@@ -5560,7 +5562,7 @@ void pevent_free(struct pevent *pevent) | |||
5560 | } | 5562 | } |
5561 | 5563 | ||
5562 | if (pevent->func_map) { | 5564 | if (pevent->func_map) { |
5563 | for (i = 0; i < pevent->func_count; i++) { | 5565 | for (i = 0; i < (int)pevent->func_count; i++) { |
5564 | free(pevent->func_map[i].func); | 5566 | free(pevent->func_map[i].func); |
5565 | free(pevent->func_map[i].mod); | 5567 | free(pevent->func_map[i].mod); |
5566 | } | 5568 | } |
@@ -5582,7 +5584,7 @@ void pevent_free(struct pevent *pevent) | |||
5582 | } | 5584 | } |
5583 | 5585 | ||
5584 | if (pevent->printk_map) { | 5586 | if (pevent->printk_map) { |
5585 | for (i = 0; i < pevent->printk_count; i++) | 5587 | for (i = 0; i < (int)pevent->printk_count; i++) |
5586 | free(pevent->printk_map[i].printk); | 5588 | free(pevent->printk_map[i].printk); |
5587 | free(pevent->printk_map); | 5589 | free(pevent->printk_map); |
5588 | } | 5590 | } |
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt index a39dbbb44c4c..8484c3a04a6a 100644 --- a/tools/perf/Documentation/android.txt +++ b/tools/perf/Documentation/android.txt | |||
@@ -48,7 +48,10 @@ For x86: | |||
48 | II. Compile perf for Android | 48 | II. Compile perf for Android |
49 | ------------------------------------------------ | 49 | ------------------------------------------------ |
50 | You need to run make with the NDK toolchain and sysroot defined above: | 50 | You need to run make with the NDK toolchain and sysroot defined above: |
51 | make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" | 51 | For arm: |
52 | make ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" | ||
53 | For x86: | ||
54 | make ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" | ||
52 | 55 | ||
53 | III. Install perf | 56 | III. Install perf |
54 | ----------------------------------------------- | 57 | ----------------------------------------------- |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 7e25f59e5e89..cca5bb8334ad 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -169,7 +169,7 @@ endif | |||
169 | 169 | ||
170 | ### --- END CONFIGURATION SECTION --- | 170 | ### --- END CONFIGURATION SECTION --- |
171 | 171 | ||
172 | BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE | 172 | BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -Iutil -I. -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE |
173 | BASIC_LDFLAGS = | 173 | BASIC_LDFLAGS = |
174 | 174 | ||
175 | ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) | 175 | ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) |
@@ -371,7 +371,6 @@ LIB_OBJS += $(OUTPUT)util/help.o | |||
371 | LIB_OBJS += $(OUTPUT)util/levenshtein.o | 371 | LIB_OBJS += $(OUTPUT)util/levenshtein.o |
372 | LIB_OBJS += $(OUTPUT)util/parse-options.o | 372 | LIB_OBJS += $(OUTPUT)util/parse-options.o |
373 | LIB_OBJS += $(OUTPUT)util/parse-events.o | 373 | LIB_OBJS += $(OUTPUT)util/parse-events.o |
374 | LIB_OBJS += $(OUTPUT)util/parse-events-test.o | ||
375 | LIB_OBJS += $(OUTPUT)util/path.o | 374 | LIB_OBJS += $(OUTPUT)util/path.o |
376 | LIB_OBJS += $(OUTPUT)util/rbtree.o | 375 | LIB_OBJS += $(OUTPUT)util/rbtree.o |
377 | LIB_OBJS += $(OUTPUT)util/bitmap.o | 376 | LIB_OBJS += $(OUTPUT)util/bitmap.o |
@@ -389,7 +388,6 @@ LIB_OBJS += $(OUTPUT)util/sigchain.o | |||
389 | LIB_OBJS += $(OUTPUT)util/dso.o | 388 | LIB_OBJS += $(OUTPUT)util/dso.o |
390 | LIB_OBJS += $(OUTPUT)util/symbol.o | 389 | LIB_OBJS += $(OUTPUT)util/symbol.o |
391 | LIB_OBJS += $(OUTPUT)util/symbol-elf.o | 390 | LIB_OBJS += $(OUTPUT)util/symbol-elf.o |
392 | LIB_OBJS += $(OUTPUT)util/dso-test-data.o | ||
393 | LIB_OBJS += $(OUTPUT)util/color.o | 391 | LIB_OBJS += $(OUTPUT)util/color.o |
394 | LIB_OBJS += $(OUTPUT)util/pager.o | 392 | LIB_OBJS += $(OUTPUT)util/pager.o |
395 | LIB_OBJS += $(OUTPUT)util/header.o | 393 | LIB_OBJS += $(OUTPUT)util/header.o |
@@ -430,6 +428,10 @@ LIB_OBJS += $(OUTPUT)ui/stdio/hist.o | |||
430 | 428 | ||
431 | LIB_OBJS += $(OUTPUT)arch/common.o | 429 | LIB_OBJS += $(OUTPUT)arch/common.o |
432 | 430 | ||
431 | LIB_OBJS += $(OUTPUT)tests/parse-events.o | ||
432 | LIB_OBJS += $(OUTPUT)tests/dso-data.o | ||
433 | LIB_OBJS += $(OUTPUT)tests/attr.o | ||
434 | |||
433 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o | 435 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o |
434 | BUILTIN_OBJS += $(OUTPUT)builtin-bench.o | 436 | BUILTIN_OBJS += $(OUTPUT)builtin-bench.o |
435 | # Benchmark modules | 437 | # Benchmark modules |
@@ -459,8 +461,8 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o | |||
459 | BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o | 461 | BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o |
460 | BUILTIN_OBJS += $(OUTPUT)builtin-lock.o | 462 | BUILTIN_OBJS += $(OUTPUT)builtin-lock.o |
461 | BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o | 463 | BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o |
462 | BUILTIN_OBJS += $(OUTPUT)builtin-test.o | ||
463 | BUILTIN_OBJS += $(OUTPUT)builtin-inject.o | 464 | BUILTIN_OBJS += $(OUTPUT)builtin-inject.o |
465 | BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o | ||
464 | 466 | ||
465 | PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) | 467 | PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) |
466 | 468 | ||
@@ -490,6 +492,8 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) | |||
490 | LIBC_SUPPORT := 1 | 492 | LIBC_SUPPORT := 1 |
491 | endif | 493 | endif |
492 | ifeq ($(LIBC_SUPPORT),1) | 494 | ifeq ($(LIBC_SUPPORT),1) |
495 | msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev); | ||
496 | |||
493 | NO_LIBELF := 1 | 497 | NO_LIBELF := 1 |
494 | NO_DWARF := 1 | 498 | NO_DWARF := 1 |
495 | NO_DEMANGLE := 1 | 499 | NO_DEMANGLE := 1 |
@@ -497,7 +501,14 @@ ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y) | |||
497 | msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); | 501 | msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); |
498 | endif | 502 | endif |
499 | else | 503 | else |
500 | FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) | 504 | # for linking with debug library, run like: |
505 | # make DEBUG=1 LIBDW_DIR=/opt/libdw/ | ||
506 | ifdef LIBDW_DIR | ||
507 | LIBDW_CFLAGS := -I$(LIBDW_DIR)/include | ||
508 | LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib | ||
509 | endif | ||
510 | |||
511 | FLAGS_DWARF=$(ALL_CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) | ||
501 | ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) | 512 | ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y) |
502 | msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); | 513 | msg := $(warning No libdw.h found or old libdw.h found or elfutils is older than 0.138, disables dwarf support. Please install new elfutils-devel/libdw-dev); |
503 | NO_DWARF := 1 | 514 | NO_DWARF := 1 |
@@ -552,7 +563,8 @@ ifndef NO_DWARF | |||
552 | ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) | 563 | ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) |
553 | msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); | 564 | msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); |
554 | else | 565 | else |
555 | BASIC_CFLAGS += -DDWARF_SUPPORT | 566 | BASIC_CFLAGS := -DDWARF_SUPPORT $(LIBDW_CFLAGS) $(BASIC_CFLAGS) |
567 | BASIC_LDFLAGS := $(LIBDW_LDFLAGS) $(BASIC_LDFLAGS) | ||
556 | EXTLIBS += -lelf -ldw | 568 | EXTLIBS += -lelf -ldw |
557 | LIB_OBJS += $(OUTPUT)util/probe-finder.o | 569 | LIB_OBJS += $(OUTPUT)util/probe-finder.o |
558 | LIB_OBJS += $(OUTPUT)util/dwarf-aux.o | 570 | LIB_OBJS += $(OUTPUT)util/dwarf-aux.o |
@@ -891,10 +903,14 @@ $(OUTPUT)%.s: %.S | |||
891 | $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS | 903 | $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS |
892 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ | 904 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ |
893 | '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ | 905 | '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ |
894 | '-DBINDIR="$(bindir_relative_SQ)"' \ | ||
895 | '-DPREFIX="$(prefix_SQ)"' \ | 906 | '-DPREFIX="$(prefix_SQ)"' \ |
896 | $< | 907 | $< |
897 | 908 | ||
909 | $(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS | ||
910 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ | ||
911 | '-DBINDIR="$(bindir_SQ)"' \ | ||
912 | $< | ||
913 | |||
898 | $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS | 914 | $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS |
899 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< | 915 | $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< |
900 | 916 | ||
@@ -1059,6 +1075,10 @@ install: all try-install-man | |||
1059 | $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' | 1075 | $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' |
1060 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d' | 1076 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d' |
1061 | $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' | 1077 | $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' |
1078 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests' | ||
1079 | $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests' | ||
1080 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' | ||
1081 | $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' | ||
1062 | 1082 | ||
1063 | install-python_ext: | 1083 | install-python_ext: |
1064 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' | 1084 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' |
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index 2367b253f039..3e975cb6232e 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c | |||
@@ -93,16 +93,46 @@ static int lookup_triplets(const char *const *triplets, const char *name) | |||
93 | return -1; | 93 | return -1; |
94 | } | 94 | } |
95 | 95 | ||
96 | /* | ||
97 | * Return architecture name in a normalized form. | ||
98 | * The conversion logic comes from the Makefile. | ||
99 | */ | ||
100 | static const char *normalize_arch(char *arch) | ||
101 | { | ||
102 | if (!strcmp(arch, "x86_64")) | ||
103 | return "x86"; | ||
104 | if (arch[0] == 'i' && arch[2] == '8' && arch[3] == '6') | ||
105 | return "x86"; | ||
106 | if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) | ||
107 | return "sparc"; | ||
108 | if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) | ||
109 | return "arm"; | ||
110 | if (!strncmp(arch, "s390", 4)) | ||
111 | return "s390"; | ||
112 | if (!strncmp(arch, "parisc", 6)) | ||
113 | return "parisc"; | ||
114 | if (!strncmp(arch, "powerpc", 7) || !strncmp(arch, "ppc", 3)) | ||
115 | return "powerpc"; | ||
116 | if (!strncmp(arch, "mips", 4)) | ||
117 | return "mips"; | ||
118 | if (!strncmp(arch, "sh", 2) && isdigit(arch[2])) | ||
119 | return "sh"; | ||
120 | |||
121 | return arch; | ||
122 | } | ||
123 | |||
96 | static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, | 124 | static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, |
97 | const char *name, | 125 | const char *name, |
98 | const char **path) | 126 | const char **path) |
99 | { | 127 | { |
100 | int idx; | 128 | int idx; |
101 | char *arch, *cross_env; | 129 | const char *arch, *cross_env; |
102 | struct utsname uts; | 130 | struct utsname uts; |
103 | const char *const *path_list; | 131 | const char *const *path_list; |
104 | char *buf = NULL; | 132 | char *buf = NULL; |
105 | 133 | ||
134 | arch = normalize_arch(env->arch); | ||
135 | |||
106 | if (uname(&uts) < 0) | 136 | if (uname(&uts) < 0) |
107 | goto out; | 137 | goto out; |
108 | 138 | ||
@@ -110,7 +140,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, | |||
110 | * We don't need to try to find objdump path for native system. | 140 | * We don't need to try to find objdump path for native system. |
111 | * Just use default binutils path (e.g.: "objdump"). | 141 | * Just use default binutils path (e.g.: "objdump"). |
112 | */ | 142 | */ |
113 | if (!strcmp(uts.machine, env->arch)) | 143 | if (!strcmp(normalize_arch(uts.machine), arch)) |
114 | goto out; | 144 | goto out; |
115 | 145 | ||
116 | cross_env = getenv("CROSS_COMPILE"); | 146 | cross_env = getenv("CROSS_COMPILE"); |
@@ -127,8 +157,6 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, | |||
127 | free(buf); | 157 | free(buf); |
128 | } | 158 | } |
129 | 159 | ||
130 | arch = env->arch; | ||
131 | |||
132 | if (!strcmp(arch, "arm")) | 160 | if (!strcmp(arch, "arm")) |
133 | path_list = arm_triplets; | 161 | path_list = arm_triplets; |
134 | else if (!strcmp(arch, "powerpc")) | 162 | else if (!strcmp(arch, "powerpc")) |
@@ -139,9 +167,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, | |||
139 | path_list = s390_triplets; | 167 | path_list = s390_triplets; |
140 | else if (!strcmp(arch, "sparc")) | 168 | else if (!strcmp(arch, "sparc")) |
141 | path_list = sparc_triplets; | 169 | path_list = sparc_triplets; |
142 | else if (!strcmp(arch, "x86") || !strcmp(arch, "i386") || | 170 | else if (!strcmp(arch, "x86")) |
143 | !strcmp(arch, "i486") || !strcmp(arch, "i586") || | ||
144 | !strcmp(arch, "i686")) | ||
145 | path_list = x86_triplets; | 171 | path_list = x86_triplets; |
146 | else if (!strcmp(arch, "mips")) | 172 | else if (!strcmp(arch, "mips")) |
147 | path_list = mips_triplets; | 173 | path_list = mips_triplets; |
@@ -173,6 +199,13 @@ out_error: | |||
173 | 199 | ||
174 | int perf_session_env__lookup_objdump(struct perf_session_env *env) | 200 | int perf_session_env__lookup_objdump(struct perf_session_env *env) |
175 | { | 201 | { |
202 | /* | ||
203 | * For live mode, env->arch will be NULL and we can use | ||
204 | * the native objdump tool. | ||
205 | */ | ||
206 | if (env->arch == NULL) | ||
207 | return 0; | ||
208 | |||
176 | return perf_session_env__lookup_binutils_path(env, "objdump", | 209 | return perf_session_env__lookup_binutils_path(env, "objdump", |
177 | &objdump_path); | 210 | &objdump_path); |
178 | } | 211 | } |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index cb234765ce3d..dc870cf31b79 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -139,7 +139,7 @@ find_next: | |||
139 | } | 139 | } |
140 | 140 | ||
141 | if (use_browser > 0) { | 141 | if (use_browser > 0) { |
142 | key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0); | 142 | key = hist_entry__tui_annotate(he, evidx, NULL); |
143 | switch (key) { | 143 | switch (key) { |
144 | case K_RIGHT: | 144 | case K_RIGHT: |
145 | next = rb_next(nd); | 145 | next = rb_next(nd); |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 380683de1df3..93b852f8a5d5 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -154,7 +154,7 @@ static double get_period_percent(struct hist_entry *he, u64 period) | |||
154 | 154 | ||
155 | double perf_diff__compute_delta(struct hist_entry *he) | 155 | double perf_diff__compute_delta(struct hist_entry *he) |
156 | { | 156 | { |
157 | struct hist_entry *pair = he->pair; | 157 | struct hist_entry *pair = hist_entry__next_pair(he); |
158 | double new_percent = get_period_percent(he, he->stat.period); | 158 | double new_percent = get_period_percent(he, he->stat.period); |
159 | double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0; | 159 | double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0; |
160 | 160 | ||
@@ -165,7 +165,7 @@ double perf_diff__compute_delta(struct hist_entry *he) | |||
165 | 165 | ||
166 | double perf_diff__compute_ratio(struct hist_entry *he) | 166 | double perf_diff__compute_ratio(struct hist_entry *he) |
167 | { | 167 | { |
168 | struct hist_entry *pair = he->pair; | 168 | struct hist_entry *pair = hist_entry__next_pair(he); |
169 | double new_period = he->stat.period; | 169 | double new_period = he->stat.period; |
170 | double old_period = pair ? pair->stat.period : 0; | 170 | double old_period = pair ? pair->stat.period : 0; |
171 | 171 | ||
@@ -176,7 +176,7 @@ double perf_diff__compute_ratio(struct hist_entry *he) | |||
176 | 176 | ||
177 | s64 perf_diff__compute_wdiff(struct hist_entry *he) | 177 | s64 perf_diff__compute_wdiff(struct hist_entry *he) |
178 | { | 178 | { |
179 | struct hist_entry *pair = he->pair; | 179 | struct hist_entry *pair = hist_entry__next_pair(he); |
180 | u64 new_period = he->stat.period; | 180 | u64 new_period = he->stat.period; |
181 | u64 old_period = pair ? pair->stat.period : 0; | 181 | u64 old_period = pair ? pair->stat.period : 0; |
182 | 182 | ||
@@ -193,7 +193,7 @@ s64 perf_diff__compute_wdiff(struct hist_entry *he) | |||
193 | 193 | ||
194 | static int formula_delta(struct hist_entry *he, char *buf, size_t size) | 194 | static int formula_delta(struct hist_entry *he, char *buf, size_t size) |
195 | { | 195 | { |
196 | struct hist_entry *pair = he->pair; | 196 | struct hist_entry *pair = hist_entry__next_pair(he); |
197 | 197 | ||
198 | if (!pair) | 198 | if (!pair) |
199 | return -1; | 199 | return -1; |
@@ -207,7 +207,7 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size) | |||
207 | 207 | ||
208 | static int formula_ratio(struct hist_entry *he, char *buf, size_t size) | 208 | static int formula_ratio(struct hist_entry *he, char *buf, size_t size) |
209 | { | 209 | { |
210 | struct hist_entry *pair = he->pair; | 210 | struct hist_entry *pair = hist_entry__next_pair(he); |
211 | double new_period = he->stat.period; | 211 | double new_period = he->stat.period; |
212 | double old_period = pair ? pair->stat.period : 0; | 212 | double old_period = pair ? pair->stat.period : 0; |
213 | 213 | ||
@@ -219,7 +219,7 @@ static int formula_ratio(struct hist_entry *he, char *buf, size_t size) | |||
219 | 219 | ||
220 | static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) | 220 | static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) |
221 | { | 221 | { |
222 | struct hist_entry *pair = he->pair; | 222 | struct hist_entry *pair = hist_entry__next_pair(he); |
223 | u64 new_period = he->stat.period; | 223 | u64 new_period = he->stat.period; |
224 | u64 old_period = pair ? pair->stat.period : 0; | 224 | u64 old_period = pair ? pair->stat.period : 0; |
225 | 225 | ||
@@ -334,36 +334,6 @@ static void hists__name_resort(struct hists *self, bool sort) | |||
334 | self->entries = tmp; | 334 | self->entries = tmp; |
335 | } | 335 | } |
336 | 336 | ||
337 | static struct hist_entry *hists__find_entry(struct hists *self, | ||
338 | struct hist_entry *he) | ||
339 | { | ||
340 | struct rb_node *n = self->entries.rb_node; | ||
341 | |||
342 | while (n) { | ||
343 | struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node); | ||
344 | int64_t cmp = hist_entry__cmp(he, iter); | ||
345 | |||
346 | if (cmp < 0) | ||
347 | n = n->rb_left; | ||
348 | else if (cmp > 0) | ||
349 | n = n->rb_right; | ||
350 | else | ||
351 | return iter; | ||
352 | } | ||
353 | |||
354 | return NULL; | ||
355 | } | ||
356 | |||
357 | static void hists__match(struct hists *older, struct hists *newer) | ||
358 | { | ||
359 | struct rb_node *nd; | ||
360 | |||
361 | for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) { | ||
362 | struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node); | ||
363 | pos->pair = hists__find_entry(older, pos); | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static struct perf_evsel *evsel_match(struct perf_evsel *evsel, | 337 | static struct perf_evsel *evsel_match(struct perf_evsel *evsel, |
368 | struct perf_evlist *evlist) | 338 | struct perf_evlist *evlist) |
369 | { | 339 | { |
@@ -402,7 +372,7 @@ static void hists__baseline_only(struct hists *hists) | |||
402 | struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); | 372 | struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); |
403 | 373 | ||
404 | next = rb_next(&he->rb_node); | 374 | next = rb_next(&he->rb_node); |
405 | if (!he->pair) { | 375 | if (!hist_entry__next_pair(he)) { |
406 | rb_erase(&he->rb_node, &hists->entries); | 376 | rb_erase(&he->rb_node, &hists->entries); |
407 | hist_entry__free(he); | 377 | hist_entry__free(he); |
408 | } | 378 | } |
@@ -517,10 +487,12 @@ static void hists__compute_resort(struct hists *hists) | |||
517 | 487 | ||
518 | static void hists__process(struct hists *old, struct hists *new) | 488 | static void hists__process(struct hists *old, struct hists *new) |
519 | { | 489 | { |
520 | hists__match(old, new); | 490 | hists__match(new, old); |
521 | 491 | ||
522 | if (show_baseline_only) | 492 | if (show_baseline_only) |
523 | hists__baseline_only(new); | 493 | hists__baseline_only(new); |
494 | else | ||
495 | hists__link(new, old); | ||
524 | 496 | ||
525 | if (sort_compute) { | 497 | if (sort_compute) { |
526 | hists__precompute(new); | 498 | hists__precompute(new); |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f07eae73e692..fc251005dd3d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -428,10 +428,11 @@ static int __cmd_report(struct perf_report *rep) | |||
428 | if (use_browser > 0) { | 428 | if (use_browser > 0) { |
429 | if (use_browser == 1) { | 429 | if (use_browser == 1) { |
430 | perf_evlist__tui_browse_hists(session->evlist, help, | 430 | perf_evlist__tui_browse_hists(session->evlist, help, |
431 | NULL, NULL, 0); | 431 | NULL, |
432 | &session->header.env); | ||
432 | } else if (use_browser == 2) { | 433 | } else if (use_browser == 2) { |
433 | perf_evlist__gtk_browse_hists(session->evlist, help, | 434 | perf_evlist__gtk_browse_hists(session->evlist, help, |
434 | NULL, NULL, 0); | 435 | NULL); |
435 | } | 436 | } |
436 | } else | 437 | } else |
437 | perf_evlist__tty_browse_hists(session->evlist, rep, help); | 438 | perf_evlist__tty_browse_hists(session->evlist, rep, help); |
@@ -672,12 +673,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
672 | has_br_stack = perf_header__has_feat(&session->header, | 673 | has_br_stack = perf_header__has_feat(&session->header, |
673 | HEADER_BRANCH_STACK); | 674 | HEADER_BRANCH_STACK); |
674 | 675 | ||
675 | if (!objdump_path) { | ||
676 | ret = perf_session_env__lookup_objdump(&session->header.env); | ||
677 | if (ret) | ||
678 | goto error; | ||
679 | } | ||
680 | |||
681 | if (sort__branch_mode == -1 && has_br_stack) | 676 | if (sort__branch_mode == -1 && has_br_stack) |
682 | sort__branch_mode = 1; | 677 | sort__branch_mode = 1; |
683 | 678 | ||
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f2ecd498c72d..c9ff3950cd4b 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -582,6 +582,11 @@ static void *display_thread_tui(void *arg) | |||
582 | struct perf_evsel *pos; | 582 | struct perf_evsel *pos; |
583 | struct perf_top *top = arg; | 583 | struct perf_top *top = arg; |
584 | const char *help = "For a higher level overview, try: perf top --sort comm,dso"; | 584 | const char *help = "For a higher level overview, try: perf top --sort comm,dso"; |
585 | struct hist_browser_timer hbt = { | ||
586 | .timer = perf_top__sort_new_samples, | ||
587 | .arg = top, | ||
588 | .refresh = top->delay_secs, | ||
589 | }; | ||
585 | 590 | ||
586 | perf_top__sort_new_samples(top); | 591 | perf_top__sort_new_samples(top); |
587 | 592 | ||
@@ -593,9 +598,8 @@ static void *display_thread_tui(void *arg) | |||
593 | list_for_each_entry(pos, &top->evlist->entries, node) | 598 | list_for_each_entry(pos, &top->evlist->entries, node) |
594 | pos->hists.uid_filter_str = top->target.uid_str; | 599 | pos->hists.uid_filter_str = top->target.uid_str; |
595 | 600 | ||
596 | perf_evlist__tui_browse_hists(top->evlist, help, | 601 | perf_evlist__tui_browse_hists(top->evlist, help, &hbt, |
597 | perf_top__sort_new_samples, | 602 | &top->session->header.env); |
598 | top, top->delay_secs); | ||
599 | 603 | ||
600 | exit_browser(0); | 604 | exit_browser(0); |
601 | exit(0); | 605 | exit(0); |
diff --git a/tools/perf/perf.c b/tools/perf/perf.c index e9683738d89f..a0ae2902f9c9 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c | |||
@@ -484,6 +484,8 @@ int main(int argc, const char **argv) | |||
484 | } | 484 | } |
485 | cmd = argv[0]; | 485 | cmd = argv[0]; |
486 | 486 | ||
487 | test_attr__init(); | ||
488 | |||
487 | /* | 489 | /* |
488 | * We use PATH to find perf commands, but we prepend some higher | 490 | * We use PATH to find perf commands, but we prepend some higher |
489 | * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH | 491 | * precedence paths: the "--exec-path" option, the PERF_EXEC_PATH |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 469fbf2daea4..054182e41dca 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -174,13 +174,26 @@ static inline unsigned long long rdclock(void) | |||
174 | (void) (&_min1 == &_min2); \ | 174 | (void) (&_min1 == &_min2); \ |
175 | _min1 < _min2 ? _min1 : _min2; }) | 175 | _min1 < _min2 ? _min1 : _min2; }) |
176 | 176 | ||
177 | extern bool test_attr__enabled; | ||
178 | void test_attr__init(void); | ||
179 | void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, | ||
180 | int fd, int group_fd, unsigned long flags); | ||
181 | int test_attr__run(void); | ||
182 | |||
177 | static inline int | 183 | static inline int |
178 | sys_perf_event_open(struct perf_event_attr *attr, | 184 | sys_perf_event_open(struct perf_event_attr *attr, |
179 | pid_t pid, int cpu, int group_fd, | 185 | pid_t pid, int cpu, int group_fd, |
180 | unsigned long flags) | 186 | unsigned long flags) |
181 | { | 187 | { |
182 | return syscall(__NR_perf_event_open, attr, pid, cpu, | 188 | int fd; |
183 | group_fd, flags); | 189 | |
190 | fd = syscall(__NR_perf_event_open, attr, pid, cpu, | ||
191 | group_fd, flags); | ||
192 | |||
193 | if (unlikely(test_attr__enabled)) | ||
194 | test_attr__open(attr, pid, cpu, fd, group_fd, flags); | ||
195 | |||
196 | return fd; | ||
184 | } | 197 | } |
185 | 198 | ||
186 | #define MAX_COUNTERS 256 | 199 | #define MAX_COUNTERS 256 |
diff --git a/tools/perf/tests/attr.c b/tools/perf/tests/attr.c new file mode 100644 index 000000000000..6e2feee8db2a --- /dev/null +++ b/tools/perf/tests/attr.c | |||
@@ -0,0 +1,174 @@ | |||
1 | |||
2 | /* | ||
3 | * The struct perf_event_attr test support. | ||
4 | * | ||
5 | * This test is embedded inside into perf directly and is governed | ||
6 | * by the PERF_TEST_ATTR environment variable and hook inside | ||
7 | * sys_perf_event_open function. | ||
8 | * | ||
9 | * The general idea is to store 'struct perf_event_attr' details for | ||
10 | * each event created within single perf command. Each event details | ||
11 | * are stored into separate text file. Once perf command is finished | ||
12 | * these files can be checked for values we expect for command. | ||
13 | * | ||
14 | * Besides 'struct perf_event_attr' values we also store 'fd' and | ||
15 | * 'group_fd' values to allow checking for groups created. | ||
16 | * | ||
17 | * This all is triggered by setting PERF_TEST_ATTR environment variable. | ||
18 | * It must contain name of existing directory with access and write | ||
19 | * permissions. All the event text files are stored there. | ||
20 | */ | ||
21 | |||
22 | #include <stdlib.h> | ||
23 | #include <stdio.h> | ||
24 | #include <inttypes.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include "../perf.h" | ||
28 | #include "util.h" | ||
29 | #include "exec_cmd.h" | ||
30 | |||
31 | #define ENV "PERF_TEST_ATTR" | ||
32 | |||
33 | extern int verbose; | ||
34 | |||
35 | bool test_attr__enabled; | ||
36 | |||
37 | static char *dir; | ||
38 | |||
39 | void test_attr__init(void) | ||
40 | { | ||
41 | dir = getenv(ENV); | ||
42 | test_attr__enabled = (dir != NULL); | ||
43 | } | ||
44 | |||
45 | #define BUFSIZE 1024 | ||
46 | |||
47 | #define __WRITE_ASS(str, fmt, data) \ | ||
48 | do { \ | ||
49 | char buf[BUFSIZE]; \ | ||
50 | size_t size; \ | ||
51 | \ | ||
52 | size = snprintf(buf, BUFSIZE, #str "=%"fmt "\n", data); \ | ||
53 | if (1 != fwrite(buf, size, 1, file)) { \ | ||
54 | perror("test attr - failed to write event file"); \ | ||
55 | fclose(file); \ | ||
56 | return -1; \ | ||
57 | } \ | ||
58 | \ | ||
59 | } while (0) | ||
60 | |||
61 | #define WRITE_ASS(field, fmt) __WRITE_ASS(field, fmt, attr->field) | ||
62 | |||
63 | static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu, | ||
64 | int fd, int group_fd, unsigned long flags) | ||
65 | { | ||
66 | FILE *file; | ||
67 | char path[PATH_MAX]; | ||
68 | |||
69 | snprintf(path, PATH_MAX, "%s/event-%d-%llu-%d", dir, | ||
70 | attr->type, attr->config, fd); | ||
71 | |||
72 | file = fopen(path, "w+"); | ||
73 | if (!file) { | ||
74 | perror("test attr - failed to open event file"); | ||
75 | return -1; | ||
76 | } | ||
77 | |||
78 | if (fprintf(file, "[event-%d-%llu-%d]\n", | ||
79 | attr->type, attr->config, fd) < 0) { | ||
80 | perror("test attr - failed to write event file"); | ||
81 | fclose(file); | ||
82 | return -1; | ||
83 | } | ||
84 | |||
85 | /* syscall arguments */ | ||
86 | __WRITE_ASS(fd, "d", fd); | ||
87 | __WRITE_ASS(group_fd, "d", group_fd); | ||
88 | __WRITE_ASS(cpu, "d", cpu); | ||
89 | __WRITE_ASS(pid, "d", pid); | ||
90 | __WRITE_ASS(flags, "lu", flags); | ||
91 | |||
92 | /* struct perf_event_attr */ | ||
93 | WRITE_ASS(type, PRIu32); | ||
94 | WRITE_ASS(size, PRIu32); | ||
95 | WRITE_ASS(config, "llu"); | ||
96 | WRITE_ASS(sample_period, "llu"); | ||
97 | WRITE_ASS(sample_type, "llu"); | ||
98 | WRITE_ASS(read_format, "llu"); | ||
99 | WRITE_ASS(disabled, "d"); | ||
100 | WRITE_ASS(inherit, "d"); | ||
101 | WRITE_ASS(pinned, "d"); | ||
102 | WRITE_ASS(exclusive, "d"); | ||
103 | WRITE_ASS(exclude_user, "d"); | ||
104 | WRITE_ASS(exclude_kernel, "d"); | ||
105 | WRITE_ASS(exclude_hv, "d"); | ||
106 | WRITE_ASS(exclude_idle, "d"); | ||
107 | WRITE_ASS(mmap, "d"); | ||
108 | WRITE_ASS(comm, "d"); | ||
109 | WRITE_ASS(freq, "d"); | ||
110 | WRITE_ASS(inherit_stat, "d"); | ||
111 | WRITE_ASS(enable_on_exec, "d"); | ||
112 | WRITE_ASS(task, "d"); | ||
113 | WRITE_ASS(watermark, "d"); | ||
114 | WRITE_ASS(precise_ip, "d"); | ||
115 | WRITE_ASS(mmap_data, "d"); | ||
116 | WRITE_ASS(sample_id_all, "d"); | ||
117 | WRITE_ASS(exclude_host, "d"); | ||
118 | WRITE_ASS(exclude_guest, "d"); | ||
119 | WRITE_ASS(exclude_callchain_kernel, "d"); | ||
120 | WRITE_ASS(exclude_callchain_user, "d"); | ||
121 | WRITE_ASS(wakeup_events, PRIu32); | ||
122 | WRITE_ASS(bp_type, PRIu32); | ||
123 | WRITE_ASS(config1, "llu"); | ||
124 | WRITE_ASS(config2, "llu"); | ||
125 | WRITE_ASS(branch_sample_type, "llu"); | ||
126 | WRITE_ASS(sample_regs_user, "llu"); | ||
127 | WRITE_ASS(sample_stack_user, PRIu32); | ||
128 | |||
129 | fclose(file); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, | ||
134 | int fd, int group_fd, unsigned long flags) | ||
135 | { | ||
136 | int errno_saved = errno; | ||
137 | |||
138 | if (store_event(attr, pid, cpu, fd, group_fd, flags)) | ||
139 | die("test attr FAILED"); | ||
140 | |||
141 | errno = errno_saved; | ||
142 | } | ||
143 | |||
144 | static int run_dir(const char *d, const char *perf) | ||
145 | { | ||
146 | char cmd[3*PATH_MAX]; | ||
147 | |||
148 | snprintf(cmd, 3*PATH_MAX, "python %s/attr.py -d %s/attr/ -p %s %s", | ||
149 | d, d, perf, verbose ? "-v" : ""); | ||
150 | |||
151 | return system(cmd); | ||
152 | } | ||
153 | |||
154 | int test_attr__run(void) | ||
155 | { | ||
156 | struct stat st; | ||
157 | char path_perf[PATH_MAX]; | ||
158 | char path_dir[PATH_MAX]; | ||
159 | |||
160 | /* First try developement tree tests. */ | ||
161 | if (!lstat("./tests", &st)) | ||
162 | return run_dir("./tests", "./perf"); | ||
163 | |||
164 | /* Then installed path. */ | ||
165 | snprintf(path_dir, PATH_MAX, "%s/tests", perf_exec_path()); | ||
166 | snprintf(path_perf, PATH_MAX, "%s/perf", BINDIR); | ||
167 | |||
168 | if (!lstat(path_dir, &st) && | ||
169 | !lstat(path_perf, &st)) | ||
170 | return run_dir(path_dir, path_perf); | ||
171 | |||
172 | fprintf(stderr, " (ommitted)"); | ||
173 | return 0; | ||
174 | } | ||
diff --git a/tools/perf/tests/attr.py b/tools/perf/tests/attr.py new file mode 100644 index 000000000000..e702b82dcb86 --- /dev/null +++ b/tools/perf/tests/attr.py | |||
@@ -0,0 +1,322 @@ | |||
1 | #! /usr/bin/python | ||
2 | |||
3 | import os | ||
4 | import sys | ||
5 | import glob | ||
6 | import optparse | ||
7 | import tempfile | ||
8 | import logging | ||
9 | import shutil | ||
10 | import ConfigParser | ||
11 | |||
12 | class Fail(Exception): | ||
13 | def __init__(self, test, msg): | ||
14 | self.msg = msg | ||
15 | self.test = test | ||
16 | def getMsg(self): | ||
17 | return '\'%s\' - %s' % (self.test.path, self.msg) | ||
18 | |||
19 | class Unsup(Exception): | ||
20 | def __init__(self, test): | ||
21 | self.test = test | ||
22 | def getMsg(self): | ||
23 | return '\'%s\'' % self.test.path | ||
24 | |||
25 | class Event(dict): | ||
26 | terms = [ | ||
27 | 'flags', | ||
28 | 'type', | ||
29 | 'size', | ||
30 | 'config', | ||
31 | 'sample_period', | ||
32 | 'sample_type', | ||
33 | 'read_format', | ||
34 | 'disabled', | ||
35 | 'inherit', | ||
36 | 'pinned', | ||
37 | 'exclusive', | ||
38 | 'exclude_user', | ||
39 | 'exclude_kernel', | ||
40 | 'exclude_hv', | ||
41 | 'exclude_idle', | ||
42 | 'mmap', | ||
43 | 'comm', | ||
44 | 'freq', | ||
45 | 'inherit_stat', | ||
46 | 'enable_on_exec', | ||
47 | 'task', | ||
48 | 'watermark', | ||
49 | 'precise_ip', | ||
50 | 'mmap_data', | ||
51 | 'sample_id_all', | ||
52 | 'exclude_host', | ||
53 | 'exclude_guest', | ||
54 | 'exclude_callchain_kernel', | ||
55 | 'exclude_callchain_user', | ||
56 | 'wakeup_events', | ||
57 | 'bp_type', | ||
58 | 'config1', | ||
59 | 'config2', | ||
60 | 'branch_sample_type', | ||
61 | 'sample_regs_user', | ||
62 | 'sample_stack_user', | ||
63 | ] | ||
64 | |||
65 | def add(self, data): | ||
66 | for key, val in data: | ||
67 | log.debug(" %s = %s" % (key, val)) | ||
68 | self[key] = val | ||
69 | |||
70 | def __init__(self, name, data, base): | ||
71 | log.info(" Event %s" % name); | ||
72 | self.name = name; | ||
73 | self.group = '' | ||
74 | self.add(base) | ||
75 | self.add(data) | ||
76 | |||
77 | def compare_data(self, a, b): | ||
78 | # Allow multiple values in assignment separated by '|' | ||
79 | a_list = a.split('|') | ||
80 | b_list = b.split('|') | ||
81 | |||
82 | for a_item in a_list: | ||
83 | for b_item in b_list: | ||
84 | if (a_item == b_item): | ||
85 | return True | ||
86 | elif (a_item == '*') or (b_item == '*'): | ||
87 | return True | ||
88 | |||
89 | return False | ||
90 | |||
91 | def equal(self, other): | ||
92 | for t in Event.terms: | ||
93 | log.debug(" [%s] %s %s" % (t, self[t], other[t])); | ||
94 | if not self.has_key(t) or not other.has_key(t): | ||
95 | return False | ||
96 | if not self.compare_data(self[t], other[t]): | ||
97 | return False | ||
98 | return True | ||
99 | |||
100 | # Test file description needs to have following sections: | ||
101 | # [config] | ||
102 | # - just single instance in file | ||
103 | # - needs to specify: | ||
104 | # 'command' - perf command name | ||
105 | # 'args' - special command arguments | ||
106 | # 'ret' - expected command return value (0 by default) | ||
107 | # | ||
108 | # [eventX:base] | ||
109 | # - one or multiple instances in file | ||
110 | # - expected values assignments | ||
111 | class Test(object): | ||
112 | def __init__(self, path, options): | ||
113 | parser = ConfigParser.SafeConfigParser() | ||
114 | parser.read(path) | ||
115 | |||
116 | log.warning("running '%s'" % path) | ||
117 | |||
118 | self.path = path | ||
119 | self.test_dir = options.test_dir | ||
120 | self.perf = options.perf | ||
121 | self.command = parser.get('config', 'command') | ||
122 | self.args = parser.get('config', 'args') | ||
123 | |||
124 | try: | ||
125 | self.ret = parser.get('config', 'ret') | ||
126 | except: | ||
127 | self.ret = 0 | ||
128 | |||
129 | self.expect = {} | ||
130 | self.result = {} | ||
131 | log.info(" loading expected events"); | ||
132 | self.load_events(path, self.expect) | ||
133 | |||
134 | def is_event(self, name): | ||
135 | if name.find("event") == -1: | ||
136 | return False | ||
137 | else: | ||
138 | return True | ||
139 | |||
140 | def load_events(self, path, events): | ||
141 | parser_event = ConfigParser.SafeConfigParser() | ||
142 | parser_event.read(path) | ||
143 | |||
144 | # The event record section header contains 'event' word, | ||
145 | # optionaly followed by ':' allowing to load 'parent | ||
146 | # event' first as a base | ||
147 | for section in filter(self.is_event, parser_event.sections()): | ||
148 | |||
149 | parser_items = parser_event.items(section); | ||
150 | base_items = {} | ||
151 | |||
152 | # Read parent event if there's any | ||
153 | if (':' in section): | ||
154 | base = section[section.index(':') + 1:] | ||
155 | parser_base = ConfigParser.SafeConfigParser() | ||
156 | parser_base.read(self.test_dir + '/' + base) | ||
157 | base_items = parser_base.items('event') | ||
158 | |||
159 | e = Event(section, parser_items, base_items) | ||
160 | events[section] = e | ||
161 | |||
162 | def run_cmd(self, tempdir): | ||
163 | cmd = "PERF_TEST_ATTR=%s %s %s -o %s/perf.data %s" % (tempdir, | ||
164 | self.perf, self.command, tempdir, self.args) | ||
165 | ret = os.WEXITSTATUS(os.system(cmd)) | ||
166 | |||
167 | log.info(" running '%s' ret %d " % (cmd, ret)) | ||
168 | |||
169 | if ret != int(self.ret): | ||
170 | raise Unsup(self) | ||
171 | |||
172 | def compare(self, expect, result): | ||
173 | match = {} | ||
174 | |||
175 | log.info(" compare"); | ||
176 | |||
177 | # For each expected event find all matching | ||
178 | # events in result. Fail if there's not any. | ||
179 | for exp_name, exp_event in expect.items(): | ||
180 | exp_list = [] | ||
181 | log.debug(" matching [%s]" % exp_name) | ||
182 | for res_name, res_event in result.items(): | ||
183 | log.debug(" to [%s]" % res_name) | ||
184 | if (exp_event.equal(res_event)): | ||
185 | exp_list.append(res_name) | ||
186 | log.debug(" ->OK") | ||
187 | else: | ||
188 | log.debug(" ->FAIL"); | ||
189 | |||
190 | log.info(" match: [%s] matches %s" % (exp_name, str(exp_list))) | ||
191 | |||
192 | # we did not any matching event - fail | ||
193 | if (not exp_list): | ||
194 | raise Fail(self, 'match failure'); | ||
195 | |||
196 | match[exp_name] = exp_list | ||
197 | |||
198 | # For each defined group in the expected events | ||
199 | # check we match the same group in the result. | ||
200 | for exp_name, exp_event in expect.items(): | ||
201 | group = exp_event.group | ||
202 | |||
203 | if (group == ''): | ||
204 | continue | ||
205 | |||
206 | for res_name in match[exp_name]: | ||
207 | res_group = result[res_name].group | ||
208 | if res_group not in match[group]: | ||
209 | raise Fail(self, 'group failure') | ||
210 | |||
211 | log.info(" group: [%s] matches group leader %s" % | ||
212 | (exp_name, str(match[group]))) | ||
213 | |||
214 | log.info(" matched") | ||
215 | |||
216 | def resolve_groups(self, events): | ||
217 | for name, event in events.items(): | ||
218 | group_fd = event['group_fd']; | ||
219 | if group_fd == '-1': | ||
220 | continue; | ||
221 | |||
222 | for iname, ievent in events.items(): | ||
223 | if (ievent['fd'] == group_fd): | ||
224 | event.group = iname | ||
225 | log.debug('[%s] has group leader [%s]' % (name, iname)) | ||
226 | break; | ||
227 | |||
228 | def run(self): | ||
229 | tempdir = tempfile.mkdtemp(); | ||
230 | |||
231 | try: | ||
232 | # run the test script | ||
233 | self.run_cmd(tempdir); | ||
234 | |||
235 | # load events expectation for the test | ||
236 | log.info(" loading result events"); | ||
237 | for f in glob.glob(tempdir + '/event*'): | ||
238 | self.load_events(f, self.result); | ||
239 | |||
240 | # resolve group_fd to event names | ||
241 | self.resolve_groups(self.expect); | ||
242 | self.resolve_groups(self.result); | ||
243 | |||
244 | # do the expectation - results matching - both ways | ||
245 | self.compare(self.expect, self.result) | ||
246 | self.compare(self.result, self.expect) | ||
247 | |||
248 | finally: | ||
249 | # cleanup | ||
250 | shutil.rmtree(tempdir) | ||
251 | |||
252 | |||
253 | def run_tests(options): | ||
254 | for f in glob.glob(options.test_dir + '/' + options.test): | ||
255 | try: | ||
256 | Test(f, options).run() | ||
257 | except Unsup, obj: | ||
258 | log.warning("unsupp %s" % obj.getMsg()) | ||
259 | |||
260 | def setup_log(verbose): | ||
261 | global log | ||
262 | level = logging.CRITICAL | ||
263 | |||
264 | if verbose == 1: | ||
265 | level = logging.WARNING | ||
266 | if verbose == 2: | ||
267 | level = logging.INFO | ||
268 | if verbose >= 3: | ||
269 | level = logging.DEBUG | ||
270 | |||
271 | log = logging.getLogger('test') | ||
272 | log.setLevel(level) | ||
273 | ch = logging.StreamHandler() | ||
274 | ch.setLevel(level) | ||
275 | formatter = logging.Formatter('%(message)s') | ||
276 | ch.setFormatter(formatter) | ||
277 | log.addHandler(ch) | ||
278 | |||
279 | USAGE = '''%s [OPTIONS] | ||
280 | -d dir # tests dir | ||
281 | -p path # perf binary | ||
282 | -t test # single test | ||
283 | -v # verbose level | ||
284 | ''' % sys.argv[0] | ||
285 | |||
286 | def main(): | ||
287 | parser = optparse.OptionParser(usage=USAGE) | ||
288 | |||
289 | parser.add_option("-t", "--test", | ||
290 | action="store", type="string", dest="test") | ||
291 | parser.add_option("-d", "--test-dir", | ||
292 | action="store", type="string", dest="test_dir") | ||
293 | parser.add_option("-p", "--perf", | ||
294 | action="store", type="string", dest="perf") | ||
295 | parser.add_option("-v", "--verbose", | ||
296 | action="count", dest="verbose") | ||
297 | |||
298 | options, args = parser.parse_args() | ||
299 | if args: | ||
300 | parser.error('FAILED wrong arguments %s' % ' '.join(args)) | ||
301 | return -1 | ||
302 | |||
303 | setup_log(options.verbose) | ||
304 | |||
305 | if not options.test_dir: | ||
306 | print 'FAILED no -d option specified' | ||
307 | sys.exit(-1) | ||
308 | |||
309 | if not options.test: | ||
310 | options.test = 'test*' | ||
311 | |||
312 | try: | ||
313 | run_tests(options) | ||
314 | |||
315 | except Fail, obj: | ||
316 | print "FAILED %s" % obj.getMsg(); | ||
317 | sys.exit(-1) | ||
318 | |||
319 | sys.exit(0) | ||
320 | |||
321 | if __name__ == '__main__': | ||
322 | main() | ||
diff --git a/tools/perf/tests/attr/README b/tools/perf/tests/attr/README new file mode 100644 index 000000000000..d102957cd59a --- /dev/null +++ b/tools/perf/tests/attr/README | |||
@@ -0,0 +1,64 @@ | |||
1 | The struct perf_event_attr test (attr tests) support | ||
2 | ==================================================== | ||
3 | This testing support is embedded into perf directly and is governed | ||
4 | by the PERF_TEST_ATTR environment variable and hook inside the | ||
5 | sys_perf_event_open function. | ||
6 | |||
7 | The general idea is to store 'struct perf_event_attr' details for | ||
8 | each event created within single perf command. Each event details | ||
9 | are stored into separate text file. Once perf command is finished | ||
10 | these files are checked for values we expect for command. | ||
11 | |||
12 | The attr tests consist of following parts: | ||
13 | |||
14 | tests/attr.c | ||
15 | ------------ | ||
16 | This is the sys_perf_event_open hook implementation. The hook | ||
17 | is triggered when the PERF_TEST_ATTR environment variable is | ||
18 | defined. It must contain name of existing directory with access | ||
19 | and write permissions. | ||
20 | |||
21 | For each sys_perf_event_open call event details are stored in | ||
22 | separate file. Besides 'struct perf_event_attr' values we also | ||
23 | store 'fd' and 'group_fd' values to allow checking for groups. | ||
24 | |||
25 | tests/attr.py | ||
26 | ------------- | ||
27 | This is the python script that does all the hard work. It reads | ||
28 | the test definition, executes it and checks results. | ||
29 | |||
30 | tests/attr/ | ||
31 | ----------- | ||
32 | Directory containing all attr test definitions. | ||
33 | Following tests are defined (with perf commands): | ||
34 | |||
35 | perf record kill (test-record-basic) | ||
36 | perf record -b kill (test-record-branch-any) | ||
37 | perf record -j any kill (test-record-branch-filter-any) | ||
38 | perf record -j any_call kill (test-record-branch-filter-any_call) | ||
39 | perf record -j any_ret kill (test-record-branch-filter-any_ret) | ||
40 | perf record -j hv kill (test-record-branch-filter-hv) | ||
41 | perf record -j ind_call kill (test-record-branch-filter-ind_call) | ||
42 | perf record -j k kill (test-record-branch-filter-k) | ||
43 | perf record -j u kill (test-record-branch-filter-u) | ||
44 | perf record -c 123 kill (test-record-count) | ||
45 | perf record -d kill (test-record-data) | ||
46 | perf record -F 100 kill (test-record-freq) | ||
47 | perf record -g -- kill (test-record-graph-default) | ||
48 | perf record -g dwarf -- kill (test-record-graph-dwarf) | ||
49 | perf record -g fp kill (test-record-graph-fp) | ||
50 | perf record --group -e cycles,instructions kill (test-record-group) | ||
51 | perf record -e '{cycles,instructions}' kill (test-record-group1) | ||
52 | perf record -D kill (test-record-no-delay) | ||
53 | perf record -i kill (test-record-no-inherit) | ||
54 | perf record -n kill (test-record-no-samples) | ||
55 | perf record -c 100 -P kill (test-record-period) | ||
56 | perf record -R kill (test-record-raw) | ||
57 | perf stat -e cycles kill (test-stat-basic) | ||
58 | perf stat kill (test-stat-default) | ||
59 | perf stat -d kill (test-stat-detailed-1) | ||
60 | perf stat -dd kill (test-stat-detailed-2) | ||
61 | perf stat -ddd kill (test-stat-detailed-3) | ||
62 | perf stat --group -e cycles,instructions kill (test-stat-group) | ||
63 | perf stat -e '{cycles,instructions}' kill (test-stat-group1) | ||
64 | perf stat -i -e cycles kill (test-stat-no-inherit) | ||
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record new file mode 100644 index 000000000000..f1485d8e6a0b --- /dev/null +++ b/tools/perf/tests/attr/base-record | |||
@@ -0,0 +1,39 @@ | |||
1 | [event] | ||
2 | fd=1 | ||
3 | group_fd=-1 | ||
4 | flags=0 | ||
5 | type=0|1 | ||
6 | size=96 | ||
7 | config=0 | ||
8 | sample_period=4000 | ||
9 | sample_type=263 | ||
10 | read_format=7 | ||
11 | disabled=1 | ||
12 | inherit=1 | ||
13 | pinned=0 | ||
14 | exclusive=0 | ||
15 | exclude_user=0 | ||
16 | exclude_kernel=0 | ||
17 | exclude_hv=0 | ||
18 | exclude_idle=0 | ||
19 | mmap=1 | ||
20 | comm=1 | ||
21 | freq=1 | ||
22 | inherit_stat=0 | ||
23 | enable_on_exec=1 | ||
24 | task=0 | ||
25 | watermark=0 | ||
26 | precise_ip=0 | ||
27 | mmap_data=0 | ||
28 | sample_id_all=1 | ||
29 | exclude_host=0 | ||
30 | exclude_guest=1 | ||
31 | exclude_callchain_kernel=0 | ||
32 | exclude_callchain_user=0 | ||
33 | wakeup_events=0 | ||
34 | bp_type=0 | ||
35 | config1=0 | ||
36 | config2=0 | ||
37 | branch_sample_type=0 | ||
38 | sample_regs_user=0 | ||
39 | sample_stack_user=0 | ||
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat new file mode 100644 index 000000000000..4bd79a82784f --- /dev/null +++ b/tools/perf/tests/attr/base-stat | |||
@@ -0,0 +1,39 @@ | |||
1 | [event] | ||
2 | fd=1 | ||
3 | group_fd=-1 | ||
4 | flags=0 | ||
5 | type=0 | ||
6 | size=96 | ||
7 | config=0 | ||
8 | sample_period=0 | ||
9 | sample_type=0 | ||
10 | read_format=3 | ||
11 | disabled=1 | ||
12 | inherit=1 | ||
13 | pinned=0 | ||
14 | exclusive=0 | ||
15 | exclude_user=0 | ||
16 | exclude_kernel=0 | ||
17 | exclude_hv=0 | ||
18 | exclude_idle=0 | ||
19 | mmap=0 | ||
20 | comm=0 | ||
21 | freq=0 | ||
22 | inherit_stat=0 | ||
23 | enable_on_exec=1 | ||
24 | task=0 | ||
25 | watermark=0 | ||
26 | precise_ip=0 | ||
27 | mmap_data=0 | ||
28 | sample_id_all=0 | ||
29 | exclude_host=0 | ||
30 | exclude_guest=1 | ||
31 | exclude_callchain_kernel=0 | ||
32 | exclude_callchain_user=0 | ||
33 | wakeup_events=0 | ||
34 | bp_type=0 | ||
35 | config1=0 | ||
36 | config2=0 | ||
37 | branch_sample_type=0 | ||
38 | sample_regs_user=0 | ||
39 | sample_stack_user=0 | ||
diff --git a/tools/perf/tests/attr/test-record-basic b/tools/perf/tests/attr/test-record-basic new file mode 100644 index 000000000000..55c0428370ca --- /dev/null +++ b/tools/perf/tests/attr/test-record-basic | |||
@@ -0,0 +1,5 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
diff --git a/tools/perf/tests/attr/test-record-branch-any b/tools/perf/tests/attr/test-record-branch-any new file mode 100644 index 000000000000..1421960ed4e9 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-any | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -b kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any b/tools/perf/tests/attr/test-record-branch-filter-any new file mode 100644 index 000000000000..915c4df0e0c2 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-any | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j any kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_call b/tools/perf/tests/attr/test-record-branch-filter-any_call new file mode 100644 index 000000000000..8708dbd4f373 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-any_call | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j any_call kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=16 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-any_ret b/tools/perf/tests/attr/test-record-branch-filter-any_ret new file mode 100644 index 000000000000..0d3607a6dcbe --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-any_ret | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j any_ret kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=32 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-hv b/tools/perf/tests/attr/test-record-branch-filter-hv new file mode 100644 index 000000000000..f25526740cec --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-hv | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j hv kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-ind_call b/tools/perf/tests/attr/test-record-branch-filter-ind_call new file mode 100644 index 000000000000..e862dd179128 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-ind_call | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j ind_call kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=64 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-k b/tools/perf/tests/attr/test-record-branch-filter-k new file mode 100644 index 000000000000..182971e898f5 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-k | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j k kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-branch-filter-u b/tools/perf/tests/attr/test-record-branch-filter-u new file mode 100644 index 000000000000..83449ef9e687 --- /dev/null +++ b/tools/perf/tests/attr/test-record-branch-filter-u | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -j u kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=2311 | ||
8 | branch_sample_type=8 | ||
diff --git a/tools/perf/tests/attr/test-record-count b/tools/perf/tests/attr/test-record-count new file mode 100644 index 000000000000..2f841de56f6b --- /dev/null +++ b/tools/perf/tests/attr/test-record-count | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -c 123 kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=123 | ||
7 | sample_type=7 | ||
8 | freq=0 | ||
diff --git a/tools/perf/tests/attr/test-record-data b/tools/perf/tests/attr/test-record-data new file mode 100644 index 000000000000..6627c3e7534a --- /dev/null +++ b/tools/perf/tests/attr/test-record-data | |||
@@ -0,0 +1,8 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -d kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=271 | ||
8 | mmap_data=1 | ||
diff --git a/tools/perf/tests/attr/test-record-freq b/tools/perf/tests/attr/test-record-freq new file mode 100644 index 000000000000..600d0f8f2583 --- /dev/null +++ b/tools/perf/tests/attr/test-record-freq | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -F 100 kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=100 | ||
diff --git a/tools/perf/tests/attr/test-record-graph-default b/tools/perf/tests/attr/test-record-graph-default new file mode 100644 index 000000000000..833d1849d767 --- /dev/null +++ b/tools/perf/tests/attr/test-record-graph-default | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -g -- kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=295 | ||
diff --git a/tools/perf/tests/attr/test-record-graph-dwarf b/tools/perf/tests/attr/test-record-graph-dwarf new file mode 100644 index 000000000000..e93e082f5208 --- /dev/null +++ b/tools/perf/tests/attr/test-record-graph-dwarf | |||
@@ -0,0 +1,10 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -g dwarf -- kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=12583 | ||
7 | exclude_callchain_user=1 | ||
8 | sample_stack_user=8192 | ||
9 | # TODO different for each arch, no support for that now | ||
10 | sample_regs_user=* | ||
diff --git a/tools/perf/tests/attr/test-record-graph-fp b/tools/perf/tests/attr/test-record-graph-fp new file mode 100644 index 000000000000..7cef3743f03f --- /dev/null +++ b/tools/perf/tests/attr/test-record-graph-fp | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -g fp kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=295 | ||
diff --git a/tools/perf/tests/attr/test-record-group b/tools/perf/tests/attr/test-record-group new file mode 100644 index 000000000000..b945f770dc9e --- /dev/null +++ b/tools/perf/tests/attr/test-record-group | |||
@@ -0,0 +1,17 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = --group -e cycles,instructions kill >/dev/null 2>&1 | ||
4 | |||
5 | [event-1:base-record] | ||
6 | fd=1 | ||
7 | group_fd=-1 | ||
8 | sample_type=327 | ||
9 | |||
10 | [event-2:base-record] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | config=1 | ||
14 | sample_type=327 | ||
15 | mmap=0 | ||
16 | comm=0 | ||
17 | enable_on_exec=0 | ||
diff --git a/tools/perf/tests/attr/test-record-group1 b/tools/perf/tests/attr/test-record-group1 new file mode 100644 index 000000000000..39bf8609538c --- /dev/null +++ b/tools/perf/tests/attr/test-record-group1 | |||
@@ -0,0 +1,20 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -e '{cycles,instructions}' kill >/tmp/krava 2>&1 | ||
4 | |||
5 | [event-1:base-record] | ||
6 | fd=1 | ||
7 | group_fd=-1 | ||
8 | sample_type=327 | ||
9 | |||
10 | [event-2:base-record] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | type=0 | ||
14 | config=1 | ||
15 | sample_type=327 | ||
16 | mmap=0 | ||
17 | comm=0 | ||
18 | # TODO this is disabled for --group option, enabled otherwise | ||
19 | # check why.. | ||
20 | enable_on_exec=1 | ||
diff --git a/tools/perf/tests/attr/test-record-no-delay b/tools/perf/tests/attr/test-record-no-delay new file mode 100644 index 000000000000..f253b78cdbf2 --- /dev/null +++ b/tools/perf/tests/attr/test-record-no-delay | |||
@@ -0,0 +1,9 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -D kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=263 | ||
8 | watermark=0 | ||
9 | wakeup_events=1 | ||
diff --git a/tools/perf/tests/attr/test-record-no-inherit b/tools/perf/tests/attr/test-record-no-inherit new file mode 100644 index 000000000000..9079a25cd643 --- /dev/null +++ b/tools/perf/tests/attr/test-record-no-inherit | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -i kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_type=259 | ||
7 | inherit=0 | ||
diff --git a/tools/perf/tests/attr/test-record-no-samples b/tools/perf/tests/attr/test-record-no-samples new file mode 100644 index 000000000000..d0141b2418b5 --- /dev/null +++ b/tools/perf/tests/attr/test-record-no-samples | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -n kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=0 | ||
diff --git a/tools/perf/tests/attr/test-record-period b/tools/perf/tests/attr/test-record-period new file mode 100644 index 000000000000..8abc5314fc52 --- /dev/null +++ b/tools/perf/tests/attr/test-record-period | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -c 100 -P kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=100 | ||
7 | freq=0 | ||
diff --git a/tools/perf/tests/attr/test-record-raw b/tools/perf/tests/attr/test-record-raw new file mode 100644 index 000000000000..4a8ef25b5f49 --- /dev/null +++ b/tools/perf/tests/attr/test-record-raw | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = record | ||
3 | args = -R kill >/dev/null 2>&1 | ||
4 | |||
5 | [event:base-record] | ||
6 | sample_period=4000 | ||
7 | sample_type=1415 | ||
diff --git a/tools/perf/tests/attr/test-stat-basic b/tools/perf/tests/attr/test-stat-basic new file mode 100644 index 000000000000..74e17881f2ba --- /dev/null +++ b/tools/perf/tests/attr/test-stat-basic | |||
@@ -0,0 +1,6 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -e cycles kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event:base-stat] | ||
diff --git a/tools/perf/tests/attr/test-stat-default b/tools/perf/tests/attr/test-stat-default new file mode 100644 index 000000000000..19270f54c96e --- /dev/null +++ b/tools/perf/tests/attr/test-stat-default | |||
@@ -0,0 +1,64 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
7 | [event1:base-stat] | ||
8 | fd=1 | ||
9 | type=1 | ||
10 | config=1 | ||
11 | |||
12 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
13 | [event2:base-stat] | ||
14 | fd=2 | ||
15 | type=1 | ||
16 | config=3 | ||
17 | |||
18 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
19 | [event3:base-stat] | ||
20 | fd=3 | ||
21 | type=1 | ||
22 | config=4 | ||
23 | |||
24 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
25 | [event4:base-stat] | ||
26 | fd=4 | ||
27 | type=1 | ||
28 | config=2 | ||
29 | |||
30 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
31 | [event5:base-stat] | ||
32 | fd=5 | ||
33 | type=0 | ||
34 | config=0 | ||
35 | |||
36 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
37 | [event6:base-stat] | ||
38 | fd=6 | ||
39 | type=0 | ||
40 | config=7 | ||
41 | |||
42 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
43 | [event7:base-stat] | ||
44 | fd=7 | ||
45 | type=0 | ||
46 | config=8 | ||
47 | |||
48 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
49 | [event8:base-stat] | ||
50 | fd=8 | ||
51 | type=0 | ||
52 | config=1 | ||
53 | |||
54 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
55 | [event9:base-stat] | ||
56 | fd=9 | ||
57 | type=0 | ||
58 | config=4 | ||
59 | |||
60 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
61 | [event10:base-stat] | ||
62 | fd=10 | ||
63 | type=0 | ||
64 | config=5 | ||
diff --git a/tools/perf/tests/attr/test-stat-detailed-1 b/tools/perf/tests/attr/test-stat-detailed-1 new file mode 100644 index 000000000000..51426b87153b --- /dev/null +++ b/tools/perf/tests/attr/test-stat-detailed-1 | |||
@@ -0,0 +1,101 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -d kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | |||
7 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
8 | [event1:base-stat] | ||
9 | fd=1 | ||
10 | type=1 | ||
11 | config=1 | ||
12 | |||
13 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
14 | [event2:base-stat] | ||
15 | fd=2 | ||
16 | type=1 | ||
17 | config=3 | ||
18 | |||
19 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
20 | [event3:base-stat] | ||
21 | fd=3 | ||
22 | type=1 | ||
23 | config=4 | ||
24 | |||
25 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
26 | [event4:base-stat] | ||
27 | fd=4 | ||
28 | type=1 | ||
29 | config=2 | ||
30 | |||
31 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
32 | [event5:base-stat] | ||
33 | fd=5 | ||
34 | type=0 | ||
35 | config=0 | ||
36 | |||
37 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
38 | [event6:base-stat] | ||
39 | fd=6 | ||
40 | type=0 | ||
41 | config=7 | ||
42 | |||
43 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
44 | [event7:base-stat] | ||
45 | fd=7 | ||
46 | type=0 | ||
47 | config=8 | ||
48 | |||
49 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
50 | [event8:base-stat] | ||
51 | fd=8 | ||
52 | type=0 | ||
53 | config=1 | ||
54 | |||
55 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
56 | [event9:base-stat] | ||
57 | fd=9 | ||
58 | type=0 | ||
59 | config=4 | ||
60 | |||
61 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
62 | [event10:base-stat] | ||
63 | fd=10 | ||
64 | type=0 | ||
65 | config=5 | ||
66 | |||
67 | # PERF_TYPE_HW_CACHE / | ||
68 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
69 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
70 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
71 | [event11:base-stat] | ||
72 | fd=11 | ||
73 | type=3 | ||
74 | config=0 | ||
75 | |||
76 | # PERF_TYPE_HW_CACHE / | ||
77 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
78 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
79 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
80 | [event12:base-stat] | ||
81 | fd=12 | ||
82 | type=3 | ||
83 | config=65536 | ||
84 | |||
85 | # PERF_TYPE_HW_CACHE / | ||
86 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
87 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
88 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
89 | [event13:base-stat] | ||
90 | fd=13 | ||
91 | type=3 | ||
92 | config=2 | ||
93 | |||
94 | # PERF_TYPE_HW_CACHE, | ||
95 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
96 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
97 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
98 | [event14:base-stat] | ||
99 | fd=14 | ||
100 | type=3 | ||
101 | config=65538 | ||
diff --git a/tools/perf/tests/attr/test-stat-detailed-2 b/tools/perf/tests/attr/test-stat-detailed-2 new file mode 100644 index 000000000000..8de5acc31c27 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-detailed-2 | |||
@@ -0,0 +1,155 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -dd kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | |||
7 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
8 | [event1:base-stat] | ||
9 | fd=1 | ||
10 | type=1 | ||
11 | config=1 | ||
12 | |||
13 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
14 | [event2:base-stat] | ||
15 | fd=2 | ||
16 | type=1 | ||
17 | config=3 | ||
18 | |||
19 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
20 | [event3:base-stat] | ||
21 | fd=3 | ||
22 | type=1 | ||
23 | config=4 | ||
24 | |||
25 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
26 | [event4:base-stat] | ||
27 | fd=4 | ||
28 | type=1 | ||
29 | config=2 | ||
30 | |||
31 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
32 | [event5:base-stat] | ||
33 | fd=5 | ||
34 | type=0 | ||
35 | config=0 | ||
36 | |||
37 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
38 | [event6:base-stat] | ||
39 | fd=6 | ||
40 | type=0 | ||
41 | config=7 | ||
42 | |||
43 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
44 | [event7:base-stat] | ||
45 | fd=7 | ||
46 | type=0 | ||
47 | config=8 | ||
48 | |||
49 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
50 | [event8:base-stat] | ||
51 | fd=8 | ||
52 | type=0 | ||
53 | config=1 | ||
54 | |||
55 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
56 | [event9:base-stat] | ||
57 | fd=9 | ||
58 | type=0 | ||
59 | config=4 | ||
60 | |||
61 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
62 | [event10:base-stat] | ||
63 | fd=10 | ||
64 | type=0 | ||
65 | config=5 | ||
66 | |||
67 | # PERF_TYPE_HW_CACHE / | ||
68 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
69 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
70 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
71 | [event11:base-stat] | ||
72 | fd=11 | ||
73 | type=3 | ||
74 | config=0 | ||
75 | |||
76 | # PERF_TYPE_HW_CACHE / | ||
77 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
78 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
79 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
80 | [event12:base-stat] | ||
81 | fd=12 | ||
82 | type=3 | ||
83 | config=65536 | ||
84 | |||
85 | # PERF_TYPE_HW_CACHE / | ||
86 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
87 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
88 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
89 | [event13:base-stat] | ||
90 | fd=13 | ||
91 | type=3 | ||
92 | config=2 | ||
93 | |||
94 | # PERF_TYPE_HW_CACHE, | ||
95 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
96 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
97 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
98 | [event14:base-stat] | ||
99 | fd=14 | ||
100 | type=3 | ||
101 | config=65538 | ||
102 | |||
103 | # PERF_TYPE_HW_CACHE, | ||
104 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
105 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
106 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
107 | [event15:base-stat] | ||
108 | fd=15 | ||
109 | type=3 | ||
110 | config=1 | ||
111 | |||
112 | # PERF_TYPE_HW_CACHE, | ||
113 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
114 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
115 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
116 | [event16:base-stat] | ||
117 | fd=16 | ||
118 | type=3 | ||
119 | config=65537 | ||
120 | |||
121 | # PERF_TYPE_HW_CACHE, | ||
122 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
123 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
124 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
125 | [event17:base-stat] | ||
126 | fd=17 | ||
127 | type=3 | ||
128 | config=3 | ||
129 | |||
130 | # PERF_TYPE_HW_CACHE, | ||
131 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
132 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
133 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
134 | [event18:base-stat] | ||
135 | fd=18 | ||
136 | type=3 | ||
137 | config=65539 | ||
138 | |||
139 | # PERF_TYPE_HW_CACHE, | ||
140 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
141 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
142 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
143 | [event19:base-stat] | ||
144 | fd=19 | ||
145 | type=3 | ||
146 | config=4 | ||
147 | |||
148 | # PERF_TYPE_HW_CACHE, | ||
149 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
150 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
151 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
152 | [event20:base-stat] | ||
153 | fd=20 | ||
154 | type=3 | ||
155 | config=65540 | ||
diff --git a/tools/perf/tests/attr/test-stat-detailed-3 b/tools/perf/tests/attr/test-stat-detailed-3 new file mode 100644 index 000000000000..0a1f45bf7d79 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-detailed-3 | |||
@@ -0,0 +1,173 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -ddd kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | |||
7 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_TASK_CLOCK | ||
8 | [event1:base-stat] | ||
9 | fd=1 | ||
10 | type=1 | ||
11 | config=1 | ||
12 | |||
13 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CONTEXT_SWITCHES | ||
14 | [event2:base-stat] | ||
15 | fd=2 | ||
16 | type=1 | ||
17 | config=3 | ||
18 | |||
19 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_CPU_MIGRATIONS | ||
20 | [event3:base-stat] | ||
21 | fd=3 | ||
22 | type=1 | ||
23 | config=4 | ||
24 | |||
25 | # PERF_TYPE_SOFTWARE / PERF_COUNT_SW_PAGE_FAULTS | ||
26 | [event4:base-stat] | ||
27 | fd=4 | ||
28 | type=1 | ||
29 | config=2 | ||
30 | |||
31 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_CPU_CYCLES | ||
32 | [event5:base-stat] | ||
33 | fd=5 | ||
34 | type=0 | ||
35 | config=0 | ||
36 | |||
37 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_FRONTEND | ||
38 | [event6:base-stat] | ||
39 | fd=6 | ||
40 | type=0 | ||
41 | config=7 | ||
42 | |||
43 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_STALLED_CYCLES_BACKEND | ||
44 | [event7:base-stat] | ||
45 | fd=7 | ||
46 | type=0 | ||
47 | config=8 | ||
48 | |||
49 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_INSTRUCTIONS | ||
50 | [event8:base-stat] | ||
51 | fd=8 | ||
52 | type=0 | ||
53 | config=1 | ||
54 | |||
55 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_INSTRUCTIONS | ||
56 | [event9:base-stat] | ||
57 | fd=9 | ||
58 | type=0 | ||
59 | config=4 | ||
60 | |||
61 | # PERF_TYPE_HARDWARE / PERF_COUNT_HW_BRANCH_MISSES | ||
62 | [event10:base-stat] | ||
63 | fd=10 | ||
64 | type=0 | ||
65 | config=5 | ||
66 | |||
67 | # PERF_TYPE_HW_CACHE / | ||
68 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
69 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
70 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
71 | [event11:base-stat] | ||
72 | fd=11 | ||
73 | type=3 | ||
74 | config=0 | ||
75 | |||
76 | # PERF_TYPE_HW_CACHE / | ||
77 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
78 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
79 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
80 | [event12:base-stat] | ||
81 | fd=12 | ||
82 | type=3 | ||
83 | config=65536 | ||
84 | |||
85 | # PERF_TYPE_HW_CACHE / | ||
86 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
87 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
88 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
89 | [event13:base-stat] | ||
90 | fd=13 | ||
91 | type=3 | ||
92 | config=2 | ||
93 | |||
94 | # PERF_TYPE_HW_CACHE, | ||
95 | # PERF_COUNT_HW_CACHE_LL << 0 | | ||
96 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
97 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
98 | [event14:base-stat] | ||
99 | fd=14 | ||
100 | type=3 | ||
101 | config=65538 | ||
102 | |||
103 | # PERF_TYPE_HW_CACHE, | ||
104 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
105 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
106 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
107 | [event15:base-stat] | ||
108 | fd=15 | ||
109 | type=3 | ||
110 | config=1 | ||
111 | |||
112 | # PERF_TYPE_HW_CACHE, | ||
113 | # PERF_COUNT_HW_CACHE_L1I << 0 | | ||
114 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
115 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
116 | [event16:base-stat] | ||
117 | fd=16 | ||
118 | type=3 | ||
119 | config=65537 | ||
120 | |||
121 | # PERF_TYPE_HW_CACHE, | ||
122 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
123 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
124 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
125 | [event17:base-stat] | ||
126 | fd=17 | ||
127 | type=3 | ||
128 | config=3 | ||
129 | |||
130 | # PERF_TYPE_HW_CACHE, | ||
131 | # PERF_COUNT_HW_CACHE_DTLB << 0 | | ||
132 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
133 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
134 | [event18:base-stat] | ||
135 | fd=18 | ||
136 | type=3 | ||
137 | config=65539 | ||
138 | |||
139 | # PERF_TYPE_HW_CACHE, | ||
140 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
141 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
142 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
143 | [event19:base-stat] | ||
144 | fd=19 | ||
145 | type=3 | ||
146 | config=4 | ||
147 | |||
148 | # PERF_TYPE_HW_CACHE, | ||
149 | # PERF_COUNT_HW_CACHE_ITLB << 0 | | ||
150 | # (PERF_COUNT_HW_CACHE_OP_READ << 8) | | ||
151 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
152 | [event20:base-stat] | ||
153 | fd=20 | ||
154 | type=3 | ||
155 | config=65540 | ||
156 | |||
157 | # PERF_TYPE_HW_CACHE, | ||
158 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
159 | # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | | ||
160 | # (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16) | ||
161 | [event21:base-stat] | ||
162 | fd=21 | ||
163 | type=3 | ||
164 | config=512 | ||
165 | |||
166 | # PERF_TYPE_HW_CACHE, | ||
167 | # PERF_COUNT_HW_CACHE_L1D << 0 | | ||
168 | # (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | | ||
169 | # (PERF_COUNT_HW_CACHE_RESULT_MISS << 16) | ||
170 | [event22:base-stat] | ||
171 | fd=22 | ||
172 | type=3 | ||
173 | config=66048 | ||
diff --git a/tools/perf/tests/attr/test-stat-group b/tools/perf/tests/attr/test-stat-group new file mode 100644 index 000000000000..fdc1596a8862 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-group | |||
@@ -0,0 +1,15 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = --group -e cycles,instructions kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event-1:base-stat] | ||
7 | fd=1 | ||
8 | group_fd=-1 | ||
9 | |||
10 | [event-2:base-stat] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | config=1 | ||
14 | disabled=0 | ||
15 | enable_on_exec=0 | ||
diff --git a/tools/perf/tests/attr/test-stat-group1 b/tools/perf/tests/attr/test-stat-group1 new file mode 100644 index 000000000000..5ae2718de864 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-group1 | |||
@@ -0,0 +1,17 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -e '{cycles,instructions}' kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event-1:base-stat] | ||
7 | fd=1 | ||
8 | group_fd=-1 | ||
9 | |||
10 | [event-2:base-stat] | ||
11 | fd=2 | ||
12 | group_fd=1 | ||
13 | config=1 | ||
14 | # TODO both disabled and enable_on_exec are disabled for --group option, | ||
15 | # enabled otherwise, check why.. | ||
16 | disabled=1 | ||
17 | enable_on_exec=1 | ||
diff --git a/tools/perf/tests/attr/test-stat-no-inherit b/tools/perf/tests/attr/test-stat-no-inherit new file mode 100644 index 000000000000..d54b2a1e3e28 --- /dev/null +++ b/tools/perf/tests/attr/test-stat-no-inherit | |||
@@ -0,0 +1,7 @@ | |||
1 | [config] | ||
2 | command = stat | ||
3 | args = -i -e cycles kill >/dev/null 2>&1 | ||
4 | ret = 1 | ||
5 | |||
6 | [event:base-stat] | ||
7 | inherit=0 | ||
diff --git a/tools/perf/builtin-test.c b/tools/perf/tests/builtin-test.c index a04276e81f40..5d4354e24457 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "util/debug.h" | 10 | #include "util/debug.h" |
11 | #include "util/debugfs.h" | 11 | #include "util/debugfs.h" |
12 | #include "util/evlist.h" | 12 | #include "util/evlist.h" |
13 | #include "util/machine.h" | ||
13 | #include "util/parse-options.h" | 14 | #include "util/parse-options.h" |
14 | #include "util/parse-events.h" | 15 | #include "util/parse-events.h" |
15 | #include "util/symbol.h" | 16 | #include "util/symbol.h" |
@@ -318,7 +319,7 @@ static int test__open_syscall_event(void) | |||
318 | nr_open_calls, evsel->counts->cpu[0].val); | 319 | nr_open_calls, evsel->counts->cpu[0].val); |
319 | goto out_close_fd; | 320 | goto out_close_fd; |
320 | } | 321 | } |
321 | 322 | ||
322 | err = 0; | 323 | err = 0; |
323 | out_close_fd: | 324 | out_close_fd: |
324 | perf_evsel__close_fd(evsel, 1, threads->nr); | 325 | perf_evsel__close_fd(evsel, 1, threads->nr); |
@@ -604,19 +605,13 @@ out_free_threads: | |||
604 | #undef nsyscalls | 605 | #undef nsyscalls |
605 | } | 606 | } |
606 | 607 | ||
607 | static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp, | 608 | static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) |
608 | size_t *sizep) | ||
609 | { | 609 | { |
610 | cpu_set_t *mask; | ||
611 | size_t size; | ||
612 | int i, cpu = -1, nrcpus = 1024; | 610 | int i, cpu = -1, nrcpus = 1024; |
613 | realloc: | 611 | realloc: |
614 | mask = CPU_ALLOC(nrcpus); | 612 | CPU_ZERO(maskp); |
615 | size = CPU_ALLOC_SIZE(nrcpus); | ||
616 | CPU_ZERO_S(size, mask); | ||
617 | 613 | ||
618 | if (sched_getaffinity(pid, size, mask) == -1) { | 614 | if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) { |
619 | CPU_FREE(mask); | ||
620 | if (errno == EINVAL && nrcpus < (1024 << 8)) { | 615 | if (errno == EINVAL && nrcpus < (1024 << 8)) { |
621 | nrcpus = nrcpus << 2; | 616 | nrcpus = nrcpus << 2; |
622 | goto realloc; | 617 | goto realloc; |
@@ -626,19 +621,14 @@ realloc: | |||
626 | } | 621 | } |
627 | 622 | ||
628 | for (i = 0; i < nrcpus; i++) { | 623 | for (i = 0; i < nrcpus; i++) { |
629 | if (CPU_ISSET_S(i, size, mask)) { | 624 | if (CPU_ISSET(i, maskp)) { |
630 | if (cpu == -1) { | 625 | if (cpu == -1) |
631 | cpu = i; | 626 | cpu = i; |
632 | *maskp = mask; | 627 | else |
633 | *sizep = size; | 628 | CPU_CLR(i, maskp); |
634 | } else | ||
635 | CPU_CLR_S(i, size, mask); | ||
636 | } | 629 | } |
637 | } | 630 | } |
638 | 631 | ||
639 | if (cpu == -1) | ||
640 | CPU_FREE(mask); | ||
641 | |||
642 | return cpu; | 632 | return cpu; |
643 | } | 633 | } |
644 | 634 | ||
@@ -653,8 +643,8 @@ static int test__PERF_RECORD(void) | |||
653 | .freq = 10, | 643 | .freq = 10, |
654 | .mmap_pages = 256, | 644 | .mmap_pages = 256, |
655 | }; | 645 | }; |
656 | cpu_set_t *cpu_mask = NULL; | 646 | cpu_set_t cpu_mask; |
657 | size_t cpu_mask_size = 0; | 647 | size_t cpu_mask_size = sizeof(cpu_mask); |
658 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); | 648 | struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); |
659 | struct perf_evsel *evsel; | 649 | struct perf_evsel *evsel; |
660 | struct perf_sample sample; | 650 | struct perf_sample sample; |
@@ -718,8 +708,7 @@ static int test__PERF_RECORD(void) | |||
718 | evsel->attr.sample_type |= PERF_SAMPLE_TIME; | 708 | evsel->attr.sample_type |= PERF_SAMPLE_TIME; |
719 | perf_evlist__config_attrs(evlist, &opts); | 709 | perf_evlist__config_attrs(evlist, &opts); |
720 | 710 | ||
721 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask, | 711 | err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); |
722 | &cpu_mask_size); | ||
723 | if (err < 0) { | 712 | if (err < 0) { |
724 | pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); | 713 | pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); |
725 | goto out_delete_evlist; | 714 | goto out_delete_evlist; |
@@ -730,9 +719,9 @@ static int test__PERF_RECORD(void) | |||
730 | /* | 719 | /* |
731 | * So that we can check perf_sample.cpu on all the samples. | 720 | * So that we can check perf_sample.cpu on all the samples. |
732 | */ | 721 | */ |
733 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) { | 722 | if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { |
734 | pr_debug("sched_setaffinity: %s\n", strerror(errno)); | 723 | pr_debug("sched_setaffinity: %s\n", strerror(errno)); |
735 | goto out_free_cpu_mask; | 724 | goto out_delete_evlist; |
736 | } | 725 | } |
737 | 726 | ||
738 | /* | 727 | /* |
@@ -916,8 +905,6 @@ found_exit: | |||
916 | } | 905 | } |
917 | out_err: | 906 | out_err: |
918 | perf_evlist__munmap(evlist); | 907 | perf_evlist__munmap(evlist); |
919 | out_free_cpu_mask: | ||
920 | CPU_FREE(cpu_mask); | ||
921 | out_delete_evlist: | 908 | out_delete_evlist: |
922 | perf_evlist__delete(evlist); | 909 | perf_evlist__delete(evlist); |
923 | out: | 910 | out: |
@@ -1344,8 +1331,8 @@ static int test__syscall_open_tp_fields(void) | |||
1344 | perf_evlist__enable(evlist); | 1331 | perf_evlist__enable(evlist); |
1345 | 1332 | ||
1346 | /* | 1333 | /* |
1347 | * Generate the event: | 1334 | * Generate the event: |
1348 | */ | 1335 | */ |
1349 | open(filename, flags); | 1336 | open(filename, flags); |
1350 | 1337 | ||
1351 | while (1) { | 1338 | while (1) { |
@@ -1455,6 +1442,10 @@ static struct test { | |||
1455 | .func = test__syscall_open_tp_fields, | 1442 | .func = test__syscall_open_tp_fields, |
1456 | }, | 1443 | }, |
1457 | { | 1444 | { |
1445 | .desc = "struct perf_event_attr setup", | ||
1446 | .func = test_attr__run, | ||
1447 | }, | ||
1448 | { | ||
1458 | .func = NULL, | 1449 | .func = NULL, |
1459 | }, | 1450 | }, |
1460 | }; | 1451 | }; |
@@ -1495,7 +1486,7 @@ static int __cmd_test(int argc, const char *argv[]) | |||
1495 | width = len; | 1486 | width = len; |
1496 | ++i; | 1487 | ++i; |
1497 | } | 1488 | } |
1498 | 1489 | ||
1499 | i = 0; | 1490 | i = 0; |
1500 | while (tests[i].func) { | 1491 | while (tests[i].func) { |
1501 | int curr = i++, err; | 1492 | int curr = i++, err; |
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/tests/dso-data.c index c6caedeb1d6b..0cd42fc9bc13 100644 --- a/tools/perf/util/dso-test-data.c +++ b/tools/perf/tests/dso-data.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <fcntl.h> | 6 | #include <fcntl.h> |
7 | #include <string.h> | 7 | #include <string.h> |
8 | 8 | ||
9 | #include "machine.h" | ||
9 | #include "symbol.h" | 10 | #include "symbol.h" |
10 | 11 | ||
11 | #define TEST_ASSERT_VAL(text, cond) \ | 12 | #define TEST_ASSERT_VAL(text, cond) \ |
diff --git a/tools/perf/util/parse-events-test.c b/tools/perf/tests/parse-events.c index b49c2eebff33..b49c2eebff33 100644 --- a/tools/perf/util/parse-events-test.c +++ b/tools/perf/tests/parse-events.c | |||
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 28f8aab73aee..5dab3ca96980 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -188,6 +188,12 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) | |||
188 | struct disasm_line *cursor = ab->selection, *target; | 188 | struct disasm_line *cursor = ab->selection, *target; |
189 | struct browser_disasm_line *btarget, *bcursor; | 189 | struct browser_disasm_line *btarget, *bcursor; |
190 | unsigned int from, to; | 190 | unsigned int from, to; |
191 | struct map_symbol *ms = ab->b.priv; | ||
192 | struct symbol *sym = ms->sym; | ||
193 | |||
194 | /* PLT symbols contain external offsets */ | ||
195 | if (strstr(sym->name, "@plt")) | ||
196 | return; | ||
191 | 197 | ||
192 | if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) || | 198 | if (!cursor || !cursor->ins || !ins__is_jump(cursor->ins) || |
193 | !disasm_line__has_offset(cursor)) | 199 | !disasm_line__has_offset(cursor)) |
@@ -386,9 +392,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser) | |||
386 | browser->b.nr_entries = browser->nr_asm_entries; | 392 | browser->b.nr_entries = browser->nr_asm_entries; |
387 | } | 393 | } |
388 | 394 | ||
389 | static bool annotate_browser__callq(struct annotate_browser *browser, | 395 | static bool annotate_browser__callq(struct annotate_browser *browser, int evidx, |
390 | int evidx, void (*timer)(void *arg), | 396 | struct hist_browser_timer *hbt) |
391 | void *arg, int delay_secs) | ||
392 | { | 397 | { |
393 | struct map_symbol *ms = browser->b.priv; | 398 | struct map_symbol *ms = browser->b.priv; |
394 | struct disasm_line *dl = browser->selection; | 399 | struct disasm_line *dl = browser->selection; |
@@ -418,7 +423,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, | |||
418 | } | 423 | } |
419 | 424 | ||
420 | pthread_mutex_unlock(¬es->lock); | 425 | pthread_mutex_unlock(¬es->lock); |
421 | symbol__tui_annotate(target, ms->map, evidx, timer, arg, delay_secs); | 426 | symbol__tui_annotate(target, ms->map, evidx, hbt); |
422 | ui_browser__show_title(&browser->b, sym->name); | 427 | ui_browser__show_title(&browser->b, sym->name); |
423 | return true; | 428 | return true; |
424 | } | 429 | } |
@@ -602,13 +607,13 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser | |||
602 | } | 607 | } |
603 | 608 | ||
604 | static int annotate_browser__run(struct annotate_browser *browser, int evidx, | 609 | static int annotate_browser__run(struct annotate_browser *browser, int evidx, |
605 | void(*timer)(void *arg), | 610 | struct hist_browser_timer *hbt) |
606 | void *arg, int delay_secs) | ||
607 | { | 611 | { |
608 | struct rb_node *nd = NULL; | 612 | struct rb_node *nd = NULL; |
609 | struct map_symbol *ms = browser->b.priv; | 613 | struct map_symbol *ms = browser->b.priv; |
610 | struct symbol *sym = ms->sym; | 614 | struct symbol *sym = ms->sym; |
611 | const char *help = "Press 'h' for help on key bindings"; | 615 | const char *help = "Press 'h' for help on key bindings"; |
616 | int delay_secs = hbt ? hbt->refresh : 0; | ||
612 | int key; | 617 | int key; |
613 | 618 | ||
614 | if (ui_browser__show(&browser->b, sym->name, help) < 0) | 619 | if (ui_browser__show(&browser->b, sym->name, help) < 0) |
@@ -639,8 +644,8 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx, | |||
639 | 644 | ||
640 | switch (key) { | 645 | switch (key) { |
641 | case K_TIMER: | 646 | case K_TIMER: |
642 | if (timer != NULL) | 647 | if (hbt) |
643 | timer(arg); | 648 | hbt->timer(hbt->arg); |
644 | 649 | ||
645 | if (delay_secs != 0) | 650 | if (delay_secs != 0) |
646 | symbol__annotate_decay_histogram(sym, evidx); | 651 | symbol__annotate_decay_histogram(sym, evidx); |
@@ -740,7 +745,7 @@ show_help: | |||
740 | goto show_sup_ins; | 745 | goto show_sup_ins; |
741 | goto out; | 746 | goto out; |
742 | } else if (!(annotate_browser__jump(browser) || | 747 | } else if (!(annotate_browser__jump(browser) || |
743 | annotate_browser__callq(browser, evidx, timer, arg, delay_secs))) { | 748 | annotate_browser__callq(browser, evidx, hbt))) { |
744 | show_sup_ins: | 749 | show_sup_ins: |
745 | ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); | 750 | ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); |
746 | } | 751 | } |
@@ -763,16 +768,21 @@ out: | |||
763 | } | 768 | } |
764 | 769 | ||
765 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, | 770 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, |
766 | void(*timer)(void *arg), void *arg, int delay_secs) | 771 | struct hist_browser_timer *hbt) |
767 | { | 772 | { |
768 | return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, | 773 | return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, hbt); |
769 | timer, arg, delay_secs); | ||
770 | } | 774 | } |
771 | 775 | ||
772 | static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, | 776 | static void annotate_browser__mark_jump_targets(struct annotate_browser *browser, |
773 | size_t size) | 777 | size_t size) |
774 | { | 778 | { |
775 | u64 offset; | 779 | u64 offset; |
780 | struct map_symbol *ms = browser->b.priv; | ||
781 | struct symbol *sym = ms->sym; | ||
782 | |||
783 | /* PLT symbols contain external offsets */ | ||
784 | if (strstr(sym->name, "@plt")) | ||
785 | return; | ||
776 | 786 | ||
777 | for (offset = 0; offset < size; ++offset) { | 787 | for (offset = 0; offset < size; ++offset) { |
778 | struct disasm_line *dl = browser->offsets[offset], *dlt; | 788 | struct disasm_line *dl = browser->offsets[offset], *dlt; |
@@ -816,8 +826,7 @@ static inline int width_jumps(int n) | |||
816 | } | 826 | } |
817 | 827 | ||
818 | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | 828 | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, |
819 | void(*timer)(void *arg), void *arg, | 829 | struct hist_browser_timer *hbt) |
820 | int delay_secs) | ||
821 | { | 830 | { |
822 | struct disasm_line *pos, *n; | 831 | struct disasm_line *pos, *n; |
823 | struct annotation *notes; | 832 | struct annotation *notes; |
@@ -899,7 +908,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | |||
899 | 908 | ||
900 | annotate_browser__update_addr_width(&browser); | 909 | annotate_browser__update_addr_width(&browser); |
901 | 910 | ||
902 | ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs); | 911 | ret = annotate_browser__run(&browser, evidx, hbt); |
903 | list_for_each_entry_safe(pos, n, ¬es->src->source, node) { | 912 | list_for_each_entry_safe(pos, n, ¬es->src->source, node) { |
904 | list_del(&pos->node); | 913 | list_del(&pos->node); |
905 | disasm_line__free(pos); | 914 | disasm_line__free(pos); |
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index fe622845872e..ccc4bd161420 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "../../util/pstack.h" | 11 | #include "../../util/pstack.h" |
12 | #include "../../util/sort.h" | 12 | #include "../../util/sort.h" |
13 | #include "../../util/util.h" | 13 | #include "../../util/util.h" |
14 | #include "../../arch/common.h" | ||
14 | 15 | ||
15 | #include "../browser.h" | 16 | #include "../browser.h" |
16 | #include "../helpline.h" | 17 | #include "../helpline.h" |
@@ -310,10 +311,11 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser) | |||
310 | } | 311 | } |
311 | 312 | ||
312 | static int hist_browser__run(struct hist_browser *browser, const char *ev_name, | 313 | static int hist_browser__run(struct hist_browser *browser, const char *ev_name, |
313 | void(*timer)(void *arg), void *arg, int delay_secs) | 314 | struct hist_browser_timer *hbt) |
314 | { | 315 | { |
315 | int key; | 316 | int key; |
316 | char title[160]; | 317 | char title[160]; |
318 | int delay_secs = hbt ? hbt->refresh : 0; | ||
317 | 319 | ||
318 | browser->b.entries = &browser->hists->entries; | 320 | browser->b.entries = &browser->hists->entries; |
319 | browser->b.nr_entries = browser->hists->nr_entries; | 321 | browser->b.nr_entries = browser->hists->nr_entries; |
@@ -330,7 +332,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *ev_name, | |||
330 | 332 | ||
331 | switch (key) { | 333 | switch (key) { |
332 | case K_TIMER: | 334 | case K_TIMER: |
333 | timer(arg); | 335 | hbt->timer(hbt->arg); |
334 | ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); | 336 | ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); |
335 | 337 | ||
336 | if (browser->hists->stats.nr_lost_warned != | 338 | if (browser->hists->stats.nr_lost_warned != |
@@ -1127,11 +1129,17 @@ static inline void free_popup_options(char **options, int n) | |||
1127 | } | 1129 | } |
1128 | } | 1130 | } |
1129 | 1131 | ||
1132 | /* Check whether the browser is for 'top' or 'report' */ | ||
1133 | static inline bool is_report_browser(void *timer) | ||
1134 | { | ||
1135 | return timer == NULL; | ||
1136 | } | ||
1137 | |||
1130 | static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | 1138 | static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, |
1131 | const char *helpline, const char *ev_name, | 1139 | const char *helpline, const char *ev_name, |
1132 | bool left_exits, | 1140 | bool left_exits, |
1133 | void(*timer)(void *arg), void *arg, | 1141 | struct hist_browser_timer *hbt, |
1134 | int delay_secs) | 1142 | struct perf_session_env *env) |
1135 | { | 1143 | { |
1136 | struct hists *hists = &evsel->hists; | 1144 | struct hists *hists = &evsel->hists; |
1137 | struct hist_browser *browser = hist_browser__new(hists); | 1145 | struct hist_browser *browser = hist_browser__new(hists); |
@@ -1142,6 +1150,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1142 | int key = -1; | 1150 | int key = -1; |
1143 | char buf[64]; | 1151 | char buf[64]; |
1144 | char script_opt[64]; | 1152 | char script_opt[64]; |
1153 | int delay_secs = hbt ? hbt->refresh : 0; | ||
1145 | 1154 | ||
1146 | if (browser == NULL) | 1155 | if (browser == NULL) |
1147 | return -1; | 1156 | return -1; |
@@ -1164,7 +1173,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1164 | 1173 | ||
1165 | nr_options = 0; | 1174 | nr_options = 0; |
1166 | 1175 | ||
1167 | key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); | 1176 | key = hist_browser__run(browser, ev_name, hbt); |
1168 | 1177 | ||
1169 | if (browser->he_selection != NULL) { | 1178 | if (browser->he_selection != NULL) { |
1170 | thread = hist_browser__selected_thread(browser); | 1179 | thread = hist_browser__selected_thread(browser); |
@@ -1214,7 +1223,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1214 | } | 1223 | } |
1215 | continue; | 1224 | continue; |
1216 | case 'r': | 1225 | case 'r': |
1217 | goto do_scripts; | 1226 | if (is_report_browser(hbt)) |
1227 | goto do_scripts; | ||
1228 | continue; | ||
1218 | case K_F1: | 1229 | case K_F1: |
1219 | case 'h': | 1230 | case 'h': |
1220 | case '?': | 1231 | case '?': |
@@ -1233,7 +1244,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, | |||
1233 | "E Expand all callchains\n" | 1244 | "E Expand all callchains\n" |
1234 | "d Zoom into current DSO\n" | 1245 | "d Zoom into current DSO\n" |
1235 | "t Zoom into current Thread\n" | 1246 | "t Zoom into current Thread\n" |
1236 | "r Run available scripts\n" | 1247 | "r Run available scripts('perf report' only)\n" |
1237 | "P Print histograms to perf.hist.N\n" | 1248 | "P Print histograms to perf.hist.N\n" |
1238 | "V Verbose (DSO names in callchains, etc)\n" | 1249 | "V Verbose (DSO names in callchains, etc)\n" |
1239 | "/ Filter symbol by name"); | 1250 | "/ Filter symbol by name"); |
@@ -1358,6 +1369,9 @@ retry_popup_menu: | |||
1358 | struct hist_entry *he; | 1369 | struct hist_entry *he; |
1359 | int err; | 1370 | int err; |
1360 | do_annotate: | 1371 | do_annotate: |
1372 | if (!objdump_path && perf_session_env__lookup_objdump(env)) | ||
1373 | continue; | ||
1374 | |||
1361 | he = hist_browser__selected_entry(browser); | 1375 | he = hist_browser__selected_entry(browser); |
1362 | if (he == NULL) | 1376 | if (he == NULL) |
1363 | continue; | 1377 | continue; |
@@ -1380,8 +1394,7 @@ do_annotate: | |||
1380 | * Don't let this be freed, say, by hists__decay_entry. | 1394 | * Don't let this be freed, say, by hists__decay_entry. |
1381 | */ | 1395 | */ |
1382 | he->used = true; | 1396 | he->used = true; |
1383 | err = hist_entry__tui_annotate(he, evsel->idx, | 1397 | err = hist_entry__tui_annotate(he, evsel->idx, hbt); |
1384 | timer, arg, delay_secs); | ||
1385 | he->used = false; | 1398 | he->used = false; |
1386 | /* | 1399 | /* |
1387 | * offer option to annotate the other branch source or target | 1400 | * offer option to annotate the other branch source or target |
@@ -1462,6 +1475,7 @@ struct perf_evsel_menu { | |||
1462 | struct ui_browser b; | 1475 | struct ui_browser b; |
1463 | struct perf_evsel *selection; | 1476 | struct perf_evsel *selection; |
1464 | bool lost_events, lost_events_warned; | 1477 | bool lost_events, lost_events_warned; |
1478 | struct perf_session_env *env; | ||
1465 | }; | 1479 | }; |
1466 | 1480 | ||
1467 | static void perf_evsel_menu__write(struct ui_browser *browser, | 1481 | static void perf_evsel_menu__write(struct ui_browser *browser, |
@@ -1504,11 +1518,12 @@ static void perf_evsel_menu__write(struct ui_browser *browser, | |||
1504 | 1518 | ||
1505 | static int perf_evsel_menu__run(struct perf_evsel_menu *menu, | 1519 | static int perf_evsel_menu__run(struct perf_evsel_menu *menu, |
1506 | int nr_events, const char *help, | 1520 | int nr_events, const char *help, |
1507 | void(*timer)(void *arg), void *arg, int delay_secs) | 1521 | struct hist_browser_timer *hbt) |
1508 | { | 1522 | { |
1509 | struct perf_evlist *evlist = menu->b.priv; | 1523 | struct perf_evlist *evlist = menu->b.priv; |
1510 | struct perf_evsel *pos; | 1524 | struct perf_evsel *pos; |
1511 | const char *ev_name, *title = "Available samples"; | 1525 | const char *ev_name, *title = "Available samples"; |
1526 | int delay_secs = hbt ? hbt->refresh : 0; | ||
1512 | int key; | 1527 | int key; |
1513 | 1528 | ||
1514 | if (ui_browser__show(&menu->b, title, | 1529 | if (ui_browser__show(&menu->b, title, |
@@ -1520,7 +1535,7 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, | |||
1520 | 1535 | ||
1521 | switch (key) { | 1536 | switch (key) { |
1522 | case K_TIMER: | 1537 | case K_TIMER: |
1523 | timer(arg); | 1538 | hbt->timer(hbt->arg); |
1524 | 1539 | ||
1525 | if (!menu->lost_events_warned && menu->lost_events) { | 1540 | if (!menu->lost_events_warned && menu->lost_events) { |
1526 | ui_browser__warn_lost_events(&menu->b); | 1541 | ui_browser__warn_lost_events(&menu->b); |
@@ -1538,12 +1553,12 @@ browse_hists: | |||
1538 | * Give the calling tool a chance to populate the non | 1553 | * Give the calling tool a chance to populate the non |
1539 | * default evsel resorted hists tree. | 1554 | * default evsel resorted hists tree. |
1540 | */ | 1555 | */ |
1541 | if (timer) | 1556 | if (hbt) |
1542 | timer(arg); | 1557 | hbt->timer(hbt->arg); |
1543 | ev_name = perf_evsel__name(pos); | 1558 | ev_name = perf_evsel__name(pos); |
1544 | key = perf_evsel__hists_browse(pos, nr_events, help, | 1559 | key = perf_evsel__hists_browse(pos, nr_events, help, |
1545 | ev_name, true, timer, | 1560 | ev_name, true, hbt, |
1546 | arg, delay_secs); | 1561 | menu->env); |
1547 | ui_browser__show_title(&menu->b, title); | 1562 | ui_browser__show_title(&menu->b, title); |
1548 | switch (key) { | 1563 | switch (key) { |
1549 | case K_TAB: | 1564 | case K_TAB: |
@@ -1591,8 +1606,8 @@ out: | |||
1591 | 1606 | ||
1592 | static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, | 1607 | static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, |
1593 | const char *help, | 1608 | const char *help, |
1594 | void(*timer)(void *arg), void *arg, | 1609 | struct hist_browser_timer *hbt, |
1595 | int delay_secs) | 1610 | struct perf_session_env *env) |
1596 | { | 1611 | { |
1597 | struct perf_evsel *pos; | 1612 | struct perf_evsel *pos; |
1598 | struct perf_evsel_menu menu = { | 1613 | struct perf_evsel_menu menu = { |
@@ -1604,6 +1619,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, | |||
1604 | .nr_entries = evlist->nr_entries, | 1619 | .nr_entries = evlist->nr_entries, |
1605 | .priv = evlist, | 1620 | .priv = evlist, |
1606 | }, | 1621 | }, |
1622 | .env = env, | ||
1607 | }; | 1623 | }; |
1608 | 1624 | ||
1609 | ui_helpline__push("Press ESC to exit"); | 1625 | ui_helpline__push("Press ESC to exit"); |
@@ -1616,23 +1632,20 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, | |||
1616 | menu.b.width = line_len; | 1632 | menu.b.width = line_len; |
1617 | } | 1633 | } |
1618 | 1634 | ||
1619 | return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, | 1635 | return perf_evsel_menu__run(&menu, evlist->nr_entries, help, hbt); |
1620 | arg, delay_secs); | ||
1621 | } | 1636 | } |
1622 | 1637 | ||
1623 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, | 1638 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, |
1624 | void(*timer)(void *arg), void *arg, | 1639 | struct hist_browser_timer *hbt, |
1625 | int delay_secs) | 1640 | struct perf_session_env *env) |
1626 | { | 1641 | { |
1627 | if (evlist->nr_entries == 1) { | 1642 | if (evlist->nr_entries == 1) { |
1628 | struct perf_evsel *first = list_entry(evlist->entries.next, | 1643 | struct perf_evsel *first = list_entry(evlist->entries.next, |
1629 | struct perf_evsel, node); | 1644 | struct perf_evsel, node); |
1630 | const char *ev_name = perf_evsel__name(first); | 1645 | const char *ev_name = perf_evsel__name(first); |
1631 | return perf_evsel__hists_browse(first, evlist->nr_entries, help, | 1646 | return perf_evsel__hists_browse(first, evlist->nr_entries, help, |
1632 | ev_name, false, timer, arg, | 1647 | ev_name, false, hbt, env); |
1633 | delay_secs); | ||
1634 | } | 1648 | } |
1635 | 1649 | ||
1636 | return __perf_evlist__tui_browse_hists(evlist, help, | 1650 | return __perf_evlist__tui_browse_hists(evlist, help, hbt, env); |
1637 | timer, arg, delay_secs); | ||
1638 | } | 1651 | } |
diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 4125c6284114..253b6219a39e 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c | |||
@@ -237,9 +237,7 @@ static GtkWidget *perf_gtk__setup_statusbar(void) | |||
237 | 237 | ||
238 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, | 238 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, |
239 | const char *help, | 239 | const char *help, |
240 | void (*timer) (void *arg)__maybe_unused, | 240 | struct hist_browser_timer *hbt __maybe_unused) |
241 | void *arg __maybe_unused, | ||
242 | int delay_secs __maybe_unused) | ||
243 | { | 241 | { |
244 | struct perf_evsel *pos; | 242 | struct perf_evsel *pos; |
245 | GtkWidget *vbox; | 243 | GtkWidget *vbox; |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 4f5f4756faac..aa84130024d5 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -161,7 +161,7 @@ static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused) | |||
161 | 161 | ||
162 | static double baseline_percent(struct hist_entry *he) | 162 | static double baseline_percent(struct hist_entry *he) |
163 | { | 163 | { |
164 | struct hist_entry *pair = he->pair; | 164 | struct hist_entry *pair = hist_entry__next_pair(he); |
165 | struct hists *pair_hists = pair ? pair->hists : NULL; | 165 | struct hists *pair_hists = pair ? pair->hists : NULL; |
166 | double percent = 0.0; | 166 | double percent = 0.0; |
167 | 167 | ||
@@ -179,7 +179,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) | |||
179 | { | 179 | { |
180 | double percent = baseline_percent(he); | 180 | double percent = baseline_percent(he); |
181 | 181 | ||
182 | if (he->pair) | 182 | if (hist_entry__has_pairs(he)) |
183 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); | 183 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); |
184 | else | 184 | else |
185 | return scnprintf(hpp->buf, hpp->size, " "); | 185 | return scnprintf(hpp->buf, hpp->size, " "); |
@@ -190,7 +190,7 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) | |||
190 | double percent = baseline_percent(he); | 190 | double percent = baseline_percent(he); |
191 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; | 191 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; |
192 | 192 | ||
193 | if (he->pair || symbol_conf.field_sep) | 193 | if (hist_entry__has_pairs(he) || symbol_conf.field_sep) |
194 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 194 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
195 | else | 195 | else |
196 | return scnprintf(hpp->buf, hpp->size, " "); | 196 | return scnprintf(hpp->buf, hpp->size, " "); |
@@ -248,7 +248,7 @@ static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused) | |||
248 | 248 | ||
249 | static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) | 249 | static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) |
250 | { | 250 | { |
251 | struct hist_entry *pair = he->pair; | 251 | struct hist_entry *pair = hist_entry__next_pair(he); |
252 | u64 period = pair ? pair->stat.period : 0; | 252 | u64 period = pair ? pair->stat.period : 0; |
253 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; | 253 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; |
254 | 254 | ||
@@ -354,7 +354,7 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) | |||
354 | static int hpp__entry_displ(struct perf_hpp *hpp, | 354 | static int hpp__entry_displ(struct perf_hpp *hpp, |
355 | struct hist_entry *he) | 355 | struct hist_entry *he) |
356 | { | 356 | { |
357 | struct hist_entry *pair = he->pair; | 357 | struct hist_entry *pair = hist_entry__next_pair(he); |
358 | long displacement = pair ? pair->position - he->position : 0; | 358 | long displacement = pair ? pair->position - he->position : 0; |
359 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; | 359 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; |
360 | char buf[32] = " "; | 360 | char buf[32] = " "; |
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN index 95264f304179..6aa34e5afdcf 100755 --- a/tools/perf/util/PERF-VERSION-GEN +++ b/tools/perf/util/PERF-VERSION-GEN | |||
@@ -9,18 +9,14 @@ GVF=${OUTPUT}PERF-VERSION-FILE | |||
9 | LF=' | 9 | LF=' |
10 | ' | 10 | ' |
11 | 11 | ||
12 | # | ||
12 | # First check if there is a .git to get the version from git describe | 13 | # First check if there is a .git to get the version from git describe |
13 | # otherwise try to get the version from the kernel makefile | 14 | # otherwise try to get the version from the kernel Makefile |
15 | # | ||
14 | if test -d ../../.git -o -f ../../.git && | 16 | if test -d ../../.git -o -f ../../.git && |
15 | VN=$(git describe --match 'v[0-9].[0-9]*' --abbrev=4 HEAD 2>/dev/null) && | 17 | VN=$(git tag 2>/dev/null | tail -1 | grep -E "v[0-9].[0-9]*") |
16 | case "$VN" in | ||
17 | *$LF*) (exit 1) ;; | ||
18 | v[0-9]*) | ||
19 | git update-index -q --refresh | ||
20 | test -z "$(git diff-index --name-only HEAD --)" || | ||
21 | VN="$VN-dirty" ;; | ||
22 | esac | ||
23 | then | 18 | then |
19 | VN=$(echo $VN"-g"$(git log -1 --abbrev=4 --pretty=format:"%h" HEAD)) | ||
24 | VN=$(echo "$VN" | sed -e 's/-/./g'); | 20 | VN=$(echo "$VN" | sed -e 's/-/./g'); |
25 | else | 21 | else |
26 | VN=$(MAKEFLAGS= make -sC ../.. kernelversion) | 22 | VN=$(MAKEFLAGS= make -sC ../.. kernelversion) |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 7a34dd18b74c..07aaeea60000 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -171,15 +171,15 @@ static int lock__parse(struct ins_operands *ops) | |||
171 | if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0) | 171 | if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0) |
172 | goto out_free_ops; | 172 | goto out_free_ops; |
173 | 173 | ||
174 | ops->locked.ins = ins__find(name); | 174 | ops->locked.ins = ins__find(name); |
175 | if (ops->locked.ins == NULL) | 175 | if (ops->locked.ins == NULL) |
176 | goto out_free_ops; | 176 | goto out_free_ops; |
177 | 177 | ||
178 | if (!ops->locked.ins->ops) | 178 | if (!ops->locked.ins->ops) |
179 | return 0; | 179 | return 0; |
180 | 180 | ||
181 | if (ops->locked.ins->ops->parse) | 181 | if (ops->locked.ins->ops->parse) |
182 | ops->locked.ins->ops->parse(ops->locked.ops); | 182 | ops->locked.ins->ops->parse(ops->locked.ops); |
183 | 183 | ||
184 | return 0; | 184 | return 0; |
185 | 185 | ||
@@ -401,6 +401,8 @@ static struct ins instructions[] = { | |||
401 | { .name = "testb", .ops = &mov_ops, }, | 401 | { .name = "testb", .ops = &mov_ops, }, |
402 | { .name = "testl", .ops = &mov_ops, }, | 402 | { .name = "testl", .ops = &mov_ops, }, |
403 | { .name = "xadd", .ops = &mov_ops, }, | 403 | { .name = "xadd", .ops = &mov_ops, }, |
404 | { .name = "xbeginl", .ops = &jump_ops, }, | ||
405 | { .name = "xbeginq", .ops = &jump_ops, }, | ||
404 | }; | 406 | }; |
405 | 407 | ||
406 | static int ins__cmp(const void *name, const void *insp) | 408 | static int ins__cmp(const void *name, const void *insp) |
@@ -856,21 +858,68 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin | |||
856 | struct source_line *iter; | 858 | struct source_line *iter; |
857 | struct rb_node **p = &root->rb_node; | 859 | struct rb_node **p = &root->rb_node; |
858 | struct rb_node *parent = NULL; | 860 | struct rb_node *parent = NULL; |
861 | int ret; | ||
859 | 862 | ||
860 | while (*p != NULL) { | 863 | while (*p != NULL) { |
861 | parent = *p; | 864 | parent = *p; |
862 | iter = rb_entry(parent, struct source_line, node); | 865 | iter = rb_entry(parent, struct source_line, node); |
863 | 866 | ||
864 | if (src_line->percent > iter->percent) | 867 | ret = strcmp(iter->path, src_line->path); |
868 | if (ret == 0) { | ||
869 | iter->percent_sum += src_line->percent; | ||
870 | return; | ||
871 | } | ||
872 | |||
873 | if (ret < 0) | ||
865 | p = &(*p)->rb_left; | 874 | p = &(*p)->rb_left; |
866 | else | 875 | else |
867 | p = &(*p)->rb_right; | 876 | p = &(*p)->rb_right; |
868 | } | 877 | } |
869 | 878 | ||
879 | src_line->percent_sum = src_line->percent; | ||
880 | |||
870 | rb_link_node(&src_line->node, parent, p); | 881 | rb_link_node(&src_line->node, parent, p); |
871 | rb_insert_color(&src_line->node, root); | 882 | rb_insert_color(&src_line->node, root); |
872 | } | 883 | } |
873 | 884 | ||
885 | static void __resort_source_line(struct rb_root *root, struct source_line *src_line) | ||
886 | { | ||
887 | struct source_line *iter; | ||
888 | struct rb_node **p = &root->rb_node; | ||
889 | struct rb_node *parent = NULL; | ||
890 | |||
891 | while (*p != NULL) { | ||
892 | parent = *p; | ||
893 | iter = rb_entry(parent, struct source_line, node); | ||
894 | |||
895 | if (src_line->percent_sum > iter->percent_sum) | ||
896 | p = &(*p)->rb_left; | ||
897 | else | ||
898 | p = &(*p)->rb_right; | ||
899 | } | ||
900 | |||
901 | rb_link_node(&src_line->node, parent, p); | ||
902 | rb_insert_color(&src_line->node, root); | ||
903 | } | ||
904 | |||
905 | static void resort_source_line(struct rb_root *dest_root, struct rb_root *src_root) | ||
906 | { | ||
907 | struct source_line *src_line; | ||
908 | struct rb_node *node; | ||
909 | |||
910 | node = rb_first(src_root); | ||
911 | while (node) { | ||
912 | struct rb_node *next; | ||
913 | |||
914 | src_line = rb_entry(node, struct source_line, node); | ||
915 | next = rb_next(node); | ||
916 | rb_erase(node, src_root); | ||
917 | |||
918 | __resort_source_line(dest_root, src_line); | ||
919 | node = next; | ||
920 | } | ||
921 | } | ||
922 | |||
874 | static void symbol__free_source_line(struct symbol *sym, int len) | 923 | static void symbol__free_source_line(struct symbol *sym, int len) |
875 | { | 924 | { |
876 | struct annotation *notes = symbol__annotation(sym); | 925 | struct annotation *notes = symbol__annotation(sym); |
@@ -895,6 +944,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, | |||
895 | struct source_line *src_line; | 944 | struct source_line *src_line; |
896 | struct annotation *notes = symbol__annotation(sym); | 945 | struct annotation *notes = symbol__annotation(sym); |
897 | struct sym_hist *h = annotation__histogram(notes, evidx); | 946 | struct sym_hist *h = annotation__histogram(notes, evidx); |
947 | struct rb_root tmp_root = RB_ROOT; | ||
898 | 948 | ||
899 | if (!h->sum) | 949 | if (!h->sum) |
900 | return 0; | 950 | return 0; |
@@ -929,12 +979,13 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map, | |||
929 | goto next; | 979 | goto next; |
930 | 980 | ||
931 | strcpy(src_line[i].path, path); | 981 | strcpy(src_line[i].path, path); |
932 | insert_source_line(root, &src_line[i]); | 982 | insert_source_line(&tmp_root, &src_line[i]); |
933 | 983 | ||
934 | next: | 984 | next: |
935 | pclose(fp); | 985 | pclose(fp); |
936 | } | 986 | } |
937 | 987 | ||
988 | resort_source_line(root, &tmp_root); | ||
938 | return 0; | 989 | return 0; |
939 | } | 990 | } |
940 | 991 | ||
@@ -958,7 +1009,7 @@ static void print_summary(struct rb_root *root, const char *filename) | |||
958 | char *path; | 1009 | char *path; |
959 | 1010 | ||
960 | src_line = rb_entry(node, struct source_line, node); | 1011 | src_line = rb_entry(node, struct source_line, node); |
961 | percent = src_line->percent; | 1012 | percent = src_line->percent_sum; |
962 | color = get_percent_color(percent); | 1013 | color = get_percent_color(percent); |
963 | path = src_line->path; | 1014 | path = src_line->path; |
964 | 1015 | ||
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index a4dd25a61a07..8eec94358a4a 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <stdint.h> | 5 | #include <stdint.h> |
6 | #include "types.h" | 6 | #include "types.h" |
7 | #include "symbol.h" | 7 | #include "symbol.h" |
8 | #include "hist.h" | ||
8 | #include <linux/list.h> | 9 | #include <linux/list.h> |
9 | #include <linux/rbtree.h> | 10 | #include <linux/rbtree.h> |
10 | #include <pthread.h> | 11 | #include <pthread.h> |
@@ -75,6 +76,7 @@ struct sym_hist { | |||
75 | struct source_line { | 76 | struct source_line { |
76 | struct rb_node node; | 77 | struct rb_node node; |
77 | double percent; | 78 | double percent; |
79 | double percent_sum; | ||
78 | char *path; | 80 | char *path; |
79 | }; | 81 | }; |
80 | 82 | ||
@@ -140,14 +142,13 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, | |||
140 | 142 | ||
141 | #ifdef NEWT_SUPPORT | 143 | #ifdef NEWT_SUPPORT |
142 | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | 144 | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, |
143 | void(*timer)(void *arg), void *arg, int delay_secs); | 145 | struct hist_browser_timer *hbt); |
144 | #else | 146 | #else |
145 | static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, | 147 | static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, |
146 | struct map *map __maybe_unused, | 148 | struct map *map __maybe_unused, |
147 | int evidx __maybe_unused, | 149 | int evidx __maybe_unused, |
148 | void(*timer)(void *arg) __maybe_unused, | 150 | struct hist_browser_timer *hbt |
149 | void *arg __maybe_unused, | 151 | __maybe_unused) |
150 | int delay_secs __maybe_unused) | ||
151 | { | 152 | { |
152 | return 0; | 153 | return 0; |
153 | } | 154 | } |
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index db24a3f0c820..d6d9a465acdb 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "symbol.h" | 1 | #include "symbol.h" |
2 | #include "dso.h" | 2 | #include "dso.h" |
3 | #include "machine.h" | ||
3 | #include "util.h" | 4 | #include "util.h" |
4 | #include "debug.h" | 5 | #include "debug.h" |
5 | 6 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 277947a669b2..7c6e73b1b7ea 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -244,6 +244,8 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) | |||
244 | he->ms.map->referenced = true; | 244 | he->ms.map->referenced = true; |
245 | if (symbol_conf.use_callchain) | 245 | if (symbol_conf.use_callchain) |
246 | callchain_init(he->callchain); | 246 | callchain_init(he->callchain); |
247 | |||
248 | INIT_LIST_HEAD(&he->pairs.node); | ||
247 | } | 249 | } |
248 | 250 | ||
249 | return he; | 251 | return he; |
@@ -410,6 +412,7 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) | |||
410 | 412 | ||
411 | void hist_entry__free(struct hist_entry *he) | 413 | void hist_entry__free(struct hist_entry *he) |
412 | { | 414 | { |
415 | free(he->branch_info); | ||
413 | free(he); | 416 | free(he); |
414 | } | 417 | } |
415 | 418 | ||
@@ -713,3 +716,100 @@ void hists__inc_nr_events(struct hists *hists, u32 type) | |||
713 | ++hists->stats.nr_events[0]; | 716 | ++hists->stats.nr_events[0]; |
714 | ++hists->stats.nr_events[type]; | 717 | ++hists->stats.nr_events[type]; |
715 | } | 718 | } |
719 | |||
720 | static struct hist_entry *hists__add_dummy_entry(struct hists *hists, | ||
721 | struct hist_entry *pair) | ||
722 | { | ||
723 | struct rb_node **p = &hists->entries.rb_node; | ||
724 | struct rb_node *parent = NULL; | ||
725 | struct hist_entry *he; | ||
726 | int cmp; | ||
727 | |||
728 | while (*p != NULL) { | ||
729 | parent = *p; | ||
730 | he = rb_entry(parent, struct hist_entry, rb_node); | ||
731 | |||
732 | cmp = hist_entry__cmp(pair, he); | ||
733 | |||
734 | if (!cmp) | ||
735 | goto out; | ||
736 | |||
737 | if (cmp < 0) | ||
738 | p = &(*p)->rb_left; | ||
739 | else | ||
740 | p = &(*p)->rb_right; | ||
741 | } | ||
742 | |||
743 | he = hist_entry__new(pair); | ||
744 | if (he) { | ||
745 | he->stat.nr_events = 0; | ||
746 | he->stat.period = 0; | ||
747 | he->hists = hists; | ||
748 | rb_link_node(&he->rb_node, parent, p); | ||
749 | rb_insert_color(&he->rb_node, &hists->entries); | ||
750 | hists__inc_nr_entries(hists, he); | ||
751 | } | ||
752 | out: | ||
753 | return he; | ||
754 | } | ||
755 | |||
756 | static struct hist_entry *hists__find_entry(struct hists *hists, | ||
757 | struct hist_entry *he) | ||
758 | { | ||
759 | struct rb_node *n = hists->entries.rb_node; | ||
760 | |||
761 | while (n) { | ||
762 | struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node); | ||
763 | int64_t cmp = hist_entry__cmp(he, iter); | ||
764 | |||
765 | if (cmp < 0) | ||
766 | n = n->rb_left; | ||
767 | else if (cmp > 0) | ||
768 | n = n->rb_right; | ||
769 | else | ||
770 | return iter; | ||
771 | } | ||
772 | |||
773 | return NULL; | ||
774 | } | ||
775 | |||
776 | /* | ||
777 | * Look for pairs to link to the leader buckets (hist_entries): | ||
778 | */ | ||
779 | void hists__match(struct hists *leader, struct hists *other) | ||
780 | { | ||
781 | struct rb_node *nd; | ||
782 | struct hist_entry *pos, *pair; | ||
783 | |||
784 | for (nd = rb_first(&leader->entries); nd; nd = rb_next(nd)) { | ||
785 | pos = rb_entry(nd, struct hist_entry, rb_node); | ||
786 | pair = hists__find_entry(other, pos); | ||
787 | |||
788 | if (pair) | ||
789 | hist__entry_add_pair(pos, pair); | ||
790 | } | ||
791 | } | ||
792 | |||
793 | /* | ||
794 | * Look for entries in the other hists that are not present in the leader, if | ||
795 | * we find them, just add a dummy entry on the leader hists, with period=0, | ||
796 | * nr_events=0, to serve as the list header. | ||
797 | */ | ||
798 | int hists__link(struct hists *leader, struct hists *other) | ||
799 | { | ||
800 | struct rb_node *nd; | ||
801 | struct hist_entry *pos, *pair; | ||
802 | |||
803 | for (nd = rb_first(&other->entries); nd; nd = rb_next(nd)) { | ||
804 | pos = rb_entry(nd, struct hist_entry, rb_node); | ||
805 | |||
806 | if (!hist_entry__has_pairs(pos)) { | ||
807 | pair = hists__add_dummy_entry(leader, pos); | ||
808 | if (pair == NULL) | ||
809 | return -1; | ||
810 | hist__entry_add_pair(pair, pos); | ||
811 | } | ||
812 | } | ||
813 | |||
814 | return 0; | ||
815 | } | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index b87460971736..1278c2c72a96 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <pthread.h> | 5 | #include <pthread.h> |
6 | #include "callchain.h" | 6 | #include "callchain.h" |
7 | #include "header.h" | ||
7 | 8 | ||
8 | extern struct callchain_param callchain_param; | 9 | extern struct callchain_param callchain_param; |
9 | 10 | ||
@@ -114,6 +115,9 @@ bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len); | |||
114 | void hists__reset_col_len(struct hists *hists); | 115 | void hists__reset_col_len(struct hists *hists); |
115 | void hists__calc_col_len(struct hists *hists, struct hist_entry *he); | 116 | void hists__calc_col_len(struct hists *hists, struct hist_entry *he); |
116 | 117 | ||
118 | void hists__match(struct hists *leader, struct hists *other); | ||
119 | int hists__link(struct hists *leader, struct hists *other); | ||
120 | |||
117 | struct perf_hpp { | 121 | struct perf_hpp { |
118 | char *buf; | 122 | char *buf; |
119 | size_t size; | 123 | size_t size; |
@@ -157,22 +161,27 @@ int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he, | |||
157 | 161 | ||
158 | struct perf_evlist; | 162 | struct perf_evlist; |
159 | 163 | ||
164 | struct hist_browser_timer { | ||
165 | void (*timer)(void *arg); | ||
166 | void *arg; | ||
167 | int refresh; | ||
168 | }; | ||
169 | |||
160 | #ifdef NEWT_SUPPORT | 170 | #ifdef NEWT_SUPPORT |
161 | #include "../ui/keysyms.h" | 171 | #include "../ui/keysyms.h" |
162 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, | 172 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx, |
163 | void(*timer)(void *arg), void *arg, int delay_secs); | 173 | struct hist_browser_timer *hbt); |
164 | 174 | ||
165 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, | 175 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, |
166 | void(*timer)(void *arg), void *arg, | 176 | struct hist_browser_timer *hbt, |
167 | int refresh); | 177 | struct perf_session_env *env); |
168 | int script_browse(const char *script_opt); | 178 | int script_browse(const char *script_opt); |
169 | #else | 179 | #else |
170 | static inline | 180 | static inline |
171 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, | 181 | int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, |
172 | const char *help __maybe_unused, | 182 | const char *help __maybe_unused, |
173 | void(*timer)(void *arg) __maybe_unused, | 183 | struct hist_browser_timer *hbt __maybe_unused, |
174 | void *arg __maybe_unused, | 184 | struct perf_session_env *env __maybe_unused) |
175 | int refresh __maybe_unused) | ||
176 | { | 185 | { |
177 | return 0; | 186 | return 0; |
178 | } | 187 | } |
@@ -180,10 +189,8 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, | |||
180 | static inline int hist_entry__tui_annotate(struct hist_entry *self | 189 | static inline int hist_entry__tui_annotate(struct hist_entry *self |
181 | __maybe_unused, | 190 | __maybe_unused, |
182 | int evidx __maybe_unused, | 191 | int evidx __maybe_unused, |
183 | void(*timer)(void *arg) | 192 | struct hist_browser_timer *hbt |
184 | __maybe_unused, | 193 | __maybe_unused) |
185 | void *arg __maybe_unused, | ||
186 | int delay_secs __maybe_unused) | ||
187 | { | 194 | { |
188 | return 0; | 195 | return 0; |
189 | } | 196 | } |
@@ -199,15 +206,12 @@ static inline int script_browse(const char *script_opt) | |||
199 | 206 | ||
200 | #ifdef GTK2_SUPPORT | 207 | #ifdef GTK2_SUPPORT |
201 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, | 208 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, |
202 | void(*timer)(void *arg), void *arg, | 209 | struct hist_browser_timer *hbt __maybe_unused); |
203 | int refresh); | ||
204 | #else | 210 | #else |
205 | static inline | 211 | static inline |
206 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, | 212 | int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, |
207 | const char *help __maybe_unused, | 213 | const char *help __maybe_unused, |
208 | void(*timer)(void *arg) __maybe_unused, | 214 | struct hist_browser_timer *hbt __maybe_unused) |
209 | void *arg __maybe_unused, | ||
210 | int refresh __maybe_unused) | ||
211 | { | 215 | { |
212 | return 0; | 216 | return 0; |
213 | } | 217 | } |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 502eec0d4773..1f09d0581e6b 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -2,9 +2,192 @@ | |||
2 | #include "event.h" | 2 | #include "event.h" |
3 | #include "machine.h" | 3 | #include "machine.h" |
4 | #include "map.h" | 4 | #include "map.h" |
5 | #include "strlist.h" | ||
5 | #include "thread.h" | 6 | #include "thread.h" |
6 | #include <stdbool.h> | 7 | #include <stdbool.h> |
7 | 8 | ||
9 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | ||
10 | { | ||
11 | map_groups__init(&machine->kmaps); | ||
12 | RB_CLEAR_NODE(&machine->rb_node); | ||
13 | INIT_LIST_HEAD(&machine->user_dsos); | ||
14 | INIT_LIST_HEAD(&machine->kernel_dsos); | ||
15 | |||
16 | machine->threads = RB_ROOT; | ||
17 | INIT_LIST_HEAD(&machine->dead_threads); | ||
18 | machine->last_match = NULL; | ||
19 | |||
20 | machine->kmaps.machine = machine; | ||
21 | machine->pid = pid; | ||
22 | |||
23 | machine->root_dir = strdup(root_dir); | ||
24 | if (machine->root_dir == NULL) | ||
25 | return -ENOMEM; | ||
26 | |||
27 | if (pid != HOST_KERNEL_ID) { | ||
28 | struct thread *thread = machine__findnew_thread(machine, pid); | ||
29 | char comm[64]; | ||
30 | |||
31 | if (thread == NULL) | ||
32 | return -ENOMEM; | ||
33 | |||
34 | snprintf(comm, sizeof(comm), "[guest/%d]", pid); | ||
35 | thread__set_comm(thread, comm); | ||
36 | } | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static void dsos__delete(struct list_head *dsos) | ||
42 | { | ||
43 | struct dso *pos, *n; | ||
44 | |||
45 | list_for_each_entry_safe(pos, n, dsos, node) { | ||
46 | list_del(&pos->node); | ||
47 | dso__delete(pos); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | void machine__exit(struct machine *machine) | ||
52 | { | ||
53 | map_groups__exit(&machine->kmaps); | ||
54 | dsos__delete(&machine->user_dsos); | ||
55 | dsos__delete(&machine->kernel_dsos); | ||
56 | free(machine->root_dir); | ||
57 | machine->root_dir = NULL; | ||
58 | } | ||
59 | |||
60 | void machine__delete(struct machine *machine) | ||
61 | { | ||
62 | machine__exit(machine); | ||
63 | free(machine); | ||
64 | } | ||
65 | |||
66 | struct machine *machines__add(struct rb_root *machines, pid_t pid, | ||
67 | const char *root_dir) | ||
68 | { | ||
69 | struct rb_node **p = &machines->rb_node; | ||
70 | struct rb_node *parent = NULL; | ||
71 | struct machine *pos, *machine = malloc(sizeof(*machine)); | ||
72 | |||
73 | if (machine == NULL) | ||
74 | return NULL; | ||
75 | |||
76 | if (machine__init(machine, root_dir, pid) != 0) { | ||
77 | free(machine); | ||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | while (*p != NULL) { | ||
82 | parent = *p; | ||
83 | pos = rb_entry(parent, struct machine, rb_node); | ||
84 | if (pid < pos->pid) | ||
85 | p = &(*p)->rb_left; | ||
86 | else | ||
87 | p = &(*p)->rb_right; | ||
88 | } | ||
89 | |||
90 | rb_link_node(&machine->rb_node, parent, p); | ||
91 | rb_insert_color(&machine->rb_node, machines); | ||
92 | |||
93 | return machine; | ||
94 | } | ||
95 | |||
96 | struct machine *machines__find(struct rb_root *machines, pid_t pid) | ||
97 | { | ||
98 | struct rb_node **p = &machines->rb_node; | ||
99 | struct rb_node *parent = NULL; | ||
100 | struct machine *machine; | ||
101 | struct machine *default_machine = NULL; | ||
102 | |||
103 | while (*p != NULL) { | ||
104 | parent = *p; | ||
105 | machine = rb_entry(parent, struct machine, rb_node); | ||
106 | if (pid < machine->pid) | ||
107 | p = &(*p)->rb_left; | ||
108 | else if (pid > machine->pid) | ||
109 | p = &(*p)->rb_right; | ||
110 | else | ||
111 | return machine; | ||
112 | if (!machine->pid) | ||
113 | default_machine = machine; | ||
114 | } | ||
115 | |||
116 | return default_machine; | ||
117 | } | ||
118 | |||
119 | struct machine *machines__findnew(struct rb_root *machines, pid_t pid) | ||
120 | { | ||
121 | char path[PATH_MAX]; | ||
122 | const char *root_dir = ""; | ||
123 | struct machine *machine = machines__find(machines, pid); | ||
124 | |||
125 | if (machine && (machine->pid == pid)) | ||
126 | goto out; | ||
127 | |||
128 | if ((pid != HOST_KERNEL_ID) && | ||
129 | (pid != DEFAULT_GUEST_KERNEL_ID) && | ||
130 | (symbol_conf.guestmount)) { | ||
131 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); | ||
132 | if (access(path, R_OK)) { | ||
133 | static struct strlist *seen; | ||
134 | |||
135 | if (!seen) | ||
136 | seen = strlist__new(true, NULL); | ||
137 | |||
138 | if (!strlist__has_entry(seen, path)) { | ||
139 | pr_err("Can't access file %s\n", path); | ||
140 | strlist__add(seen, path); | ||
141 | } | ||
142 | machine = NULL; | ||
143 | goto out; | ||
144 | } | ||
145 | root_dir = path; | ||
146 | } | ||
147 | |||
148 | machine = machines__add(machines, pid, root_dir); | ||
149 | out: | ||
150 | return machine; | ||
151 | } | ||
152 | |||
153 | void machines__process(struct rb_root *machines, | ||
154 | machine__process_t process, void *data) | ||
155 | { | ||
156 | struct rb_node *nd; | ||
157 | |||
158 | for (nd = rb_first(machines); nd; nd = rb_next(nd)) { | ||
159 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
160 | process(pos, data); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | char *machine__mmap_name(struct machine *machine, char *bf, size_t size) | ||
165 | { | ||
166 | if (machine__is_host(machine)) | ||
167 | snprintf(bf, size, "[%s]", "kernel.kallsyms"); | ||
168 | else if (machine__is_default_guest(machine)) | ||
169 | snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); | ||
170 | else { | ||
171 | snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", | ||
172 | machine->pid); | ||
173 | } | ||
174 | |||
175 | return bf; | ||
176 | } | ||
177 | |||
178 | void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size) | ||
179 | { | ||
180 | struct rb_node *node; | ||
181 | struct machine *machine; | ||
182 | |||
183 | for (node = rb_first(machines); node; node = rb_next(node)) { | ||
184 | machine = rb_entry(node, struct machine, rb_node); | ||
185 | machine->id_hdr_size = id_hdr_size; | ||
186 | } | ||
187 | |||
188 | return; | ||
189 | } | ||
190 | |||
8 | static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, | 191 | static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, |
9 | bool create) | 192 | bool create) |
10 | { | 193 | { |
@@ -84,15 +267,19 @@ int machine__process_lost_event(struct machine *machine __maybe_unused, | |||
84 | static void machine__set_kernel_mmap_len(struct machine *machine, | 267 | static void machine__set_kernel_mmap_len(struct machine *machine, |
85 | union perf_event *event) | 268 | union perf_event *event) |
86 | { | 269 | { |
87 | machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start; | 270 | int i; |
88 | machine->vmlinux_maps[MAP__FUNCTION]->end = (event->mmap.start + | 271 | |
89 | event->mmap.len); | 272 | for (i = 0; i < MAP__NR_TYPES; i++) { |
90 | /* | 273 | machine->vmlinux_maps[i]->start = event->mmap.start; |
91 | * Be a bit paranoid here, some perf.data file came with | 274 | machine->vmlinux_maps[i]->end = (event->mmap.start + |
92 | * a zero sized synthesized MMAP event for the kernel. | 275 | event->mmap.len); |
93 | */ | 276 | /* |
94 | if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0) | 277 | * Be a bit paranoid here, some perf.data file came with |
95 | machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL; | 278 | * a zero sized synthesized MMAP event for the kernel. |
279 | */ | ||
280 | if (machine->vmlinux_maps[i]->end == 0) | ||
281 | machine->vmlinux_maps[i]->end = ~0ULL; | ||
282 | } | ||
96 | } | 283 | } |
97 | 284 | ||
98 | static int machine__process_kernel_mmap_event(struct machine *machine, | 285 | static int machine__process_kernel_mmap_event(struct machine *machine, |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index df152f1768be..b7cde7467d55 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -2,11 +2,40 @@ | |||
2 | #define __PERF_MACHINE_H | 2 | #define __PERF_MACHINE_H |
3 | 3 | ||
4 | #include <sys/types.h> | 4 | #include <sys/types.h> |
5 | #include <linux/rbtree.h> | ||
6 | #include "map.h" | ||
5 | 7 | ||
8 | struct branch_stack; | ||
9 | struct perf_evsel; | ||
10 | struct perf_sample; | ||
11 | struct symbol; | ||
6 | struct thread; | 12 | struct thread; |
7 | struct machine; | ||
8 | union perf_event; | 13 | union perf_event; |
9 | 14 | ||
15 | /* Native host kernel uses -1 as pid index in machine */ | ||
16 | #define HOST_KERNEL_ID (-1) | ||
17 | #define DEFAULT_GUEST_KERNEL_ID (0) | ||
18 | |||
19 | struct machine { | ||
20 | struct rb_node rb_node; | ||
21 | pid_t pid; | ||
22 | u16 id_hdr_size; | ||
23 | char *root_dir; | ||
24 | struct rb_root threads; | ||
25 | struct list_head dead_threads; | ||
26 | struct thread *last_match; | ||
27 | struct list_head user_dsos; | ||
28 | struct list_head kernel_dsos; | ||
29 | struct map_groups kmaps; | ||
30 | struct map *vmlinux_maps[MAP__NR_TYPES]; | ||
31 | }; | ||
32 | |||
33 | static inline | ||
34 | struct map *machine__kernel_map(struct machine *machine, enum map_type type) | ||
35 | { | ||
36 | return machine->vmlinux_maps[type]; | ||
37 | } | ||
38 | |||
10 | struct thread *machine__find_thread(struct machine *machine, pid_t pid); | 39 | struct thread *machine__find_thread(struct machine *machine, pid_t pid); |
11 | 40 | ||
12 | int machine__process_comm_event(struct machine *machine, union perf_event *event); | 41 | int machine__process_comm_event(struct machine *machine, union perf_event *event); |
@@ -16,4 +45,104 @@ int machine__process_lost_event(struct machine *machine, union perf_event *event | |||
16 | int machine__process_mmap_event(struct machine *machine, union perf_event *event); | 45 | int machine__process_mmap_event(struct machine *machine, union perf_event *event); |
17 | int machine__process_event(struct machine *machine, union perf_event *event); | 46 | int machine__process_event(struct machine *machine, union perf_event *event); |
18 | 47 | ||
48 | typedef void (*machine__process_t)(struct machine *machine, void *data); | ||
49 | |||
50 | void machines__process(struct rb_root *machines, | ||
51 | machine__process_t process, void *data); | ||
52 | |||
53 | struct machine *machines__add(struct rb_root *machines, pid_t pid, | ||
54 | const char *root_dir); | ||
55 | struct machine *machines__find_host(struct rb_root *machines); | ||
56 | struct machine *machines__find(struct rb_root *machines, pid_t pid); | ||
57 | struct machine *machines__findnew(struct rb_root *machines, pid_t pid); | ||
58 | |||
59 | void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size); | ||
60 | char *machine__mmap_name(struct machine *machine, char *bf, size_t size); | ||
61 | |||
62 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid); | ||
63 | void machine__exit(struct machine *machine); | ||
64 | void machine__delete(struct machine *machine); | ||
65 | |||
66 | |||
67 | struct branch_info *machine__resolve_bstack(struct machine *machine, | ||
68 | struct thread *thread, | ||
69 | struct branch_stack *bs); | ||
70 | int machine__resolve_callchain(struct machine *machine, | ||
71 | struct perf_evsel *evsel, | ||
72 | struct thread *thread, | ||
73 | struct perf_sample *sample, | ||
74 | struct symbol **parent); | ||
75 | |||
76 | /* | ||
77 | * Default guest kernel is defined by parameter --guestkallsyms | ||
78 | * and --guestmodules | ||
79 | */ | ||
80 | static inline bool machine__is_default_guest(struct machine *machine) | ||
81 | { | ||
82 | return machine ? machine->pid == DEFAULT_GUEST_KERNEL_ID : false; | ||
83 | } | ||
84 | |||
85 | static inline bool machine__is_host(struct machine *machine) | ||
86 | { | ||
87 | return machine ? machine->pid == HOST_KERNEL_ID : false; | ||
88 | } | ||
89 | |||
90 | struct thread *machine__findnew_thread(struct machine *machine, pid_t pid); | ||
91 | void machine__remove_thread(struct machine *machine, struct thread *th); | ||
92 | |||
93 | size_t machine__fprintf(struct machine *machine, FILE *fp); | ||
94 | |||
95 | static inline | ||
96 | struct symbol *machine__find_kernel_symbol(struct machine *machine, | ||
97 | enum map_type type, u64 addr, | ||
98 | struct map **mapp, | ||
99 | symbol_filter_t filter) | ||
100 | { | ||
101 | return map_groups__find_symbol(&machine->kmaps, type, addr, | ||
102 | mapp, filter); | ||
103 | } | ||
104 | |||
105 | static inline | ||
106 | struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr, | ||
107 | struct map **mapp, | ||
108 | symbol_filter_t filter) | ||
109 | { | ||
110 | return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr, | ||
111 | mapp, filter); | ||
112 | } | ||
113 | |||
114 | static inline | ||
115 | struct symbol *machine__find_kernel_function_by_name(struct machine *machine, | ||
116 | const char *name, | ||
117 | struct map **mapp, | ||
118 | symbol_filter_t filter) | ||
119 | { | ||
120 | return map_groups__find_function_by_name(&machine->kmaps, name, mapp, | ||
121 | filter); | ||
122 | } | ||
123 | |||
124 | struct map *machine__new_module(struct machine *machine, u64 start, | ||
125 | const char *filename); | ||
126 | |||
127 | int machine__load_kallsyms(struct machine *machine, const char *filename, | ||
128 | enum map_type type, symbol_filter_t filter); | ||
129 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, | ||
130 | symbol_filter_t filter); | ||
131 | |||
132 | size_t machine__fprintf_dsos_buildid(struct machine *machine, | ||
133 | FILE *fp, bool with_hits); | ||
134 | size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); | ||
135 | size_t machines__fprintf_dsos_buildid(struct rb_root *machines, | ||
136 | FILE *fp, bool with_hits); | ||
137 | |||
138 | void machine__destroy_kernel_maps(struct machine *machine); | ||
139 | int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); | ||
140 | int machine__create_kernel_maps(struct machine *machine); | ||
141 | |||
142 | int machines__create_kernel_maps(struct rb_root *machines, pid_t pid); | ||
143 | int machines__create_guest_kernel_maps(struct rb_root *machines); | ||
144 | void machines__destroy_guest_kernel_maps(struct rb_root *machines); | ||
145 | |||
146 | size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); | ||
147 | |||
19 | #endif /* __PERF_MACHINE_H */ | 148 | #endif /* __PERF_MACHINE_H */ |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 9b40c444039c..0328d45c4f2a 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -24,7 +24,7 @@ static inline int is_anon_memory(const char *filename) | |||
24 | 24 | ||
25 | static inline int is_no_dso_memory(const char *filename) | 25 | static inline int is_no_dso_memory(const char *filename) |
26 | { | 26 | { |
27 | return !strcmp(filename, "[stack]") || | 27 | return !strncmp(filename, "[stack", 6) || |
28 | !strcmp(filename, "[heap]"); | 28 | !strcmp(filename, "[heap]"); |
29 | } | 29 | } |
30 | 30 | ||
@@ -590,182 +590,3 @@ struct map *maps__find(struct rb_root *maps, u64 ip) | |||
590 | 590 | ||
591 | return NULL; | 591 | return NULL; |
592 | } | 592 | } |
593 | |||
594 | int machine__init(struct machine *self, const char *root_dir, pid_t pid) | ||
595 | { | ||
596 | map_groups__init(&self->kmaps); | ||
597 | RB_CLEAR_NODE(&self->rb_node); | ||
598 | INIT_LIST_HEAD(&self->user_dsos); | ||
599 | INIT_LIST_HEAD(&self->kernel_dsos); | ||
600 | |||
601 | self->threads = RB_ROOT; | ||
602 | INIT_LIST_HEAD(&self->dead_threads); | ||
603 | self->last_match = NULL; | ||
604 | |||
605 | self->kmaps.machine = self; | ||
606 | self->pid = pid; | ||
607 | self->root_dir = strdup(root_dir); | ||
608 | if (self->root_dir == NULL) | ||
609 | return -ENOMEM; | ||
610 | |||
611 | if (pid != HOST_KERNEL_ID) { | ||
612 | struct thread *thread = machine__findnew_thread(self, pid); | ||
613 | char comm[64]; | ||
614 | |||
615 | if (thread == NULL) | ||
616 | return -ENOMEM; | ||
617 | |||
618 | snprintf(comm, sizeof(comm), "[guest/%d]", pid); | ||
619 | thread__set_comm(thread, comm); | ||
620 | } | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static void dsos__delete(struct list_head *self) | ||
626 | { | ||
627 | struct dso *pos, *n; | ||
628 | |||
629 | list_for_each_entry_safe(pos, n, self, node) { | ||
630 | list_del(&pos->node); | ||
631 | dso__delete(pos); | ||
632 | } | ||
633 | } | ||
634 | |||
635 | void machine__exit(struct machine *self) | ||
636 | { | ||
637 | map_groups__exit(&self->kmaps); | ||
638 | dsos__delete(&self->user_dsos); | ||
639 | dsos__delete(&self->kernel_dsos); | ||
640 | free(self->root_dir); | ||
641 | self->root_dir = NULL; | ||
642 | } | ||
643 | |||
644 | void machine__delete(struct machine *self) | ||
645 | { | ||
646 | machine__exit(self); | ||
647 | free(self); | ||
648 | } | ||
649 | |||
650 | struct machine *machines__add(struct rb_root *self, pid_t pid, | ||
651 | const char *root_dir) | ||
652 | { | ||
653 | struct rb_node **p = &self->rb_node; | ||
654 | struct rb_node *parent = NULL; | ||
655 | struct machine *pos, *machine = malloc(sizeof(*machine)); | ||
656 | |||
657 | if (!machine) | ||
658 | return NULL; | ||
659 | |||
660 | if (machine__init(machine, root_dir, pid) != 0) { | ||
661 | free(machine); | ||
662 | return NULL; | ||
663 | } | ||
664 | |||
665 | while (*p != NULL) { | ||
666 | parent = *p; | ||
667 | pos = rb_entry(parent, struct machine, rb_node); | ||
668 | if (pid < pos->pid) | ||
669 | p = &(*p)->rb_left; | ||
670 | else | ||
671 | p = &(*p)->rb_right; | ||
672 | } | ||
673 | |||
674 | rb_link_node(&machine->rb_node, parent, p); | ||
675 | rb_insert_color(&machine->rb_node, self); | ||
676 | |||
677 | return machine; | ||
678 | } | ||
679 | |||
680 | struct machine *machines__find(struct rb_root *self, pid_t pid) | ||
681 | { | ||
682 | struct rb_node **p = &self->rb_node; | ||
683 | struct rb_node *parent = NULL; | ||
684 | struct machine *machine; | ||
685 | struct machine *default_machine = NULL; | ||
686 | |||
687 | while (*p != NULL) { | ||
688 | parent = *p; | ||
689 | machine = rb_entry(parent, struct machine, rb_node); | ||
690 | if (pid < machine->pid) | ||
691 | p = &(*p)->rb_left; | ||
692 | else if (pid > machine->pid) | ||
693 | p = &(*p)->rb_right; | ||
694 | else | ||
695 | return machine; | ||
696 | if (!machine->pid) | ||
697 | default_machine = machine; | ||
698 | } | ||
699 | |||
700 | return default_machine; | ||
701 | } | ||
702 | |||
703 | struct machine *machines__findnew(struct rb_root *self, pid_t pid) | ||
704 | { | ||
705 | char path[PATH_MAX]; | ||
706 | const char *root_dir = ""; | ||
707 | struct machine *machine = machines__find(self, pid); | ||
708 | |||
709 | if (machine && (machine->pid == pid)) | ||
710 | goto out; | ||
711 | |||
712 | if ((pid != HOST_KERNEL_ID) && | ||
713 | (pid != DEFAULT_GUEST_KERNEL_ID) && | ||
714 | (symbol_conf.guestmount)) { | ||
715 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); | ||
716 | if (access(path, R_OK)) { | ||
717 | static struct strlist *seen; | ||
718 | |||
719 | if (!seen) | ||
720 | seen = strlist__new(true, NULL); | ||
721 | |||
722 | if (!strlist__has_entry(seen, path)) { | ||
723 | pr_err("Can't access file %s\n", path); | ||
724 | strlist__add(seen, path); | ||
725 | } | ||
726 | machine = NULL; | ||
727 | goto out; | ||
728 | } | ||
729 | root_dir = path; | ||
730 | } | ||
731 | |||
732 | machine = machines__add(self, pid, root_dir); | ||
733 | |||
734 | out: | ||
735 | return machine; | ||
736 | } | ||
737 | |||
738 | void machines__process(struct rb_root *self, machine__process_t process, void *data) | ||
739 | { | ||
740 | struct rb_node *nd; | ||
741 | |||
742 | for (nd = rb_first(self); nd; nd = rb_next(nd)) { | ||
743 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
744 | process(pos, data); | ||
745 | } | ||
746 | } | ||
747 | |||
748 | char *machine__mmap_name(struct machine *self, char *bf, size_t size) | ||
749 | { | ||
750 | if (machine__is_host(self)) | ||
751 | snprintf(bf, size, "[%s]", "kernel.kallsyms"); | ||
752 | else if (machine__is_default_guest(self)) | ||
753 | snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); | ||
754 | else | ||
755 | snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", self->pid); | ||
756 | |||
757 | return bf; | ||
758 | } | ||
759 | |||
760 | void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size) | ||
761 | { | ||
762 | struct rb_node *node; | ||
763 | struct machine *machine; | ||
764 | |||
765 | for (node = rb_first(machines); node; node = rb_next(node)) { | ||
766 | machine = rb_entry(node, struct machine, rb_node); | ||
767 | machine->id_hdr_size = id_hdr_size; | ||
768 | } | ||
769 | |||
770 | return; | ||
771 | } | ||
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index d2250fc97e25..bcb39e2a6965 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -57,30 +57,6 @@ struct map_groups { | |||
57 | struct machine *machine; | 57 | struct machine *machine; |
58 | }; | 58 | }; |
59 | 59 | ||
60 | /* Native host kernel uses -1 as pid index in machine */ | ||
61 | #define HOST_KERNEL_ID (-1) | ||
62 | #define DEFAULT_GUEST_KERNEL_ID (0) | ||
63 | |||
64 | struct machine { | ||
65 | struct rb_node rb_node; | ||
66 | pid_t pid; | ||
67 | u16 id_hdr_size; | ||
68 | char *root_dir; | ||
69 | struct rb_root threads; | ||
70 | struct list_head dead_threads; | ||
71 | struct thread *last_match; | ||
72 | struct list_head user_dsos; | ||
73 | struct list_head kernel_dsos; | ||
74 | struct map_groups kmaps; | ||
75 | struct map *vmlinux_maps[MAP__NR_TYPES]; | ||
76 | }; | ||
77 | |||
78 | static inline | ||
79 | struct map *machine__kernel_map(struct machine *self, enum map_type type) | ||
80 | { | ||
81 | return self->vmlinux_maps[type]; | ||
82 | } | ||
83 | |||
84 | static inline struct kmap *map__kmap(struct map *self) | 60 | static inline struct kmap *map__kmap(struct map *self) |
85 | { | 61 | { |
86 | return (struct kmap *)(self + 1); | 62 | return (struct kmap *)(self + 1); |
@@ -143,44 +119,9 @@ int map_groups__clone(struct map_groups *mg, | |||
143 | size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp); | 119 | size_t map_groups__fprintf(struct map_groups *mg, int verbose, FILE *fp); |
144 | size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp); | 120 | size_t map_groups__fprintf_maps(struct map_groups *mg, int verbose, FILE *fp); |
145 | 121 | ||
146 | typedef void (*machine__process_t)(struct machine *self, void *data); | ||
147 | |||
148 | void machines__process(struct rb_root *self, machine__process_t process, void *data); | ||
149 | struct machine *machines__add(struct rb_root *self, pid_t pid, | ||
150 | const char *root_dir); | ||
151 | struct machine *machines__find_host(struct rb_root *self); | ||
152 | struct machine *machines__find(struct rb_root *self, pid_t pid); | ||
153 | struct machine *machines__findnew(struct rb_root *self, pid_t pid); | ||
154 | void machines__set_id_hdr_size(struct rb_root *self, u16 id_hdr_size); | ||
155 | char *machine__mmap_name(struct machine *self, char *bf, size_t size); | ||
156 | int machine__init(struct machine *self, const char *root_dir, pid_t pid); | ||
157 | void machine__exit(struct machine *self); | ||
158 | void machine__delete(struct machine *self); | ||
159 | |||
160 | struct perf_evsel; | ||
161 | struct perf_sample; | ||
162 | int machine__resolve_callchain(struct machine *machine, | ||
163 | struct perf_evsel *evsel, | ||
164 | struct thread *thread, | ||
165 | struct perf_sample *sample, | ||
166 | struct symbol **parent); | ||
167 | int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, | 122 | int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name, |
168 | u64 addr); | 123 | u64 addr); |
169 | 124 | ||
170 | /* | ||
171 | * Default guest kernel is defined by parameter --guestkallsyms | ||
172 | * and --guestmodules | ||
173 | */ | ||
174 | static inline bool machine__is_default_guest(struct machine *self) | ||
175 | { | ||
176 | return self ? self->pid == DEFAULT_GUEST_KERNEL_ID : false; | ||
177 | } | ||
178 | |||
179 | static inline bool machine__is_host(struct machine *self) | ||
180 | { | ||
181 | return self ? self->pid == HOST_KERNEL_ID : false; | ||
182 | } | ||
183 | |||
184 | static inline void map_groups__insert(struct map_groups *mg, struct map *map) | 125 | static inline void map_groups__insert(struct map_groups *mg, struct map *map) |
185 | { | 126 | { |
186 | maps__insert(&mg->maps[map->type], map); | 127 | maps__insert(&mg->maps[map->type], map); |
@@ -209,29 +150,6 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, | |||
209 | struct map **mapp, | 150 | struct map **mapp, |
210 | symbol_filter_t filter); | 151 | symbol_filter_t filter); |
211 | 152 | ||
212 | |||
213 | struct thread *machine__findnew_thread(struct machine *machine, pid_t pid); | ||
214 | void machine__remove_thread(struct machine *machine, struct thread *th); | ||
215 | |||
216 | size_t machine__fprintf(struct machine *machine, FILE *fp); | ||
217 | |||
218 | static inline | ||
219 | struct symbol *machine__find_kernel_symbol(struct machine *self, | ||
220 | enum map_type type, u64 addr, | ||
221 | struct map **mapp, | ||
222 | symbol_filter_t filter) | ||
223 | { | ||
224 | return map_groups__find_symbol(&self->kmaps, type, addr, mapp, filter); | ||
225 | } | ||
226 | |||
227 | static inline | ||
228 | struct symbol *machine__find_kernel_function(struct machine *self, u64 addr, | ||
229 | struct map **mapp, | ||
230 | symbol_filter_t filter) | ||
231 | { | ||
232 | return machine__find_kernel_symbol(self, MAP__FUNCTION, addr, mapp, filter); | ||
233 | } | ||
234 | |||
235 | static inline | 153 | static inline |
236 | struct symbol *map_groups__find_function_by_name(struct map_groups *mg, | 154 | struct symbol *map_groups__find_function_by_name(struct map_groups *mg, |
237 | const char *name, struct map **mapp, | 155 | const char *name, struct map **mapp, |
@@ -240,22 +158,11 @@ struct symbol *map_groups__find_function_by_name(struct map_groups *mg, | |||
240 | return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter); | 158 | return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter); |
241 | } | 159 | } |
242 | 160 | ||
243 | static inline | ||
244 | struct symbol *machine__find_kernel_function_by_name(struct machine *self, | ||
245 | const char *name, | ||
246 | struct map **mapp, | ||
247 | symbol_filter_t filter) | ||
248 | { | ||
249 | return map_groups__find_function_by_name(&self->kmaps, name, mapp, | ||
250 | filter); | ||
251 | } | ||
252 | |||
253 | int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, | 161 | int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, |
254 | int verbose, FILE *fp); | 162 | int verbose, FILE *fp); |
255 | 163 | ||
256 | struct map *map_groups__find_by_name(struct map_groups *mg, | 164 | struct map *map_groups__find_by_name(struct map_groups *mg, |
257 | enum map_type type, const char *name); | 165 | enum map_type type, const char *name); |
258 | struct map *machine__new_module(struct machine *self, u64 start, const char *filename); | ||
259 | 166 | ||
260 | void map_groups__flush(struct map_groups *mg); | 167 | void map_groups__flush(struct map_groups *mg); |
261 | 168 | ||
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index c87efc12579d..66959fab6634 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l | |||
@@ -81,6 +81,7 @@ num_dec [0-9]+ | |||
81 | num_hex 0x[a-fA-F0-9]+ | 81 | num_hex 0x[a-fA-F0-9]+ |
82 | num_raw_hex [a-fA-F0-9]+ | 82 | num_raw_hex [a-fA-F0-9]+ |
83 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* | 83 | name [a-zA-Z_*?][a-zA-Z0-9_*?]* |
84 | name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* | ||
84 | modifier_event [ukhpGH]{1,8} | 85 | modifier_event [ukhpGH]{1,8} |
85 | modifier_bp [rwx]{1,3} | 86 | modifier_bp [rwx]{1,3} |
86 | 87 | ||
@@ -168,6 +169,7 @@ period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } | |||
168 | branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } | 169 | branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } |
169 | , { return ','; } | 170 | , { return ','; } |
170 | "/" { BEGIN(INITIAL); return '/'; } | 171 | "/" { BEGIN(INITIAL); return '/'; } |
172 | {name_minus} { return str(yyscanner, PE_NAME); } | ||
171 | } | 173 | } |
172 | 174 | ||
173 | mem: { BEGIN(mem); return PE_PREFIX_MEM; } | 175 | mem: { BEGIN(mem); return PE_PREFIX_MEM; } |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index dd6426163ba6..18d1222b05a2 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "hist.h" | 4 | #include "hist.h" |
5 | #include "event.h" | 5 | #include "event.h" |
6 | #include "header.h" | 6 | #include "header.h" |
7 | #include "machine.h" | ||
7 | #include "symbol.h" | 8 | #include "symbol.h" |
8 | #include "thread.h" | 9 | #include "thread.h" |
9 | #include <linux/rbtree.h> | 10 | #include <linux/rbtree.h> |
@@ -68,10 +69,6 @@ int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel | |||
68 | struct ip_callchain *chain, | 69 | struct ip_callchain *chain, |
69 | struct symbol **parent); | 70 | struct symbol **parent); |
70 | 71 | ||
71 | struct branch_info *machine__resolve_bstack(struct machine *self, | ||
72 | struct thread *thread, | ||
73 | struct branch_stack *bs); | ||
74 | |||
75 | bool perf_session__has_traces(struct perf_session *self, const char *msg); | 72 | bool perf_session__has_traces(struct perf_session *self, const char *msg); |
76 | 73 | ||
77 | void mem_bswap_64(void *src, int byte_size); | 74 | void mem_bswap_64(void *src, int byte_size); |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 13761d83a5a0..b4e8c3ba559d 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -77,6 +77,10 @@ struct hist_entry_diff { | |||
77 | struct hist_entry { | 77 | struct hist_entry { |
78 | struct rb_node rb_node_in; | 78 | struct rb_node rb_node_in; |
79 | struct rb_node rb_node; | 79 | struct rb_node rb_node; |
80 | union { | ||
81 | struct list_head node; | ||
82 | struct list_head head; | ||
83 | } pairs; | ||
80 | struct he_stat stat; | 84 | struct he_stat stat; |
81 | struct map_symbol ms; | 85 | struct map_symbol ms; |
82 | struct thread *thread; | 86 | struct thread *thread; |
@@ -96,15 +100,30 @@ struct hist_entry { | |||
96 | char *srcline; | 100 | char *srcline; |
97 | struct symbol *parent; | 101 | struct symbol *parent; |
98 | unsigned long position; | 102 | unsigned long position; |
99 | union { | 103 | struct rb_root sorted_chain; |
100 | struct hist_entry *pair; | ||
101 | struct rb_root sorted_chain; | ||
102 | }; | ||
103 | struct branch_info *branch_info; | 104 | struct branch_info *branch_info; |
104 | struct hists *hists; | 105 | struct hists *hists; |
105 | struct callchain_root callchain[0]; | 106 | struct callchain_root callchain[0]; |
106 | }; | 107 | }; |
107 | 108 | ||
109 | static inline bool hist_entry__has_pairs(struct hist_entry *he) | ||
110 | { | ||
111 | return !list_empty(&he->pairs.node); | ||
112 | } | ||
113 | |||
114 | static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he) | ||
115 | { | ||
116 | if (hist_entry__has_pairs(he)) | ||
117 | return list_entry(he->pairs.node.next, struct hist_entry, pairs.node); | ||
118 | return NULL; | ||
119 | } | ||
120 | |||
121 | static inline void hist__entry_add_pair(struct hist_entry *he, | ||
122 | struct hist_entry *pair) | ||
123 | { | ||
124 | list_add_tail(&he->pairs.head, &pair->pairs.node); | ||
125 | } | ||
126 | |||
108 | enum sort_type { | 127 | enum sort_type { |
109 | SORT_PID, | 128 | SORT_PID, |
110 | SORT_COMM, | 129 | SORT_COMM, |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 624c65e6ab98..295f8d4feedf 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "build-id.h" | 12 | #include "build-id.h" |
13 | #include "util.h" | 13 | #include "util.h" |
14 | #include "debug.h" | 14 | #include "debug.h" |
15 | #include "machine.h" | ||
15 | #include "symbol.h" | 16 | #include "symbol.h" |
16 | #include "strlist.h" | 17 | #include "strlist.h" |
17 | 18 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 863b05bea5ff..04ccf2962080 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -200,16 +200,6 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
200 | symbol_filter_t filter); | 200 | symbol_filter_t filter); |
201 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, | 201 | int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, |
202 | symbol_filter_t filter); | 202 | symbol_filter_t filter); |
203 | int machine__load_kallsyms(struct machine *machine, const char *filename, | ||
204 | enum map_type type, symbol_filter_t filter); | ||
205 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, | ||
206 | symbol_filter_t filter); | ||
207 | |||
208 | size_t machine__fprintf_dsos_buildid(struct machine *machine, | ||
209 | FILE *fp, bool with_hits); | ||
210 | size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); | ||
211 | size_t machines__fprintf_dsos_buildid(struct rb_root *machines, | ||
212 | FILE *fp, bool with_hits); | ||
213 | 203 | ||
214 | struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, | 204 | struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, |
215 | u64 addr); | 205 | u64 addr); |
@@ -224,14 +214,6 @@ int kallsyms__parse(const char *filename, void *arg, | |||
224 | int filename__read_debuglink(const char *filename, char *debuglink, | 214 | int filename__read_debuglink(const char *filename, char *debuglink, |
225 | size_t size); | 215 | size_t size); |
226 | 216 | ||
227 | void machine__destroy_kernel_maps(struct machine *machine); | ||
228 | int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel); | ||
229 | int machine__create_kernel_maps(struct machine *machine); | ||
230 | |||
231 | int machines__create_kernel_maps(struct rb_root *machines, pid_t pid); | ||
232 | int machines__create_guest_kernel_maps(struct rb_root *machines); | ||
233 | void machines__destroy_guest_kernel_maps(struct rb_root *machines); | ||
234 | |||
235 | int symbol__init(void); | 217 | int symbol__init(void); |
236 | void symbol__exit(void); | 218 | void symbol__exit(void); |
237 | void symbol__elf_init(void); | 219 | void symbol__elf_init(void); |
@@ -242,8 +224,6 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); | |||
242 | size_t symbol__fprintf(struct symbol *sym, FILE *fp); | 224 | size_t symbol__fprintf(struct symbol *sym, FILE *fp); |
243 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); | 225 | bool symbol_type__is_a(char symbol_type, enum map_type map_type); |
244 | 226 | ||
245 | size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); | ||
246 | |||
247 | int dso__test_data(void); | 227 | int dso__test_data(void); |
248 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, | 228 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, |
249 | struct symsrc *runtime_ss, symbol_filter_t filter, | 229 | struct symsrc *runtime_ss, symbol_filter_t filter, |