aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds2012-12-11 20:14:31 -0600
committerLinus Torvalds2012-12-11 20:14:31 -0600
commit090f8ccba37034cec5a5972a70abeaae7eb0222b (patch)
tree0b7cf8a4bb94601816399acfb336835fbf309a2a /tools
parentaefb058b0c27dafb15072406fbfd92d2ac2c8790 (diff)
parentcc1b39dbf9f55a438e8a21a694394c20e6a17129 (diff)
downloadkernel-omap-090f8ccba37034cec5a5972a70abeaae7eb0222b.tar.gz
kernel-omap-090f8ccba37034cec5a5972a70abeaae7eb0222b.tar.xz
kernel-omap-090f8ccba37034cec5a5972a70abeaae7eb0222b.zip
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Lots of activity: 211 files changed, 8328 insertions(+), 4116 deletions(-) most of it on the tooling side. Main changes: * ftrace enhancements and fixes from Steve Rostedt. * uprobes fixes, cleanups and preparation for the ARM port from Oleg Nesterov. * UAPI fixes, from David Howels - prepares the arch/x86 UAPI transition * Separate perf tests into multiple objects, one per test, from Jiri Olsa. * Make hardware event translations available in sysfs, from Jiri Olsa. * Fixes to /proc/pid/maps parsing, preparatory to supporting data maps, from Namhyung Kim * Implement ui_progress for GTK, from Namhyung Kim * Add framework for automated perf_event_attr tests, where tools with different command line options will be run from a 'perf test', via python glue, and the perf syscall will be intercepted to verify that the perf_event_attr fields set by the tool are those expected, from Jiri Olsa * Add a 'link' method for hists, so that we can have the leader with buckets for all the entries in all the hists. This new method is now used in the default 'diff' output, making the sum of the 'baseline' column be 100%, eliminating blind spots. * libtraceevent fixes for compiler warnings trying to make perf it build on some distros, like fedora 14, 32-bit, some of the warnings really pointed to real bugs. * Add a browser for 'perf script' and make it available from the report and annotate browsers. It does filtering to find the scripts that handle events found in the perf.data file used. From Feng Tang * perf inject changes to allow showing where a task sleeps, from Andrew Vagin. * Makefile improvements from Namhyung Kim. * Add --pre and --post command hooks in 'stat', from Peter Zijlstra. * Don't stop synthesizing threads when one vanishes, this is for the existing threads when we start a tool like trace. * Use sched:sched_stat_runtime to provide a thread summary, this produces the same output as the 'trace summary' subcommand of tglx's original "trace" tool. * Support interrupted syscalls in 'trace' * Add an event duration column and filter in 'trace'. * There are references to the man pages in some tools, so try to build Documentation when installing, warning the user if that is not possible, from Borislav Petkov. * Give user better message if precise is not supported, from David Ahern. * Try to find cross-built objdump path by using the session environment information in the perf.data file header, from Irina Tirdea, original patch and idea by Namhyung Kim. * Diplays more output on features check for make V=1, so that one can figure out what is happening by looking at gcc output, etc. From Jiri Olsa. * Add on_exit implementation for systems without one, e.g. Android, from Bernhard Rosenkraenzer. * Only process events for vcpus of interest, helps handling large number of events, from David Ahern. * Cross compilation fixes for Android, from Irina Tirdea. * Add documentation on compiling for Android, from Irina Tirdea. * perf diff improvements from Jiri Olsa. * Target (task/user/cpu/syswide) handling improvements, from Namhyung Kim. * Add support in 'trace' for tracing workload given by command line, from Namhyung Kim. * ... and much more." * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (194 commits) uprobes: Use percpu_rw_semaphore to fix register/unregister vs dup_mmap() race perf evsel: Introduce is_group_member method perf powerpc: Use uapi/unistd.h to fix build error tools: Pass the target in descend tools: Honour the O= flag when tool build called from a higher Makefile tools: Define a Makefile function to do subdir processing perf ui: Always compile browser setup code perf ui: Add ui_progress__finish() perf ui gtk: Implement ui_progress functions perf ui: Introduce generic ui_progress helper perf ui tui: Move progress.c under ui/tui directory perf tools: Add basic event modifier sanity check perf tools: Omit group members from perf_evlist__disable/enable perf tools: Ensure single disable call per event in record comand perf tools: Fix 'disabled' attribute config for record command perf tools: Fix attributes for '{}' defined event groups perf tools: Use sscanf for parsing /proc/pid/maps perf tools: Add gtk.<command> config option for launching GTK browser perf tools: Fix compile error on NO_NEWT=1 build perf hists: Initialize all of he->stat with zeroes ...
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/traceevent/Makefile2
-rw-r--r--tools/lib/traceevent/event-parse.c22
-rw-r--r--tools/perf/Documentation/Makefile31
-rw-r--r--tools/perf/Documentation/android.txt78
-rw-r--r--tools/perf/Documentation/perf-diff.txt60
-rw-r--r--tools/perf/Documentation/perf-inject.txt11
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Documentation/perf-trace.txt6
-rw-r--r--tools/perf/Makefile174
-rw-r--r--tools/perf/arch/common.c211
-rw-r--r--tools/perf/arch/common.h10
-rw-r--r--tools/perf/builtin-annotate.c17
-rw-r--r--tools/perf/builtin-buildid-cache.c1
-rw-r--r--tools/perf/builtin-buildid-list.c6
-rw-r--r--tools/perf/builtin-diff.c437
-rw-r--r--tools/perf/builtin-evlist.c5
-rw-r--r--tools/perf/builtin-inject.c195
-rw-r--r--tools/perf/builtin-kmem.c5
-rw-r--r--tools/perf/builtin-kvm.c35
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-record.c66
-rw-r--r--tools/perf/builtin-report.c23
-rw-r--r--tools/perf/builtin-sched.c8
-rw-r--r--tools/perf/builtin-script.c87
-rw-r--r--tools/perf/builtin-stat.c54
-rw-r--r--tools/perf/builtin-test.c1547
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/builtin-top.c17
-rw-r--r--tools/perf/builtin-trace.c403
-rw-r--r--tools/perf/config/feature-tests.mak25
-rw-r--r--tools/perf/config/utilities.mak10
-rw-r--r--tools/perf/perf.c20
-rw-r--r--tools/perf/perf.h18
-rw-r--r--tools/perf/tests/attr.c175
-rw-r--r--tools/perf/tests/attr.py322
-rw-r--r--tools/perf/tests/attr/README64
-rw-r--r--tools/perf/tests/attr/base-record39
-rw-r--r--tools/perf/tests/attr/base-stat39
-rw-r--r--tools/perf/tests/attr/test-record-basic5
-rw-r--r--tools/perf/tests/attr/test-record-branch-any8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_call8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-any_ret8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-hv8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-ind_call8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-k8
-rw-r--r--tools/perf/tests/attr/test-record-branch-filter-u8
-rw-r--r--tools/perf/tests/attr/test-record-count8
-rw-r--r--tools/perf/tests/attr/test-record-data8
-rw-r--r--tools/perf/tests/attr/test-record-freq6
-rw-r--r--tools/perf/tests/attr/test-record-graph-default6
-rw-r--r--tools/perf/tests/attr/test-record-graph-dwarf10
-rw-r--r--tools/perf/tests/attr/test-record-graph-fp6
-rw-r--r--tools/perf/tests/attr/test-record-group18
-rw-r--r--tools/perf/tests/attr/test-record-group119
-rw-r--r--tools/perf/tests/attr/test-record-no-delay9
-rw-r--r--tools/perf/tests/attr/test-record-no-inherit7
-rw-r--r--tools/perf/tests/attr/test-record-no-samples6
-rw-r--r--tools/perf/tests/attr/test-record-period7
-rw-r--r--tools/perf/tests/attr/test-record-raw7
-rw-r--r--tools/perf/tests/attr/test-stat-basic6
-rw-r--r--tools/perf/tests/attr/test-stat-default64
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-1101
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-2155
-rw-r--r--tools/perf/tests/attr/test-stat-detailed-3173
-rw-r--r--tools/perf/tests/attr/test-stat-group15
-rw-r--r--tools/perf/tests/attr/test-stat-group115
-rw-r--r--tools/perf/tests/attr/test-stat-no-inherit7
-rw-r--r--tools/perf/tests/builtin-test.c173
-rw-r--r--tools/perf/tests/dso-data.c (renamed from tools/perf/util/dso-test-data.c)8
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c114
-rw-r--r--tools/perf/tests/evsel-tp-sched.c84
-rw-r--r--tools/perf/tests/mmap-basic.c162
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c120
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c117
-rw-r--r--tools/perf/tests/open-syscall.c66
-rw-r--r--tools/perf/tests/parse-events.c (renamed from tools/perf/util/parse-events-test.c)91
-rw-r--r--tools/perf/tests/perf-record.c312
-rw-r--r--tools/perf/tests/pmu.c178
-rw-r--r--tools/perf/tests/rdpmc.c175
-rw-r--r--tools/perf/tests/tests.h22
-rw-r--r--tools/perf/tests/util.c30
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c230
-rw-r--r--tools/perf/ui/browsers/annotate.c45
-rw-r--r--tools/perf/ui/browsers/hists.c97
-rw-r--r--tools/perf/ui/browsers/scripts.c189
-rw-r--r--tools/perf/ui/gtk/browser.c4
-rw-r--r--tools/perf/ui/gtk/gtk.h1
-rw-r--r--tools/perf/ui/gtk/progress.c59
-rw-r--r--tools/perf/ui/gtk/setup.c2
-rw-r--r--tools/perf/ui/gtk/util.c11
-rw-r--r--tools/perf/ui/hist.c138
-rw-r--r--tools/perf/ui/progress.c44
-rw-r--r--tools/perf/ui/progress.h10
-rw-r--r--tools/perf/ui/stdio/hist.c2
-rw-r--r--tools/perf/ui/tui/progress.c42
-rw-r--r--tools/perf/ui/tui/setup.c1
-rw-r--r--tools/perf/ui/ui.h28
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN14
-rw-r--r--tools/perf/util/annotate.c72
-rw-r--r--tools/perf/util/annotate.h10
-rw-r--r--tools/perf/util/build-id.c27
-rw-r--r--tools/perf/util/build-id.h11
-rw-r--r--tools/perf/util/cache.h39
-rw-r--r--tools/perf/util/debug.h1
-rw-r--r--tools/perf/util/dso.c595
-rw-r--r--tools/perf/util/dso.h148
-rw-r--r--tools/perf/util/event.c302
-rw-r--r--tools/perf/util/event.h9
-rw-r--r--tools/perf/util/evlist.c13
-rw-r--r--tools/perf/util/evsel.c52
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/header.c11
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.c99
-rw-r--r--tools/perf/util/hist.h49
-rw-r--r--tools/perf/util/machine.c464
-rw-r--r--tools/perf/util/machine.h148
-rw-r--r--tools/perf/util/map.c182
-rw-r--r--tools/perf/util/map.h93
-rw-r--r--tools/perf/util/parse-events.c54
-rw-r--r--tools/perf/util/parse-events.h3
-rw-r--r--tools/perf/util/parse-events.l4
-rw-r--r--tools/perf/util/parse-events.y18
-rw-r--r--tools/perf/util/pmu.c192
-rw-r--r--tools/perf/util/pmu.h4
-rw-r--r--tools/perf/util/pstack.c46
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/rblist.c4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c1
-rw-r--r--tools/perf/util/session.c5
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/sort.h45
-rw-r--r--tools/perf/util/string.c18
-rw-r--r--tools/perf/util/symbol.c658
-rw-r--r--tools/perf/util/symbol.h162
-rw-r--r--tools/perf/util/thread.c41
-rw-r--r--tools/perf/util/thread.h2
-rw-r--r--tools/perf/util/trace-event-read.c2
-rw-r--r--tools/perf/util/util.c35
-rw-r--r--tools/perf/util/util.h8
141 files changed, 7570 insertions, 3599 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 04d959fa0226..a20e32033431 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -253,7 +253,7 @@ all_deps := $(all_objs:%.o=.%.d)
253# let .d file also depends on the source and header files 253# let .d file also depends on the source and header files
254define check_deps 254define check_deps
255 @set -e; $(RM) $@; \ 255 @set -e; $(RM) $@; \
256 $(CC) -M $(CFLAGS) $< > $@.$$$$; \ 256 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
257 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ 257 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
258 $(RM) $@.$$$$ 258 $(RM) $@.$$$$
259endef 259endef
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
177static char *find_cmdline(struct pevent *pevent, int pid) 177static 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
3934static void print_event_fields(struct trace_seq *s, void *data, int size, 3934static 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,
4408void pevent_print_event(struct pevent *pevent, struct trace_seq *s, 4409void 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
5073int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 5074int 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/Makefile b/tools/perf/Documentation/Makefile
index 9f2e44f2b17a..ef6d22e879eb 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -1,3 +1,5 @@
1include ../config/utilities.mak
2
1OUTPUT := ./ 3OUTPUT := ./
2ifeq ("$(origin O)", "command line") 4ifeq ("$(origin O)", "command line")
3 ifneq ($(O),) 5 ifneq ($(O),)
@@ -64,6 +66,7 @@ MAKEINFO=makeinfo
64INSTALL_INFO=install-info 66INSTALL_INFO=install-info
65DOCBOOK2X_TEXI=docbook2x-texi 67DOCBOOK2X_TEXI=docbook2x-texi
66DBLATEX=dblatex 68DBLATEX=dblatex
69XMLTO=xmlto
67ifndef PERL_PATH 70ifndef PERL_PATH
68 PERL_PATH = /usr/bin/perl 71 PERL_PATH = /usr/bin/perl
69endif 72endif
@@ -71,6 +74,16 @@ endif
71-include ../config.mak.autogen 74-include ../config.mak.autogen
72-include ../config.mak 75-include ../config.mak
73 76
77_tmp_tool_path := $(call get-executable,$(ASCIIDOC))
78ifeq ($(_tmp_tool_path),)
79 missing_tools = $(ASCIIDOC)
80endif
81
82_tmp_tool_path := $(call get-executable,$(XMLTO))
83ifeq ($(_tmp_tool_path),)
84 missing_tools += $(XMLTO)
85endif
86
74# 87#
75# For asciidoc ... 88# For asciidoc ...
76# -7.1.2, no extra settings are needed. 89# -7.1.2, no extra settings are needed.
@@ -170,7 +183,12 @@ pdf: $(OUTPUT)user-manual.pdf
170 183
171install: install-man 184install: install-man
172 185
173install-man: man 186check-man-tools:
187ifdef missing_tools
188 $(error "You need to install $(missing_tools) for man pages")
189endif
190
191do-install-man: man
174 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir) 192 $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir)
175# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir) 193# $(INSTALL) -d -m 755 $(DESTDIR)$(man5dir)
176# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir) 194# $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir)
@@ -178,6 +196,15 @@ install-man: man
178# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir) 196# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir)
179# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir) 197# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
180 198
199install-man: check-man-tools man
200
201try-install-man:
202ifdef missing_tools
203 $(warning Please install $(missing_tools) to have the man pages installed)
204else
205 $(MAKE) do-install-man
206endif
207
181install-info: info 208install-info: info
182 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) 209 $(INSTALL) -d -m 755 $(DESTDIR)$(infodir)
183 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir) 210 $(INSTALL) -m 644 $(OUTPUT)perf.info $(OUTPUT)perfman.info $(DESTDIR)$(infodir)
@@ -246,7 +273,7 @@ $(MAN_HTML): $(OUTPUT)%.html : %.txt
246 273
247$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml 274$(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
248 $(QUIET_XMLTO)$(RM) $@ && \ 275 $(QUIET_XMLTO)$(RM) $@ && \
249 xmlto -o $(OUTPUT) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< 276 $(XMLTO) -o $(OUTPUT) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
250 277
251$(OUTPUT)%.xml : %.txt 278$(OUTPUT)%.xml : %.txt
252 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \ 279 $(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
new file mode 100644
index 000000000000..8484c3a04a6a
--- /dev/null
+++ b/tools/perf/Documentation/android.txt
@@ -0,0 +1,78 @@
1How to compile perf for Android
2=========================================
3
4I. Set the Android NDK environment
5------------------------------------------------
6
7(a). Use the Android NDK
8------------------------------------------------
91. You need to download and install the Android Native Development Kit (NDK).
10Set the NDK variable to point to the path where you installed the NDK:
11 export NDK=/path/to/android-ndk
12
132. Set cross-compiling environment variables for NDK toolchain and sysroot.
14For arm:
15 export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
16 export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm
17For x86:
18 export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-
19 export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86
20
21This method is not working for Android NDK versions up to Revision 8b.
22perf uses some bionic enhancements that are not included in these NDK versions.
23You can use method (b) described below instead.
24
25(b). Use the Android source tree
26-----------------------------------------------
271. Download the master branch of the Android source tree.
28Set the environment for the target you want using:
29 source build/envsetup.sh
30 lunch
31
322. Build your own NDK sysroot to contain latest bionic changes and set the
33NDK sysroot environment variable.
34 cd ${ANDROID_BUILD_TOP}/ndk
35For arm:
36 ./build/tools/build-ndk-sysroot.sh --abi=arm
37 export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-arm
38For x86:
39 ./build/tools/build-ndk-sysroot.sh --abi=x86
40 export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-x86
41
423. Set the NDK toolchain environment variable.
43For arm:
44 export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/arm-linux-androideabi-
45For x86:
46 export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/i686-linux-android-
47
48II. Compile perf for Android
49------------------------------------------------
50You need to run make with the NDK toolchain and sysroot defined above:
51For arm:
52 make ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
53For x86:
54 make ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
55
56III. Install perf
57-----------------------------------------------
58You need to connect to your Android device/emulator using adb.
59Install perf using:
60 adb push perf /data/perf
61
62If you also want to use perf-archive you need busybox tools for Android.
63For installing perf-archive, you first need to replace #!/bin/bash with #!/system/bin/sh:
64 sed 's/#!\/bin\/bash/#!\/system\/bin\/sh/g' perf-archive >> /tmp/perf-archive
65 chmod +x /tmp/perf-archive
66 adb push /tmp/perf-archive /data/perf-archive
67
68IV. Environment settings for running perf
69------------------------------------------------
70Some perf features need environment variables to run properly.
71You need to set these before running perf on the target:
72 adb shell
73 # PERF_PAGER=cat
74
75IV. Run perf
76------------------------------------------------
77Run perf on your device/emulator to which you previously connected using adb:
78 # ./data/perf
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index ab7f667de1b1..194f37d635df 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -72,6 +72,66 @@ OPTIONS
72--symfs=<directory>:: 72--symfs=<directory>::
73 Look for files with symbols relative to this directory. 73 Look for files with symbols relative to this directory.
74 74
75-b::
76--baseline-only::
77 Show only items with match in baseline.
78
79-c::
80--compute::
81 Differential computation selection - delta,ratio,wdiff (default is delta).
82 If '+' is specified as a first character, the output is sorted based
83 on the computation results.
84 See COMPARISON METHODS section for more info.
85
86-p::
87--period::
88 Show period values for both compared hist entries.
89
90-F::
91--formula::
92 Show formula for given computation.
93
94COMPARISON METHODS
95------------------
96delta
97~~~~~
98If specified the 'Delta' column is displayed with value 'd' computed as:
99
100 d = A->period_percent - B->period_percent
101
102with:
103 - A/B being matching hist entry from first/second file specified
104 (or perf.data/perf.data.old) respectively.
105
106 - period_percent being the % of the hist entry period value within
107 single data file
108
109ratio
110~~~~~
111If specified the 'Ratio' column is displayed with value 'r' computed as:
112
113 r = A->period / B->period
114
115with:
116 - A/B being matching hist entry from first/second file specified
117 (or perf.data/perf.data.old) respectively.
118
119 - period being the hist entry period value
120
121wdiff
122~~~~~
123If specified the 'Weighted diff' column is displayed with value 'd' computed as:
124
125 d = B->period * WEIGHT-A - A->period * WEIGHT-B
126
127 - A/B being matching hist entry from first/second file specified
128 (or perf.data/perf.data.old) respectively.
129
130 - period being the hist entry period value
131
132 - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
133 behind ':' separator like '-c wdiff:1,2'.
134
75SEE ALSO 135SEE ALSO
76-------- 136--------
77linkperf:perf-record[1] 137linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index 025630d43cd2..a00a34276c54 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -29,6 +29,17 @@ OPTIONS
29-v:: 29-v::
30--verbose:: 30--verbose::
31 Be more verbose. 31 Be more verbose.
32-i::
33--input=::
34 Input file name. (default: stdin)
35-o::
36--output=::
37 Output file name. (default: stdout)
38-s::
39--sched-stat::
40 Merge sched_stat and sched_switch for getting events where and how long
41 tasks slept. sched_switch contains a callchain where a task slept and
42 sched_stat contains a timeslice how long a task slept.
32 43
33SEE ALSO 44SEE ALSO
34-------- 45--------
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 2fa173b51970..cf0c3107e06e 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -108,6 +108,11 @@ with it. --append may be used here. Examples:
108 3>results perf stat --log-fd 3 -- $cmd 108 3>results perf stat --log-fd 3 -- $cmd
109 3>>results perf stat --log-fd 3 --append -- $cmd 109 3>>results perf stat --log-fd 3 --append -- $cmd
110 110
111--pre::
112--post::
113 Pre and post measurement hooks, e.g.:
114
115perf stat --repeat 10 --null --sync --pre 'make -s O=defconfig-build/clean' -- make -s -j64 O=defconfig-build/ bzImage
111 116
112 117
113EXAMPLES 118EXAMPLES
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 3a2ae37310a9..68718ccdd178 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -48,6 +48,12 @@ comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-
48In per-thread mode with inheritance mode on (default), Events are captured only when 48In per-thread mode with inheritance mode on (default), Events are captured only when
49the thread executes on the designated CPUs. Default is to monitor all CPUs. 49the thread executes on the designated CPUs. Default is to monitor all CPUs.
50 50
51--duration:
52 Show only events that had a duration greater than N.M ms.
53
54--sched:
55 Accrue thread runtime and provide a summary at the end of the session.
56
51SEE ALSO 57SEE ALSO
52-------- 58--------
53linkperf:perf-record[1], linkperf:perf-script[1] 59linkperf:perf-record[1], linkperf:perf-script[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 0a619af5be43..891bc77bdb2c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
155 155
156-include config/feature-tests.mak 156-include config/feature-tests.mak
157 157
158ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y) 158ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all,-fstack-protector-all),y)
159 CFLAGS := $(CFLAGS) -fstack-protector-all 159 CFLAGS := $(CFLAGS) -fstack-protector-all
160endif 160endif
161 161
162ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y) 162ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector,-Wstack-protector),y)
163 CFLAGS := $(CFLAGS) -Wstack-protector 163 CFLAGS := $(CFLAGS) -Wstack-protector
164endif 164endif
165 165
166ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y) 166ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-Wvolatile-register-var),y)
167 CFLAGS := $(CFLAGS) -Wvolatile-register-var 167 CFLAGS := $(CFLAGS) -Wvolatile-register-var
168endif 168endif
169 169
@@ -197,8 +197,16 @@ BASIC_CFLAGS = \
197 -I. \ 197 -I. \
198 -I$(TRACE_EVENT_DIR) \ 198 -I$(TRACE_EVENT_DIR) \
199 -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 199 -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
200
200BASIC_LDFLAGS = 201BASIC_LDFLAGS =
201 202
203ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y)
204 BIONIC := 1
205 EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
206 EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
207 BASIC_CFLAGS += -I.
208endif
209
202# Guard against environment variables 210# Guard against environment variables
203BUILTIN_OBJS = 211BUILTIN_OBJS =
204LIB_H = 212LIB_H =
@@ -330,6 +338,7 @@ LIB_H += util/evlist.h
330LIB_H += util/exec_cmd.h 338LIB_H += util/exec_cmd.h
331LIB_H += util/types.h 339LIB_H += util/types.h
332LIB_H += util/levenshtein.h 340LIB_H += util/levenshtein.h
341LIB_H += util/machine.h
333LIB_H += util/map.h 342LIB_H += util/map.h
334LIB_H += util/parse-options.h 343LIB_H += util/parse-options.h
335LIB_H += util/parse-events.h 344LIB_H += util/parse-events.h
@@ -346,6 +355,7 @@ LIB_H += util/svghelper.h
346LIB_H += util/tool.h 355LIB_H += util/tool.h
347LIB_H += util/run-command.h 356LIB_H += util/run-command.h
348LIB_H += util/sigchain.h 357LIB_H += util/sigchain.h
358LIB_H += util/dso.h
349LIB_H += util/symbol.h 359LIB_H += util/symbol.h
350LIB_H += util/color.h 360LIB_H += util/color.h
351LIB_H += util/values.h 361LIB_H += util/values.h
@@ -389,7 +399,6 @@ LIB_OBJS += $(OUTPUT)util/help.o
389LIB_OBJS += $(OUTPUT)util/levenshtein.o 399LIB_OBJS += $(OUTPUT)util/levenshtein.o
390LIB_OBJS += $(OUTPUT)util/parse-options.o 400LIB_OBJS += $(OUTPUT)util/parse-options.o
391LIB_OBJS += $(OUTPUT)util/parse-events.o 401LIB_OBJS += $(OUTPUT)util/parse-events.o
392LIB_OBJS += $(OUTPUT)util/parse-events-test.o
393LIB_OBJS += $(OUTPUT)util/path.o 402LIB_OBJS += $(OUTPUT)util/path.o
394LIB_OBJS += $(OUTPUT)util/rbtree.o 403LIB_OBJS += $(OUTPUT)util/rbtree.o
395LIB_OBJS += $(OUTPUT)util/bitmap.o 404LIB_OBJS += $(OUTPUT)util/bitmap.o
@@ -404,15 +413,16 @@ LIB_OBJS += $(OUTPUT)util/top.o
404LIB_OBJS += $(OUTPUT)util/usage.o 413LIB_OBJS += $(OUTPUT)util/usage.o
405LIB_OBJS += $(OUTPUT)util/wrapper.o 414LIB_OBJS += $(OUTPUT)util/wrapper.o
406LIB_OBJS += $(OUTPUT)util/sigchain.o 415LIB_OBJS += $(OUTPUT)util/sigchain.o
416LIB_OBJS += $(OUTPUT)util/dso.o
407LIB_OBJS += $(OUTPUT)util/symbol.o 417LIB_OBJS += $(OUTPUT)util/symbol.o
408LIB_OBJS += $(OUTPUT)util/symbol-elf.o 418LIB_OBJS += $(OUTPUT)util/symbol-elf.o
409LIB_OBJS += $(OUTPUT)util/dso-test-data.o
410LIB_OBJS += $(OUTPUT)util/color.o 419LIB_OBJS += $(OUTPUT)util/color.o
411LIB_OBJS += $(OUTPUT)util/pager.o 420LIB_OBJS += $(OUTPUT)util/pager.o
412LIB_OBJS += $(OUTPUT)util/header.o 421LIB_OBJS += $(OUTPUT)util/header.o
413LIB_OBJS += $(OUTPUT)util/callchain.o 422LIB_OBJS += $(OUTPUT)util/callchain.o
414LIB_OBJS += $(OUTPUT)util/values.o 423LIB_OBJS += $(OUTPUT)util/values.o
415LIB_OBJS += $(OUTPUT)util/debug.o 424LIB_OBJS += $(OUTPUT)util/debug.o
425LIB_OBJS += $(OUTPUT)util/machine.o
416LIB_OBJS += $(OUTPUT)util/map.o 426LIB_OBJS += $(OUTPUT)util/map.o
417LIB_OBJS += $(OUTPUT)util/pstack.o 427LIB_OBJS += $(OUTPUT)util/pstack.o
418LIB_OBJS += $(OUTPUT)util/session.o 428LIB_OBJS += $(OUTPUT)util/session.o
@@ -440,10 +450,29 @@ LIB_OBJS += $(OUTPUT)util/intlist.o
440LIB_OBJS += $(OUTPUT)util/vdso.o 450LIB_OBJS += $(OUTPUT)util/vdso.o
441LIB_OBJS += $(OUTPUT)util/stat.o 451LIB_OBJS += $(OUTPUT)util/stat.o
442 452
453LIB_OBJS += $(OUTPUT)ui/setup.o
443LIB_OBJS += $(OUTPUT)ui/helpline.o 454LIB_OBJS += $(OUTPUT)ui/helpline.o
455LIB_OBJS += $(OUTPUT)ui/progress.o
444LIB_OBJS += $(OUTPUT)ui/hist.o 456LIB_OBJS += $(OUTPUT)ui/hist.o
445LIB_OBJS += $(OUTPUT)ui/stdio/hist.o 457LIB_OBJS += $(OUTPUT)ui/stdio/hist.o
446 458
459LIB_OBJS += $(OUTPUT)arch/common.o
460
461LIB_OBJS += $(OUTPUT)tests/parse-events.o
462LIB_OBJS += $(OUTPUT)tests/dso-data.o
463LIB_OBJS += $(OUTPUT)tests/attr.o
464LIB_OBJS += $(OUTPUT)tests/vmlinux-kallsyms.o
465LIB_OBJS += $(OUTPUT)tests/open-syscall.o
466LIB_OBJS += $(OUTPUT)tests/open-syscall-all-cpus.o
467LIB_OBJS += $(OUTPUT)tests/open-syscall-tp-fields.o
468LIB_OBJS += $(OUTPUT)tests/mmap-basic.o
469LIB_OBJS += $(OUTPUT)tests/perf-record.o
470LIB_OBJS += $(OUTPUT)tests/rdpmc.o
471LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
472LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
473LIB_OBJS += $(OUTPUT)tests/pmu.o
474LIB_OBJS += $(OUTPUT)tests/util.o
475
447BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 476BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
448BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 477BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
449# Benchmark modules 478# Benchmark modules
@@ -473,8 +502,8 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
473BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o 502BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
474BUILTIN_OBJS += $(OUTPUT)builtin-lock.o 503BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
475BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o 504BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
476BUILTIN_OBJS += $(OUTPUT)builtin-test.o
477BUILTIN_OBJS += $(OUTPUT)builtin-inject.o 505BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
506BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
478 507
479PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) 508PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
480 509
@@ -495,18 +524,33 @@ ifdef NO_LIBELF
495 NO_LIBUNWIND := 1 524 NO_LIBUNWIND := 1
496else 525else
497FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) 526FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
498ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y) 527ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF),libelf),y)
499 FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS) 528 FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
500 ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y) 529 ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC),glibc),y)
501 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); 530 LIBC_SUPPORT := 1
502 else 531 endif
532 ifeq ($(BIONIC),1)
533 LIBC_SUPPORT := 1
534 endif
535 ifeq ($(LIBC_SUPPORT),1)
536 msg := $(warning No libelf found, disables 'probe' tool, please install elfutils-libelf-devel/libelf-dev);
537
503 NO_LIBELF := 1 538 NO_LIBELF := 1
504 NO_DWARF := 1 539 NO_DWARF := 1
505 NO_DEMANGLE := 1 540 NO_DEMANGLE := 1
541 else
542 msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
506 endif 543 endif
507else 544else
508 FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS) 545 # for linking with debug library, run like:
509 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF)),y) 546 # make DEBUG=1 LIBDW_DIR=/opt/libdw/
547 ifdef LIBDW_DIR
548 LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
549 LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
550 endif
551
552 FLAGS_DWARF=$(ALL_CFLAGS) $(LIBDW_CFLAGS) -ldw -lelf $(LIBDW_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
553 ifneq ($(call try-cc,$(SOURCE_DWARF),$(FLAGS_DWARF),libdw),y)
510 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); 554 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);
511 NO_DWARF := 1 555 NO_DWARF := 1
512 endif # Dwarf support 556 endif # Dwarf support
@@ -522,7 +566,7 @@ ifdef LIBUNWIND_DIR
522endif 566endif
523 567
524FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS) 568FLAGS_UNWIND=$(LIBUNWIND_CFLAGS) $(ALL_CFLAGS) $(LIBUNWIND_LDFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(LIBUNWIND_LIBS)
525ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND)),y) 569ifneq ($(call try-cc,$(SOURCE_LIBUNWIND),$(FLAGS_UNWIND),libunwind),y)
526 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99); 570 msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 0.99);
527 NO_LIBUNWIND := 1 571 NO_LIBUNWIND := 1
528endif # Libunwind support 572endif # Libunwind support
@@ -551,7 +595,8 @@ LIB_OBJS += $(OUTPUT)util/symbol-minimal.o
551else # NO_LIBELF 595else # NO_LIBELF
552BASIC_CFLAGS += -DLIBELF_SUPPORT 596BASIC_CFLAGS += -DLIBELF_SUPPORT
553 597
554ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_COMMON)),y) 598FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
599ifeq ($(call try-cc,$(SOURCE_ELF_MMAP),$(FLAGS_LIBELF),-DLIBELF_MMAP),y)
555 BASIC_CFLAGS += -DLIBELF_MMAP 600 BASIC_CFLAGS += -DLIBELF_MMAP
556endif 601endif
557 602
@@ -559,7 +604,8 @@ ifndef NO_DWARF
559ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 604ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
560 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 605 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
561else 606else
562 BASIC_CFLAGS += -DDWARF_SUPPORT 607 BASIC_CFLAGS := -DDWARF_SUPPORT $(LIBDW_CFLAGS) $(BASIC_CFLAGS)
608 BASIC_LDFLAGS := $(LIBDW_LDFLAGS) $(BASIC_LDFLAGS)
563 EXTLIBS += -lelf -ldw 609 EXTLIBS += -lelf -ldw
564 LIB_OBJS += $(OUTPUT)util/probe-finder.o 610 LIB_OBJS += $(OUTPUT)util/probe-finder.o
565 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o 611 LIB_OBJS += $(OUTPUT)util/dwarf-aux.o
@@ -577,7 +623,7 @@ endif
577 623
578ifndef NO_LIBAUDIT 624ifndef NO_LIBAUDIT
579 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit 625 FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit
580 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y) 626 ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT),libaudit),y)
581 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev); 627 msg := $(warning No libaudit.h found, disables 'trace' tool, please install audit-libs-devel or libaudit-dev);
582 else 628 else
583 BASIC_CFLAGS += -DLIBAUDIT_SUPPORT 629 BASIC_CFLAGS += -DLIBAUDIT_SUPPORT
@@ -588,23 +634,23 @@ endif
588 634
589ifndef NO_NEWT 635ifndef NO_NEWT
590 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt 636 FLAGS_NEWT=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -lnewt
591 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT)),y) 637 ifneq ($(call try-cc,$(SOURCE_NEWT),$(FLAGS_NEWT),libnewt),y)
592 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev); 638 msg := $(warning newt not found, disables TUI support. Please install newt-devel or libnewt-dev);
593 else 639 else
594 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 640 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
595 BASIC_CFLAGS += -I/usr/include/slang 641 BASIC_CFLAGS += -I/usr/include/slang
596 BASIC_CFLAGS += -DNEWT_SUPPORT 642 BASIC_CFLAGS += -DNEWT_SUPPORT
597 EXTLIBS += -lnewt -lslang 643 EXTLIBS += -lnewt -lslang
598 LIB_OBJS += $(OUTPUT)ui/setup.o
599 LIB_OBJS += $(OUTPUT)ui/browser.o 644 LIB_OBJS += $(OUTPUT)ui/browser.o
600 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o 645 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
601 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o 646 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
602 LIB_OBJS += $(OUTPUT)ui/browsers/map.o 647 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
603 LIB_OBJS += $(OUTPUT)ui/progress.o 648 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
604 LIB_OBJS += $(OUTPUT)ui/util.o 649 LIB_OBJS += $(OUTPUT)ui/util.o
605 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 650 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
606 LIB_OBJS += $(OUTPUT)ui/tui/util.o 651 LIB_OBJS += $(OUTPUT)ui/tui/util.o
607 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o 652 LIB_OBJS += $(OUTPUT)ui/tui/helpline.o
653 LIB_OBJS += $(OUTPUT)ui/tui/progress.o
608 LIB_H += ui/browser.h 654 LIB_H += ui/browser.h
609 LIB_H += ui/browsers/map.h 655 LIB_H += ui/browsers/map.h
610 LIB_H += ui/keysyms.h 656 LIB_H += ui/keysyms.h
@@ -617,10 +663,10 @@ endif
617 663
618ifndef NO_GTK2 664ifndef NO_GTK2
619 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null) 665 FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0 2>/dev/null)
620 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y) 666 ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2),gtk2),y)
621 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev); 667 msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
622 else 668 else
623 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y) 669 ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2),-DHAVE_GTK_INFO_BAR),y)
624 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR 670 BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
625 endif 671 endif
626 BASIC_CFLAGS += -DGTK2_SUPPORT 672 BASIC_CFLAGS += -DGTK2_SUPPORT
@@ -630,9 +676,9 @@ ifndef NO_GTK2
630 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o 676 LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
631 LIB_OBJS += $(OUTPUT)ui/gtk/util.o 677 LIB_OBJS += $(OUTPUT)ui/gtk/util.o
632 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o 678 LIB_OBJS += $(OUTPUT)ui/gtk/helpline.o
679 LIB_OBJS += $(OUTPUT)ui/gtk/progress.o
633 # Make sure that it'd be included only once. 680 # Make sure that it'd be included only once.
634 ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),) 681 ifeq ($(findstring -DNEWT_SUPPORT,$(BASIC_CFLAGS)),)
635 LIB_OBJS += $(OUTPUT)ui/setup.o
636 LIB_OBJS += $(OUTPUT)ui/util.o 682 LIB_OBJS += $(OUTPUT)ui/util.o
637 endif 683 endif
638 endif 684 endif
@@ -647,7 +693,7 @@ else
647 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null` 693 PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
648 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS) 694 FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
649 695
650 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED)),y) 696 ifneq ($(call try-cc,$(SOURCE_PERL_EMBED),$(FLAGS_PERL_EMBED),perl),y)
651 BASIC_CFLAGS += -DNO_LIBPERL 697 BASIC_CFLAGS += -DNO_LIBPERL
652 else 698 else
653 ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS) 699 ALL_LDFLAGS += $(PERL_EMBED_LDFLAGS)
@@ -701,11 +747,11 @@ else
701 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) 747 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
702 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS) 748 FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
703 749
704 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y) 750 ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED),python),y)
705 $(call disable-python,Python.h (for Python 2.x)) 751 $(call disable-python,Python.h (for Python 2.x))
706 else 752 else
707 753
708 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED)),y) 754 ifneq ($(call try-cc,$(SOURCE_PYTHON_VERSION),$(FLAGS_PYTHON_EMBED),python version),y)
709 $(warning Python 3 is not yet supported; please set) 755 $(warning Python 3 is not yet supported; please set)
710 $(warning PYTHON and/or PYTHON_CONFIG appropriately.) 756 $(warning PYTHON and/or PYTHON_CONFIG appropriately.)
711 $(warning If you also have Python 2 installed, then) 757 $(warning If you also have Python 2 installed, then)
@@ -739,22 +785,22 @@ else
739 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE 785 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
740 else 786 else
741 FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd 787 FLAGS_BFD=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -DPACKAGE='perf' -lbfd
742 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD)) 788 has_bfd := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD),libbfd)
743 ifeq ($(has_bfd),y) 789 ifeq ($(has_bfd),y)
744 EXTLIBS += -lbfd 790 EXTLIBS += -lbfd
745 else 791 else
746 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty 792 FLAGS_BFD_IBERTY=$(FLAGS_BFD) -liberty
747 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY)) 793 has_bfd_iberty := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY),liberty)
748 ifeq ($(has_bfd_iberty),y) 794 ifeq ($(has_bfd_iberty),y)
749 EXTLIBS += -lbfd -liberty 795 EXTLIBS += -lbfd -liberty
750 else 796 else
751 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz 797 FLAGS_BFD_IBERTY_Z=$(FLAGS_BFD_IBERTY) -lz
752 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z)) 798 has_bfd_iberty_z := $(call try-cc,$(SOURCE_BFD),$(FLAGS_BFD_IBERTY_Z),libz)
753 ifeq ($(has_bfd_iberty_z),y) 799 ifeq ($(has_bfd_iberty_z),y)
754 EXTLIBS += -lbfd -liberty -lz 800 EXTLIBS += -lbfd -liberty -lz
755 else 801 else
756 FLAGS_CPLUS_DEMANGLE=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -liberty 802 FLAGS_CPLUS_DEMANGLE=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) -liberty
757 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE)) 803 has_cplus_demangle := $(call try-cc,$(SOURCE_CPLUS_DEMANGLE),$(FLAGS_CPLUS_DEMANGLE),demangle)
758 ifeq ($(has_cplus_demangle),y) 804 ifeq ($(has_cplus_demangle),y)
759 EXTLIBS += -liberty 805 EXTLIBS += -liberty
760 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE 806 BASIC_CFLAGS += -DHAVE_CPLUS_DEMANGLE
@@ -776,13 +822,19 @@ ifeq ($(NO_PERF_REGS),0)
776endif 822endif
777 823
778ifndef NO_STRLCPY 824ifndef NO_STRLCPY
779 ifeq ($(call try-cc,$(SOURCE_STRLCPY),),y) 825 ifeq ($(call try-cc,$(SOURCE_STRLCPY),,-DHAVE_STRLCPY),y)
780 BASIC_CFLAGS += -DHAVE_STRLCPY 826 BASIC_CFLAGS += -DHAVE_STRLCPY
781 endif 827 endif
782endif 828endif
783 829
830ifndef NO_ON_EXIT
831 ifeq ($(call try-cc,$(SOURCE_ON_EXIT),,-DHAVE_ON_EXIT),y)
832 BASIC_CFLAGS += -DHAVE_ON_EXIT
833 endif
834endif
835
784ifndef NO_BACKTRACE 836ifndef NO_BACKTRACE
785 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y) 837 ifeq ($(call try-cc,$(SOURCE_BACKTRACE),,-DBACKTRACE_SUPPORT),y)
786 BASIC_CFLAGS += -DBACKTRACE_SUPPORT 838 BASIC_CFLAGS += -DBACKTRACE_SUPPORT
787 endif 839 endif
788endif 840endif
@@ -891,10 +943,14 @@ $(OUTPUT)%.s: %.S
891$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS 943$(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
892 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \ 944 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
893 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \ 945 '-DPERF_EXEC_PATH="$(perfexecdir_SQ)"' \
894 '-DBINDIR="$(bindir_relative_SQ)"' \
895 '-DPREFIX="$(prefix_SQ)"' \ 946 '-DPREFIX="$(prefix_SQ)"' \
896 $< 947 $<
897 948
949$(OUTPUT)tests/attr.o: tests/attr.c $(OUTPUT)PERF-CFLAGS
950 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) \
951 '-DBINDIR="$(bindir_SQ)"' \
952 $<
953
898$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS 954$(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
899 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 955 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
900 956
@@ -910,6 +966,9 @@ $(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
910$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 966$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
911 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 967 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
912 968
969$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
970 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
971
913$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 972$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
914 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 973 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
915 974
@@ -981,20 +1040,15 @@ help:
981 @echo 'Perf maintainer targets:' 1040 @echo 'Perf maintainer targets:'
982 @echo ' clean - clean all binary objects and build output' 1041 @echo ' clean - clean all binary objects and build output'
983 1042
984doc:
985 $(MAKE) -C Documentation all
986
987man:
988 $(MAKE) -C Documentation man
989 1043
990html: 1044DOC_TARGETS := doc man html info pdf
991 $(MAKE) -C Documentation html
992 1045
993info: 1046INSTALL_DOC_TARGETS := $(patsubst %,install-%,$(DOC_TARGETS)) try-install-man
994 $(MAKE) -C Documentation info 1047INSTALL_DOC_TARGETS += quick-install-doc quick-install-man quick-install-html
995 1048
996pdf: 1049# 'make doc' should call 'make -C Documentation all'
997 $(MAKE) -C Documentation pdf 1050$(DOC_TARGETS):
1051 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:doc=all)
998 1052
999TAGS: 1053TAGS:
1000 $(RM) TAGS 1054 $(RM) TAGS
@@ -1045,7 +1099,7 @@ perfexec_instdir = $(prefix)/$(perfexecdir)
1045endif 1099endif
1046perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir)) 1100perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
1047 1101
1048install: all 1102install: all try-install-man
1049 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' 1103 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
1050 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)' 1104 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
1051 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace' 1105 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
@@ -1061,33 +1115,17 @@ install: all
1061 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin' 1115 $(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
1062 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d' 1116 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d'
1063 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf' 1117 $(INSTALL) bash_completion '$(DESTDIR_SQ)$(sysconfdir_SQ)/bash_completion.d/perf'
1118 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
1119 $(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'
1120 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
1121 $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
1064 1122
1065install-python_ext: 1123install-python_ext:
1066 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' 1124 $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
1067 1125
1068install-doc: 1126# 'make install-doc' should call 'make -C Documentation install'
1069 $(MAKE) -C Documentation install 1127$(INSTALL_DOC_TARGETS):
1070 1128 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) $(@:-doc=)
1071install-man:
1072 $(MAKE) -C Documentation install-man
1073
1074install-html:
1075 $(MAKE) -C Documentation install-html
1076
1077install-info:
1078 $(MAKE) -C Documentation install-info
1079
1080install-pdf:
1081 $(MAKE) -C Documentation install-pdf
1082
1083quick-install-doc:
1084 $(MAKE) -C Documentation quick-install
1085
1086quick-install-man:
1087 $(MAKE) -C Documentation quick-install-man
1088
1089quick-install-html:
1090 $(MAKE) -C Documentation quick-install-html
1091 1129
1092### Cleaning rules 1130### Cleaning rules
1093 1131
@@ -1095,7 +1133,7 @@ clean: $(LIBTRACEEVENT)-clean
1095 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) 1133 $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
1096 $(RM) $(ALL_PROGRAMS) perf 1134 $(RM) $(ALL_PROGRAMS) perf
1097 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* 1135 $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
1098 $(MAKE) -C Documentation/ clean 1136 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
1099 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS 1137 $(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
1100 $(RM) $(OUTPUT)util/*-bison* 1138 $(RM) $(OUTPUT)util/*-bison*
1101 $(RM) $(OUTPUT)util/*-flex* 1139 $(RM) $(OUTPUT)util/*-flex*
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
new file mode 100644
index 000000000000..3e975cb6232e
--- /dev/null
+++ b/tools/perf/arch/common.c
@@ -0,0 +1,211 @@
1#include <stdio.h>
2#include <sys/utsname.h>
3#include "common.h"
4#include "../util/debug.h"
5
6const char *const arm_triplets[] = {
7 "arm-eabi-",
8 "arm-linux-androideabi-",
9 "arm-unknown-linux-",
10 "arm-unknown-linux-gnu-",
11 "arm-unknown-linux-gnueabi-",
12 NULL
13};
14
15const char *const powerpc_triplets[] = {
16 "powerpc-unknown-linux-gnu-",
17 "powerpc64-unknown-linux-gnu-",
18 NULL
19};
20
21const char *const s390_triplets[] = {
22 "s390-ibm-linux-",
23 NULL
24};
25
26const char *const sh_triplets[] = {
27 "sh-unknown-linux-gnu-",
28 "sh64-unknown-linux-gnu-",
29 NULL
30};
31
32const char *const sparc_triplets[] = {
33 "sparc-unknown-linux-gnu-",
34 "sparc64-unknown-linux-gnu-",
35 NULL
36};
37
38const char *const x86_triplets[] = {
39 "x86_64-pc-linux-gnu-",
40 "x86_64-unknown-linux-gnu-",
41 "i686-pc-linux-gnu-",
42 "i586-pc-linux-gnu-",
43 "i486-pc-linux-gnu-",
44 "i386-pc-linux-gnu-",
45 "i686-linux-android-",
46 "i686-android-linux-",
47 NULL
48};
49
50const char *const mips_triplets[] = {
51 "mips-unknown-linux-gnu-",
52 "mipsel-linux-android-",
53 NULL
54};
55
56static bool lookup_path(char *name)
57{
58 bool found = false;
59 char *path, *tmp;
60 char buf[PATH_MAX];
61 char *env = getenv("PATH");
62
63 if (!env)
64 return false;
65
66 env = strdup(env);
67 if (!env)
68 return false;
69
70 path = strtok_r(env, ":", &tmp);
71 while (path) {
72 scnprintf(buf, sizeof(buf), "%s/%s", path, name);
73 if (access(buf, F_OK) == 0) {
74 found = true;
75 break;
76 }
77 path = strtok_r(NULL, ":", &tmp);
78 }
79 free(env);
80 return found;
81}
82
83static int lookup_triplets(const char *const *triplets, const char *name)
84{
85 int i;
86 char buf[PATH_MAX];
87
88 for (i = 0; triplets[i] != NULL; i++) {
89 scnprintf(buf, sizeof(buf), "%s%s", triplets[i], name);
90 if (lookup_path(buf))
91 return i;
92 }
93 return -1;
94}
95
96/*
97 * Return architecture name in a normalized form.
98 * The conversion logic comes from the Makefile.
99 */
100static 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
124static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
125 const char *name,
126 const char **path)
127{
128 int idx;
129 const char *arch, *cross_env;
130 struct utsname uts;
131 const char *const *path_list;
132 char *buf = NULL;
133
134 arch = normalize_arch(env->arch);
135
136 if (uname(&uts) < 0)
137 goto out;
138
139 /*
140 * We don't need to try to find objdump path for native system.
141 * Just use default binutils path (e.g.: "objdump").
142 */
143 if (!strcmp(normalize_arch(uts.machine), arch))
144 goto out;
145
146 cross_env = getenv("CROSS_COMPILE");
147 if (cross_env) {
148 if (asprintf(&buf, "%s%s", cross_env, name) < 0)
149 goto out_error;
150 if (buf[0] == '/') {
151 if (access(buf, F_OK) == 0)
152 goto out;
153 goto out_error;
154 }
155 if (lookup_path(buf))
156 goto out;
157 free(buf);
158 }
159
160 if (!strcmp(arch, "arm"))
161 path_list = arm_triplets;
162 else if (!strcmp(arch, "powerpc"))
163 path_list = powerpc_triplets;
164 else if (!strcmp(arch, "sh"))
165 path_list = sh_triplets;
166 else if (!strcmp(arch, "s390"))
167 path_list = s390_triplets;
168 else if (!strcmp(arch, "sparc"))
169 path_list = sparc_triplets;
170 else if (!strcmp(arch, "x86"))
171 path_list = x86_triplets;
172 else if (!strcmp(arch, "mips"))
173 path_list = mips_triplets;
174 else {
175 ui__error("binutils for %s not supported.\n", arch);
176 goto out_error;
177 }
178
179 idx = lookup_triplets(path_list, name);
180 if (idx < 0) {
181 ui__error("Please install %s for %s.\n"
182 "You can add it to PATH, set CROSS_COMPILE or "
183 "override the default using --%s.\n",
184 name, arch, name);
185 goto out_error;
186 }
187
188 if (asprintf(&buf, "%s%s", path_list[idx], name) < 0)
189 goto out_error;
190
191out:
192 *path = buf;
193 return 0;
194out_error:
195 free(buf);
196 *path = NULL;
197 return -1;
198}
199
200int perf_session_env__lookup_objdump(struct perf_session_env *env)
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
209 return perf_session_env__lookup_binutils_path(env, "objdump",
210 &objdump_path);
211}
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
new file mode 100644
index 000000000000..ede246eda9be
--- /dev/null
+++ b/tools/perf/arch/common.h
@@ -0,0 +1,10 @@
1#ifndef ARCH_PERF_COMMON_H
2#define ARCH_PERF_COMMON_H
3
4#include "../util/session.h"
5
6extern const char *objdump_path;
7
8int perf_session_env__lookup_objdump(struct perf_session_env *env);
9
10#endif /* ARCH_PERF_COMMON_H */
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 9ea38540b873..dc870cf31b79 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -28,12 +28,12 @@
28#include "util/hist.h" 28#include "util/hist.h"
29#include "util/session.h" 29#include "util/session.h"
30#include "util/tool.h" 30#include "util/tool.h"
31#include "arch/common.h"
31 32
32#include <linux/bitmap.h> 33#include <linux/bitmap.h>
33 34
34struct perf_annotate { 35struct perf_annotate {
35 struct perf_tool tool; 36 struct perf_tool tool;
36 char const *input_name;
37 bool force, use_tui, use_stdio; 37 bool force, use_tui, use_stdio;
38 bool full_paths; 38 bool full_paths;
39 bool print_line; 39 bool print_line;
@@ -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);
@@ -174,7 +174,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
174 struct perf_evsel *pos; 174 struct perf_evsel *pos;
175 u64 total_nr_samples; 175 u64 total_nr_samples;
176 176
177 session = perf_session__new(ann->input_name, O_RDONLY, 177 session = perf_session__new(input_name, O_RDONLY,
178 ann->force, false, &ann->tool); 178 ann->force, false, &ann->tool);
179 if (session == NULL) 179 if (session == NULL)
180 return -ENOMEM; 180 return -ENOMEM;
@@ -186,6 +186,12 @@ static int __cmd_annotate(struct perf_annotate *ann)
186 goto out_delete; 186 goto out_delete;
187 } 187 }
188 188
189 if (!objdump_path) {
190 ret = perf_session_env__lookup_objdump(&session->header.env);
191 if (ret)
192 goto out_delete;
193 }
194
189 ret = perf_session__process_events(session, &ann->tool); 195 ret = perf_session__process_events(session, &ann->tool);
190 if (ret) 196 if (ret)
191 goto out_delete; 197 goto out_delete;
@@ -246,13 +252,14 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
246 .sample = process_sample_event, 252 .sample = process_sample_event,
247 .mmap = perf_event__process_mmap, 253 .mmap = perf_event__process_mmap,
248 .comm = perf_event__process_comm, 254 .comm = perf_event__process_comm,
249 .fork = perf_event__process_task, 255 .exit = perf_event__process_exit,
256 .fork = perf_event__process_fork,
250 .ordered_samples = true, 257 .ordered_samples = true,
251 .ordering_requires_timestamps = true, 258 .ordering_requires_timestamps = true,
252 }, 259 },
253 }; 260 };
254 const struct option options[] = { 261 const struct option options[] = {
255 OPT_STRING('i', "input", &annotate.input_name, "file", 262 OPT_STRING('i', "input", &input_name, "file",
256 "input file name"), 263 "input file name"),
257 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 264 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
258 "only consider symbols in these dsos"), 265 "only consider symbols in these dsos"),
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index d37e077f4b14..fae8b250b2ca 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -13,6 +13,7 @@
13#include "util/header.h" 13#include "util/header.h"
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/strlist.h" 15#include "util/strlist.h"
16#include "util/build-id.h"
16#include "util/symbol.h" 17#include "util/symbol.h"
17 18
18static int build_id_cache__add_file(const char *filename, const char *debugdir) 19static int build_id_cache__add_file(const char *filename, const char *debugdir)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index a0e94fffa03e..a82d99fec83e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -44,8 +44,7 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
44 return fprintf(fp, "%s\n", sbuild_id); 44 return fprintf(fp, "%s\n", sbuild_id);
45} 45}
46 46
47static int perf_session__list_build_ids(const char *input_name, 47static int perf_session__list_build_ids(bool force, bool with_hits)
48 bool force, bool with_hits)
49{ 48{
50 struct perf_session *session; 49 struct perf_session *session;
51 50
@@ -81,7 +80,6 @@ int cmd_buildid_list(int argc, const char **argv,
81 bool show_kernel = false; 80 bool show_kernel = false;
82 bool with_hits = false; 81 bool with_hits = false;
83 bool force = false; 82 bool force = false;
84 const char *input_name = NULL;
85 const struct option options[] = { 83 const struct option options[] = {
86 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"), 84 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
87 OPT_STRING('i', "input", &input_name, "file", "input file name"), 85 OPT_STRING('i', "input", &input_name, "file", "input file name"),
@@ -101,5 +99,5 @@ int cmd_buildid_list(int argc, const char **argv,
101 if (show_kernel) 99 if (show_kernel)
102 return sysfs__fprintf_build_id(stdout); 100 return sysfs__fprintf_build_id(stdout);
103 101
104 return perf_session__list_build_ids(input_name, force, with_hits); 102 return perf_session__list_build_ids(force, with_hits);
105} 103}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index a0b531c14b97..93b852f8a5d5 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -24,6 +24,228 @@ static char const *input_old = "perf.data.old",
24static char diff__default_sort_order[] = "dso,symbol"; 24static char diff__default_sort_order[] = "dso,symbol";
25static bool force; 25static bool force;
26static bool show_displacement; 26static bool show_displacement;
27static bool show_period;
28static bool show_formula;
29static bool show_baseline_only;
30static bool sort_compute;
31
32static s64 compute_wdiff_w1;
33static s64 compute_wdiff_w2;
34
35enum {
36 COMPUTE_DELTA,
37 COMPUTE_RATIO,
38 COMPUTE_WEIGHTED_DIFF,
39 COMPUTE_MAX,
40};
41
42const char *compute_names[COMPUTE_MAX] = {
43 [COMPUTE_DELTA] = "delta",
44 [COMPUTE_RATIO] = "ratio",
45 [COMPUTE_WEIGHTED_DIFF] = "wdiff",
46};
47
48static int compute;
49
50static int setup_compute_opt_wdiff(char *opt)
51{
52 char *w1_str = opt;
53 char *w2_str;
54
55 int ret = -EINVAL;
56
57 if (!opt)
58 goto out;
59
60 w2_str = strchr(opt, ',');
61 if (!w2_str)
62 goto out;
63
64 *w2_str++ = 0x0;
65 if (!*w2_str)
66 goto out;
67
68 compute_wdiff_w1 = strtol(w1_str, NULL, 10);
69 compute_wdiff_w2 = strtol(w2_str, NULL, 10);
70
71 if (!compute_wdiff_w1 || !compute_wdiff_w2)
72 goto out;
73
74 pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
75 compute_wdiff_w1, compute_wdiff_w2);
76
77 ret = 0;
78
79 out:
80 if (ret)
81 pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
82
83 return ret;
84}
85
86static int setup_compute_opt(char *opt)
87{
88 if (compute == COMPUTE_WEIGHTED_DIFF)
89 return setup_compute_opt_wdiff(opt);
90
91 if (opt) {
92 pr_err("Failed: extra option specified '%s'", opt);
93 return -EINVAL;
94 }
95
96 return 0;
97}
98
99static int setup_compute(const struct option *opt, const char *str,
100 int unset __maybe_unused)
101{
102 int *cp = (int *) opt->value;
103 char *cstr = (char *) str;
104 char buf[50];
105 unsigned i;
106 char *option;
107
108 if (!str) {
109 *cp = COMPUTE_DELTA;
110 return 0;
111 }
112
113 if (*str == '+') {
114 sort_compute = true;
115 cstr = (char *) ++str;
116 if (!*str)
117 return 0;
118 }
119
120 option = strchr(str, ':');
121 if (option) {
122 unsigned len = option++ - str;
123
124 /*
125 * The str data are not writeable, so we need
126 * to use another buffer.
127 */
128
129 /* No option value is longer. */
130 if (len >= sizeof(buf))
131 return -EINVAL;
132
133 strncpy(buf, str, len);
134 buf[len] = 0x0;
135 cstr = buf;
136 }
137
138 for (i = 0; i < COMPUTE_MAX; i++)
139 if (!strcmp(cstr, compute_names[i])) {
140 *cp = i;
141 return setup_compute_opt(option);
142 }
143
144 pr_err("Failed: '%s' is not computation method "
145 "(use 'delta','ratio' or 'wdiff')\n", str);
146 return -EINVAL;
147}
148
149static double get_period_percent(struct hist_entry *he, u64 period)
150{
151 u64 total = he->hists->stats.total_period;
152 return (period * 100.0) / total;
153}
154
155double perf_diff__compute_delta(struct hist_entry *he)
156{
157 struct hist_entry *pair = hist_entry__next_pair(he);
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;
160
161 he->diff.period_ratio_delta = new_percent - old_percent;
162 he->diff.computed = true;
163 return he->diff.period_ratio_delta;
164}
165
166double perf_diff__compute_ratio(struct hist_entry *he)
167{
168 struct hist_entry *pair = hist_entry__next_pair(he);
169 double new_period = he->stat.period;
170 double old_period = pair ? pair->stat.period : 0;
171
172 he->diff.computed = true;
173 he->diff.period_ratio = pair ? (new_period / old_period) : 0;
174 return he->diff.period_ratio;
175}
176
177s64 perf_diff__compute_wdiff(struct hist_entry *he)
178{
179 struct hist_entry *pair = hist_entry__next_pair(he);
180 u64 new_period = he->stat.period;
181 u64 old_period = pair ? pair->stat.period : 0;
182
183 he->diff.computed = true;
184
185 if (!pair)
186 he->diff.wdiff = 0;
187 else
188 he->diff.wdiff = new_period * compute_wdiff_w2 -
189 old_period * compute_wdiff_w1;
190
191 return he->diff.wdiff;
192}
193
194static int formula_delta(struct hist_entry *he, char *buf, size_t size)
195{
196 struct hist_entry *pair = hist_entry__next_pair(he);
197
198 if (!pair)
199 return -1;
200
201 return scnprintf(buf, size,
202 "(%" PRIu64 " * 100 / %" PRIu64 ") - "
203 "(%" PRIu64 " * 100 / %" PRIu64 ")",
204 he->stat.period, he->hists->stats.total_period,
205 pair->stat.period, pair->hists->stats.total_period);
206}
207
208static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
209{
210 struct hist_entry *pair = hist_entry__next_pair(he);
211 double new_period = he->stat.period;
212 double old_period = pair ? pair->stat.period : 0;
213
214 if (!pair)
215 return -1;
216
217 return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
218}
219
220static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
221{
222 struct hist_entry *pair = hist_entry__next_pair(he);
223 u64 new_period = he->stat.period;
224 u64 old_period = pair ? pair->stat.period : 0;
225
226 if (!pair)
227 return -1;
228
229 return scnprintf(buf, size,
230 "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
231 new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
232}
233
234int perf_diff__formula(char *buf, size_t size, struct hist_entry *he)
235{
236 switch (compute) {
237 case COMPUTE_DELTA:
238 return formula_delta(he, buf, size);
239 case COMPUTE_RATIO:
240 return formula_ratio(he, buf, size);
241 case COMPUTE_WEIGHTED_DIFF:
242 return formula_wdiff(he, buf, size);
243 default:
244 BUG_ON(1);
245 }
246
247 return -1;
248}
27 249
28static int hists__add_entry(struct hists *self, 250static int hists__add_entry(struct hists *self,
29 struct addr_location *al, u64 period) 251 struct addr_location *al, u64 period)
@@ -47,7 +269,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
47 return -1; 269 return -1;
48 } 270 }
49 271
50 if (al.filtered || al.sym == NULL) 272 if (al.filtered)
51 return 0; 273 return 0;
52 274
53 if (hists__add_entry(&evsel->hists, &al, sample->period)) { 275 if (hists__add_entry(&evsel->hists, &al, sample->period)) {
@@ -63,8 +285,8 @@ static struct perf_tool tool = {
63 .sample = diff__process_sample_event, 285 .sample = diff__process_sample_event,
64 .mmap = perf_event__process_mmap, 286 .mmap = perf_event__process_mmap,
65 .comm = perf_event__process_comm, 287 .comm = perf_event__process_comm,
66 .exit = perf_event__process_task, 288 .exit = perf_event__process_exit,
67 .fork = perf_event__process_task, 289 .fork = perf_event__process_fork,
68 .lost = perf_event__process_lost, 290 .lost = perf_event__process_lost,
69 .ordered_samples = true, 291 .ordered_samples = true,
70 .ordering_requires_timestamps = true, 292 .ordering_requires_timestamps = true,
@@ -112,36 +334,6 @@ static void hists__name_resort(struct hists *self, bool sort)
112 self->entries = tmp; 334 self->entries = tmp;
113} 335}
114 336
115static struct hist_entry *hists__find_entry(struct hists *self,
116 struct hist_entry *he)
117{
118 struct rb_node *n = self->entries.rb_node;
119
120 while (n) {
121 struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node);
122 int64_t cmp = hist_entry__cmp(he, iter);
123
124 if (cmp < 0)
125 n = n->rb_left;
126 else if (cmp > 0)
127 n = n->rb_right;
128 else
129 return iter;
130 }
131
132 return NULL;
133}
134
135static void hists__match(struct hists *older, struct hists *newer)
136{
137 struct rb_node *nd;
138
139 for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) {
140 struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node);
141 pos->pair = hists__find_entry(older, pos);
142 }
143}
144
145static struct perf_evsel *evsel_match(struct perf_evsel *evsel, 337static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
146 struct perf_evlist *evlist) 338 struct perf_evlist *evlist)
147{ 339{
@@ -172,6 +364,144 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
172 } 364 }
173} 365}
174 366
367static void hists__baseline_only(struct hists *hists)
368{
369 struct rb_node *next = rb_first(&hists->entries);
370
371 while (next != NULL) {
372 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
373
374 next = rb_next(&he->rb_node);
375 if (!hist_entry__next_pair(he)) {
376 rb_erase(&he->rb_node, &hists->entries);
377 hist_entry__free(he);
378 }
379 }
380}
381
382static void hists__precompute(struct hists *hists)
383{
384 struct rb_node *next = rb_first(&hists->entries);
385
386 while (next != NULL) {
387 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
388
389 next = rb_next(&he->rb_node);
390
391 switch (compute) {
392 case COMPUTE_DELTA:
393 perf_diff__compute_delta(he);
394 break;
395 case COMPUTE_RATIO:
396 perf_diff__compute_ratio(he);
397 break;
398 case COMPUTE_WEIGHTED_DIFF:
399 perf_diff__compute_wdiff(he);
400 break;
401 default:
402 BUG_ON(1);
403 }
404 }
405}
406
407static int64_t cmp_doubles(double l, double r)
408{
409 if (l > r)
410 return -1;
411 else if (l < r)
412 return 1;
413 else
414 return 0;
415}
416
417static int64_t
418hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
419 int c)
420{
421 switch (c) {
422 case COMPUTE_DELTA:
423 {
424 double l = left->diff.period_ratio_delta;
425 double r = right->diff.period_ratio_delta;
426
427 return cmp_doubles(l, r);
428 }
429 case COMPUTE_RATIO:
430 {
431 double l = left->diff.period_ratio;
432 double r = right->diff.period_ratio;
433
434 return cmp_doubles(l, r);
435 }
436 case COMPUTE_WEIGHTED_DIFF:
437 {
438 s64 l = left->diff.wdiff;
439 s64 r = right->diff.wdiff;
440
441 return r - l;
442 }
443 default:
444 BUG_ON(1);
445 }
446
447 return 0;
448}
449
450static void insert_hist_entry_by_compute(struct rb_root *root,
451 struct hist_entry *he,
452 int c)
453{
454 struct rb_node **p = &root->rb_node;
455 struct rb_node *parent = NULL;
456 struct hist_entry *iter;
457
458 while (*p != NULL) {
459 parent = *p;
460 iter = rb_entry(parent, struct hist_entry, rb_node);
461 if (hist_entry__cmp_compute(he, iter, c) < 0)
462 p = &(*p)->rb_left;
463 else
464 p = &(*p)->rb_right;
465 }
466
467 rb_link_node(&he->rb_node, parent, p);
468 rb_insert_color(&he->rb_node, root);
469}
470
471static void hists__compute_resort(struct hists *hists)
472{
473 struct rb_root tmp = RB_ROOT;
474 struct rb_node *next = rb_first(&hists->entries);
475
476 while (next != NULL) {
477 struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
478
479 next = rb_next(&he->rb_node);
480
481 rb_erase(&he->rb_node, &hists->entries);
482 insert_hist_entry_by_compute(&tmp, he, compute);
483 }
484
485 hists->entries = tmp;
486}
487
488static void hists__process(struct hists *old, struct hists *new)
489{
490 hists__match(new, old);
491
492 if (show_baseline_only)
493 hists__baseline_only(new);
494 else
495 hists__link(new, old);
496
497 if (sort_compute) {
498 hists__precompute(new);
499 hists__compute_resort(new);
500 }
501
502 hists__fprintf(new, true, 0, 0, stdout);
503}
504
175static int __cmd_diff(void) 505static int __cmd_diff(void)
176{ 506{
177 int ret, i; 507 int ret, i;
@@ -213,8 +543,7 @@ static int __cmd_diff(void)
213 543
214 first = false; 544 first = false;
215 545
216 hists__match(&evsel_old->hists, &evsel->hists); 546 hists__process(&evsel_old->hists, &evsel->hists);
217 hists__fprintf(&evsel->hists, true, 0, 0, stdout);
218 } 547 }
219 548
220out_delete: 549out_delete:
@@ -235,6 +564,16 @@ static const struct option options[] = {
235 "be more verbose (show symbol address, etc)"), 564 "be more verbose (show symbol address, etc)"),
236 OPT_BOOLEAN('M', "displacement", &show_displacement, 565 OPT_BOOLEAN('M', "displacement", &show_displacement,
237 "Show position displacement relative to baseline"), 566 "Show position displacement relative to baseline"),
567 OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
568 "Show only items with match in baseline"),
569 OPT_CALLBACK('c', "compute", &compute,
570 "delta,ratio,wdiff:w1,w2 (default delta)",
571 "Entries differential computation selection",
572 setup_compute),
573 OPT_BOOLEAN('p', "period", &show_period,
574 "Show period values."),
575 OPT_BOOLEAN('F', "formula", &show_formula,
576 "Show formula."),
238 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 577 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
239 "dump raw trace in ASCII"), 578 "dump raw trace in ASCII"),
240 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 579 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -263,12 +602,36 @@ static void ui_init(void)
263 /* No overhead column. */ 602 /* No overhead column. */
264 perf_hpp__column_enable(PERF_HPP__OVERHEAD, false); 603 perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);
265 604
266 /* Display baseline/delta/displacement columns. */ 605 /*
606 * Display baseline/delta/ratio/displacement/
607 * formula/periods columns.
608 */
267 perf_hpp__column_enable(PERF_HPP__BASELINE, true); 609 perf_hpp__column_enable(PERF_HPP__BASELINE, true);
268 perf_hpp__column_enable(PERF_HPP__DELTA, true); 610
611 switch (compute) {
612 case COMPUTE_DELTA:
613 perf_hpp__column_enable(PERF_HPP__DELTA, true);
614 break;
615 case COMPUTE_RATIO:
616 perf_hpp__column_enable(PERF_HPP__RATIO, true);
617 break;
618 case COMPUTE_WEIGHTED_DIFF:
619 perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
620 break;
621 default:
622 BUG_ON(1);
623 };
269 624
270 if (show_displacement) 625 if (show_displacement)
271 perf_hpp__column_enable(PERF_HPP__DISPL, true); 626 perf_hpp__column_enable(PERF_HPP__DISPL, true);
627
628 if (show_formula)
629 perf_hpp__column_enable(PERF_HPP__FORMULA, true);
630
631 if (show_period) {
632 perf_hpp__column_enable(PERF_HPP__PERIOD, true);
633 perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
634 }
272} 635}
273 636
274int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 637int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 997afb82691b..c20f1dcfb7e2 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -48,12 +48,12 @@ static int __if_print(bool *first, const char *field, u64 value)
48 48
49#define if_print(field) __if_print(&first, #field, pos->attr.field) 49#define if_print(field) __if_print(&first, #field, pos->attr.field)
50 50
51static int __cmd_evlist(const char *input_name, struct perf_attr_details *details) 51static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
52{ 52{
53 struct perf_session *session; 53 struct perf_session *session;
54 struct perf_evsel *pos; 54 struct perf_evsel *pos;
55 55
56 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); 56 session = perf_session__new(file_name, O_RDONLY, 0, false, NULL);
57 if (session == NULL) 57 if (session == NULL)
58 return -ENOMEM; 58 return -ENOMEM;
59 59
@@ -111,7 +111,6 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
111int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) 111int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
112{ 112{
113 struct perf_attr_details details = { .verbose = false, }; 113 struct perf_attr_details details = { .verbose = false, };
114 const char *input_name = NULL;
115 const struct option options[] = { 114 const struct option options[] = {
116 OPT_STRING('i', "input", &input_name, "file", "Input file name"), 115 OPT_STRING('i', "input", &input_name, "file", "Input file name"),
117 OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"), 116 OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 4688bea95c12..84ad6abe4258 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -8,33 +8,53 @@
8#include "builtin.h" 8#include "builtin.h"
9 9
10#include "perf.h" 10#include "perf.h"
11#include "util/color.h"
12#include "util/evlist.h"
13#include "util/evsel.h"
11#include "util/session.h" 14#include "util/session.h"
12#include "util/tool.h" 15#include "util/tool.h"
13#include "util/debug.h" 16#include "util/debug.h"
17#include "util/build-id.h"
14 18
15#include "util/parse-options.h" 19#include "util/parse-options.h"
16 20
21#include <linux/list.h>
22
17struct perf_inject { 23struct perf_inject {
18 struct perf_tool tool; 24 struct perf_tool tool;
19 bool build_ids; 25 bool build_ids;
26 bool sched_stat;
27 const char *input_name;
28 int pipe_output,
29 output;
30 u64 bytes_written;
31 struct list_head samples;
32};
33
34struct event_entry {
35 struct list_head node;
36 u32 tid;
37 union perf_event event[0];
20}; 38};
21 39
22static int perf_event__repipe_synth(struct perf_tool *tool __maybe_unused, 40static int perf_event__repipe_synth(struct perf_tool *tool,
23 union perf_event *event, 41 union perf_event *event,
24 struct machine *machine __maybe_unused) 42 struct machine *machine __maybe_unused)
25{ 43{
44 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
26 uint32_t size; 45 uint32_t size;
27 void *buf = event; 46 void *buf = event;
28 47
29 size = event->header.size; 48 size = event->header.size;
30 49
31 while (size) { 50 while (size) {
32 int ret = write(STDOUT_FILENO, buf, size); 51 int ret = write(inject->output, buf, size);
33 if (ret < 0) 52 if (ret < 0)
34 return -errno; 53 return -errno;
35 54
36 size -= ret; 55 size -= ret;
37 buf += ret; 56 buf += ret;
57 inject->bytes_written += ret;
38 } 58 }
39 59
40 return 0; 60 return 0;
@@ -80,12 +100,25 @@ static int perf_event__repipe(struct perf_tool *tool,
80 return perf_event__repipe_synth(tool, event, machine); 100 return perf_event__repipe_synth(tool, event, machine);
81} 101}
82 102
103typedef int (*inject_handler)(struct perf_tool *tool,
104 union perf_event *event,
105 struct perf_sample *sample,
106 struct perf_evsel *evsel,
107 struct machine *machine);
108
83static int perf_event__repipe_sample(struct perf_tool *tool, 109static int perf_event__repipe_sample(struct perf_tool *tool,
84 union perf_event *event, 110 union perf_event *event,
85 struct perf_sample *sample __maybe_unused, 111 struct perf_sample *sample,
86 struct perf_evsel *evsel __maybe_unused, 112 struct perf_evsel *evsel,
87 struct machine *machine) 113 struct machine *machine)
88{ 114{
115 if (evsel->handler.func) {
116 inject_handler f = evsel->handler.func;
117 return f(tool, event, sample, evsel, machine);
118 }
119
120 build_id__mark_dso_hit(tool, event, sample, evsel, machine);
121
89 return perf_event__repipe_synth(tool, event, machine); 122 return perf_event__repipe_synth(tool, event, machine);
90} 123}
91 124
@@ -102,14 +135,14 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
102 return err; 135 return err;
103} 136}
104 137
105static int perf_event__repipe_task(struct perf_tool *tool, 138static int perf_event__repipe_fork(struct perf_tool *tool,
106 union perf_event *event, 139 union perf_event *event,
107 struct perf_sample *sample, 140 struct perf_sample *sample,
108 struct machine *machine) 141 struct machine *machine)
109{ 142{
110 int err; 143 int err;
111 144
112 err = perf_event__process_task(tool, event, sample, machine); 145 err = perf_event__process_fork(tool, event, sample, machine);
113 perf_event__repipe(tool, event, sample, machine); 146 perf_event__repipe(tool, event, sample, machine);
114 147
115 return err; 148 return err;
@@ -210,6 +243,80 @@ repipe:
210 return 0; 243 return 0;
211} 244}
212 245
246static int perf_inject__sched_process_exit(struct perf_tool *tool,
247 union perf_event *event __maybe_unused,
248 struct perf_sample *sample,
249 struct perf_evsel *evsel __maybe_unused,
250 struct machine *machine __maybe_unused)
251{
252 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
253 struct event_entry *ent;
254
255 list_for_each_entry(ent, &inject->samples, node) {
256 if (sample->tid == ent->tid) {
257 list_del_init(&ent->node);
258 free(ent);
259 break;
260 }
261 }
262
263 return 0;
264}
265
266static int perf_inject__sched_switch(struct perf_tool *tool,
267 union perf_event *event,
268 struct perf_sample *sample,
269 struct perf_evsel *evsel,
270 struct machine *machine)
271{
272 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
273 struct event_entry *ent;
274
275 perf_inject__sched_process_exit(tool, event, sample, evsel, machine);
276
277 ent = malloc(event->header.size + sizeof(struct event_entry));
278 if (ent == NULL) {
279 color_fprintf(stderr, PERF_COLOR_RED,
280 "Not enough memory to process sched switch event!");
281 return -1;
282 }
283
284 ent->tid = sample->tid;
285 memcpy(&ent->event, event, event->header.size);
286 list_add(&ent->node, &inject->samples);
287 return 0;
288}
289
290static int perf_inject__sched_stat(struct perf_tool *tool,
291 union perf_event *event __maybe_unused,
292 struct perf_sample *sample,
293 struct perf_evsel *evsel,
294 struct machine *machine)
295{
296 struct event_entry *ent;
297 union perf_event *event_sw;
298 struct perf_sample sample_sw;
299 struct perf_inject *inject = container_of(tool, struct perf_inject, tool);
300 u32 pid = perf_evsel__intval(evsel, sample, "pid");
301
302 list_for_each_entry(ent, &inject->samples, node) {
303 if (pid == ent->tid)
304 goto found;
305 }
306
307 return 0;
308found:
309 event_sw = &ent->event[0];
310 perf_evsel__parse_sample(evsel, event_sw, &sample_sw);
311
312 sample_sw.period = sample->period;
313 sample_sw.time = sample->time;
314 perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
315 &sample_sw, false);
316 build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
317 return perf_event__repipe(tool, event_sw, &sample_sw, machine);
318}
319
213extern volatile int session_done; 320extern volatile int session_done;
214 321
215static void sig_handler(int sig __maybe_unused) 322static void sig_handler(int sig __maybe_unused)
@@ -217,6 +324,21 @@ static void sig_handler(int sig __maybe_unused)
217 session_done = 1; 324 session_done = 1;
218} 325}
219 326
327static int perf_evsel__check_stype(struct perf_evsel *evsel,
328 u64 sample_type, const char *sample_msg)
329{
330 struct perf_event_attr *attr = &evsel->attr;
331 const char *name = perf_evsel__name(evsel);
332
333 if (!(attr->sample_type & sample_type)) {
334 pr_err("Samples for %s event do not have %s attribute set.",
335 name, sample_msg);
336 return -EINVAL;
337 }
338
339 return 0;
340}
341
220static int __cmd_inject(struct perf_inject *inject) 342static int __cmd_inject(struct perf_inject *inject)
221{ 343{
222 struct perf_session *session; 344 struct perf_session *session;
@@ -224,19 +346,48 @@ static int __cmd_inject(struct perf_inject *inject)
224 346
225 signal(SIGINT, sig_handler); 347 signal(SIGINT, sig_handler);
226 348
227 if (inject->build_ids) { 349 if (inject->build_ids || inject->sched_stat) {
228 inject->tool.sample = perf_event__inject_buildid;
229 inject->tool.mmap = perf_event__repipe_mmap; 350 inject->tool.mmap = perf_event__repipe_mmap;
230 inject->tool.fork = perf_event__repipe_task; 351 inject->tool.fork = perf_event__repipe_fork;
231 inject->tool.tracing_data = perf_event__repipe_tracing_data; 352 inject->tool.tracing_data = perf_event__repipe_tracing_data;
232 } 353 }
233 354
234 session = perf_session__new("-", O_RDONLY, false, true, &inject->tool); 355 session = perf_session__new(inject->input_name, O_RDONLY, false, true, &inject->tool);
235 if (session == NULL) 356 if (session == NULL)
236 return -ENOMEM; 357 return -ENOMEM;
237 358
359 if (inject->build_ids) {
360 inject->tool.sample = perf_event__inject_buildid;
361 } else if (inject->sched_stat) {
362 struct perf_evsel *evsel;
363
364 inject->tool.ordered_samples = true;
365
366 list_for_each_entry(evsel, &session->evlist->entries, node) {
367 const char *name = perf_evsel__name(evsel);
368
369 if (!strcmp(name, "sched:sched_switch")) {
370 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
371 return -EINVAL;
372
373 evsel->handler.func = perf_inject__sched_switch;
374 } else if (!strcmp(name, "sched:sched_process_exit"))
375 evsel->handler.func = perf_inject__sched_process_exit;
376 else if (!strncmp(name, "sched:sched_stat_", 17))
377 evsel->handler.func = perf_inject__sched_stat;
378 }
379 }
380
381 if (!inject->pipe_output)
382 lseek(inject->output, session->header.data_offset, SEEK_SET);
383
238 ret = perf_session__process_events(session, &inject->tool); 384 ret = perf_session__process_events(session, &inject->tool);
239 385
386 if (!inject->pipe_output) {
387 session->header.data_size = inject->bytes_written;
388 perf_session__write_header(session, session->evlist, inject->output, true);
389 }
390
240 perf_session__delete(session); 391 perf_session__delete(session);
241 392
242 return ret; 393 return ret;
@@ -260,10 +411,20 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
260 .tracing_data = perf_event__repipe_tracing_data_synth, 411 .tracing_data = perf_event__repipe_tracing_data_synth,
261 .build_id = perf_event__repipe_op2_synth, 412 .build_id = perf_event__repipe_op2_synth,
262 }, 413 },
414 .input_name = "-",
415 .samples = LIST_HEAD_INIT(inject.samples),
263 }; 416 };
417 const char *output_name = "-";
264 const struct option options[] = { 418 const struct option options[] = {
265 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 419 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
266 "Inject build-ids into the output stream"), 420 "Inject build-ids into the output stream"),
421 OPT_STRING('i', "input", &inject.input_name, "file",
422 "input file name"),
423 OPT_STRING('o', "output", &output_name, "file",
424 "output file name"),
425 OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat,
426 "Merge sched-stat and sched-switch for getting events "
427 "where and how long tasks slept"),
267 OPT_INCR('v', "verbose", &verbose, 428 OPT_INCR('v', "verbose", &verbose,
268 "be more verbose (show build ids, etc)"), 429 "be more verbose (show build ids, etc)"),
269 OPT_END() 430 OPT_END()
@@ -281,6 +442,18 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
281 if (argc) 442 if (argc)
282 usage_with_options(inject_usage, options); 443 usage_with_options(inject_usage, options);
283 444
445 if (!strcmp(output_name, "-")) {
446 inject.pipe_output = 1;
447 inject.output = STDOUT_FILENO;
448 } else {
449 inject.output = open(output_name, O_CREAT | O_WRONLY | O_TRUNC,
450 S_IRUSR | S_IWUSR);
451 if (inject.output < 0) {
452 perror("failed to create output file");
453 return -1;
454 }
455 }
456
284 if (symbol__init() < 0) 457 if (symbol__init() < 0)
285 return -1; 458 return -1;
286 459
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 14bf82f63659..0b4b796167be 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -477,7 +477,7 @@ static void sort_result(void)
477 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 477 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
478} 478}
479 479
480static int __cmd_kmem(const char *input_name) 480static int __cmd_kmem(void)
481{ 481{
482 int err = -EINVAL; 482 int err = -EINVAL;
483 struct perf_session *session; 483 struct perf_session *session;
@@ -743,7 +743,6 @@ static int __cmd_record(int argc, const char **argv)
743int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 743int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
744{ 744{
745 const char * const default_sort_order = "frag,hit,bytes"; 745 const char * const default_sort_order = "frag,hit,bytes";
746 const char *input_name = NULL;
747 const struct option kmem_options[] = { 746 const struct option kmem_options[] = {
748 OPT_STRING('i', "input", &input_name, "file", "input file name"), 747 OPT_STRING('i', "input", &input_name, "file", "input file name"),
749 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 748 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
@@ -779,7 +778,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
779 if (list_empty(&alloc_sort)) 778 if (list_empty(&alloc_sort))
780 setup_sorting(&alloc_sort, default_sort_order); 779 setup_sorting(&alloc_sort, default_sort_order);
781 780
782 return __cmd_kmem(input_name); 781 return __cmd_kmem();
783 } else 782 } else
784 usage_with_options(kmem_usage, kmem_options); 783 usage_with_options(kmem_usage, kmem_options);
785 784
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 283b4397e397..ca3f80ebc100 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -314,9 +314,9 @@ struct vcpu_event_record {
314 314
315static void init_kvm_event_record(struct perf_kvm_stat *kvm) 315static void init_kvm_event_record(struct perf_kvm_stat *kvm)
316{ 316{
317 int i; 317 unsigned int i;
318 318
319 for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++) 319 for (i = 0; i < EVENTS_CACHE_SIZE; i++)
320 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]); 320 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
321} 321}
322 322
@@ -370,9 +370,10 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm_stat *kvm,
370 BUG_ON(key->key == INVALID_KEY); 370 BUG_ON(key->key == INVALID_KEY);
371 371
372 head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)]; 372 head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
373 list_for_each_entry(event, head, hash_entry) 373 list_for_each_entry(event, head, hash_entry) {
374 if (event->key.key == key->key && event->key.info == key->info) 374 if (event->key.key == key->key && event->key.info == key->info)
375 return event; 375 return event;
376 }
376 377
377 event = kvm_alloc_init_event(key); 378 event = kvm_alloc_init_event(key);
378 if (!event) 379 if (!event)
@@ -417,7 +418,10 @@ static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
417static bool update_kvm_event(struct kvm_event *event, int vcpu_id, 418static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
418 u64 time_diff) 419 u64 time_diff)
419{ 420{
420 kvm_update_event_stats(&event->total, time_diff); 421 if (vcpu_id == -1) {
422 kvm_update_event_stats(&event->total, time_diff);
423 return true;
424 }
421 425
422 if (!kvm_event_expand(event, vcpu_id)) 426 if (!kvm_event_expand(event, vcpu_id))
423 return false; 427 return false;
@@ -433,6 +437,12 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
433{ 437{
434 struct kvm_event *event; 438 struct kvm_event *event;
435 u64 time_begin, time_diff; 439 u64 time_begin, time_diff;
440 int vcpu;
441
442 if (kvm->trace_vcpu == -1)
443 vcpu = -1;
444 else
445 vcpu = vcpu_record->vcpu_id;
436 446
437 event = vcpu_record->last_event; 447 event = vcpu_record->last_event;
438 time_begin = vcpu_record->start_time; 448 time_begin = vcpu_record->start_time;
@@ -462,7 +472,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
462 BUG_ON(timestamp < time_begin); 472 BUG_ON(timestamp < time_begin);
463 473
464 time_diff = timestamp - time_begin; 474 time_diff = timestamp - time_begin;
465 return update_kvm_event(event, vcpu_record->vcpu_id, time_diff); 475 return update_kvm_event(event, vcpu, time_diff);
466} 476}
467 477
468static 478static
@@ -499,6 +509,11 @@ static bool handle_kvm_event(struct perf_kvm_stat *kvm,
499 if (!vcpu_record) 509 if (!vcpu_record)
500 return true; 510 return true;
501 511
512 /* only process events for vcpus user cares about */
513 if ((kvm->trace_vcpu != -1) &&
514 (kvm->trace_vcpu != vcpu_record->vcpu_id))
515 return true;
516
502 if (kvm->events_ops->is_begin_event(evsel, sample, &key)) 517 if (kvm->events_ops->is_begin_event(evsel, sample, &key))
503 return handle_begin_event(kvm, vcpu_record, &key, sample->time); 518 return handle_begin_event(kvm, vcpu_record, &key, sample->time);
504 519
@@ -598,13 +613,15 @@ static void sort_result(struct perf_kvm_stat *kvm)
598 int vcpu = kvm->trace_vcpu; 613 int vcpu = kvm->trace_vcpu;
599 struct kvm_event *event; 614 struct kvm_event *event;
600 615
601 for (i = 0; i < EVENTS_CACHE_SIZE; i++) 616 for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
602 list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) 617 list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
603 if (event_is_valid(event, vcpu)) { 618 if (event_is_valid(event, vcpu)) {
604 update_total_count(kvm, event); 619 update_total_count(kvm, event);
605 insert_to_result(&kvm->result, event, 620 insert_to_result(&kvm->result, event,
606 kvm->compare, vcpu); 621 kvm->compare, vcpu);
607 } 622 }
623 }
624 }
608} 625}
609 626
610/* returns left most element of result, and erase it */ 627/* returns left most element of result, and erase it */
@@ -661,8 +678,8 @@ static void print_result(struct perf_kvm_stat *kvm)
661 pr_info("\n"); 678 pr_info("\n");
662 } 679 }
663 680
664 pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n", 681 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
665 (unsigned long long)kvm->total_count, kvm->total_time / 1e3); 682 kvm->total_count, kvm->total_time / 1e3);
666} 683}
667 684
668static int process_sample_event(struct perf_tool *tool, 685static int process_sample_event(struct perf_tool *tool,
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6f5f328157aa..425830069749 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -335,8 +335,6 @@ alloc_failed:
335 return NULL; 335 return NULL;
336} 336}
337 337
338static const char *input_name;
339
340struct trace_lock_handler { 338struct trace_lock_handler {
341 int (*acquire_event)(struct perf_evsel *evsel, 339 int (*acquire_event)(struct perf_evsel *evsel,
342 struct perf_sample *sample); 340 struct perf_sample *sample);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e9231659754d..f3151d3c70ce 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,38 @@
31#include <sched.h> 31#include <sched.h>
32#include <sys/mman.h> 32#include <sys/mman.h>
33 33
34#ifndef HAVE_ON_EXIT
35#ifndef ATEXIT_MAX
36#define ATEXIT_MAX 32
37#endif
38static int __on_exit_count = 0;
39typedef void (*on_exit_func_t) (int, void *);
40static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
41static void *__on_exit_args[ATEXIT_MAX];
42static int __exitcode = 0;
43static void __handle_on_exit_funcs(void);
44static int on_exit(on_exit_func_t function, void *arg);
45#define exit(x) (exit)(__exitcode = (x))
46
47static int on_exit(on_exit_func_t function, void *arg)
48{
49 if (__on_exit_count == ATEXIT_MAX)
50 return -ENOMEM;
51 else if (__on_exit_count == 0)
52 atexit(__handle_on_exit_funcs);
53 __on_exit_funcs[__on_exit_count] = function;
54 __on_exit_args[__on_exit_count++] = arg;
55 return 0;
56}
57
58static void __handle_on_exit_funcs(void)
59{
60 int i;
61 for (i = 0; i < __on_exit_count; i++)
62 __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
63}
64#endif
65
34enum write_mode_t { 66enum write_mode_t {
35 WRITE_FORCE, 67 WRITE_FORCE,
36 WRITE_APPEND 68 WRITE_APPEND
@@ -198,11 +230,15 @@ static int perf_record__open(struct perf_record *rec)
198 struct perf_record_opts *opts = &rec->opts; 230 struct perf_record_opts *opts = &rec->opts;
199 int rc = 0; 231 int rc = 0;
200 232
201 perf_evlist__config_attrs(evlist, opts); 233 /*
202 234 * Set the evsel leader links before we configure attributes,
235 * since some might depend on this info.
236 */
203 if (opts->group) 237 if (opts->group)
204 perf_evlist__set_leader(evlist); 238 perf_evlist__set_leader(evlist);
205 239
240 perf_evlist__config_attrs(evlist, opts);
241
206 list_for_each_entry(pos, &evlist->entries, node) { 242 list_for_each_entry(pos, &evlist->entries, node) {
207 struct perf_event_attr *attr = &pos->attr; 243 struct perf_event_attr *attr = &pos->attr;
208 /* 244 /*
@@ -285,6 +321,11 @@ try_again:
285 perf_evsel__name(pos)); 321 perf_evsel__name(pos));
286 rc = -err; 322 rc = -err;
287 goto out; 323 goto out;
324 } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
325 ui__error("\'precise\' request may not be supported. "
326 "Try removing 'p' modifier\n");
327 rc = -err;
328 goto out;
288 } 329 }
289 330
290 printf("\n"); 331 printf("\n");
@@ -326,7 +367,8 @@ try_again:
326 "or try again with a smaller value of -m/--mmap_pages.\n" 367 "or try again with a smaller value of -m/--mmap_pages.\n"
327 "(current value: %d)\n", opts->mmap_pages); 368 "(current value: %d)\n", opts->mmap_pages);
328 rc = -errno; 369 rc = -errno;
329 } else if (!is_power_of_2(opts->mmap_pages)) { 370 } else if (!is_power_of_2(opts->mmap_pages) &&
371 (opts->mmap_pages != UINT_MAX)) {
330 pr_err("--mmap_pages/-m value must be a power of two."); 372 pr_err("--mmap_pages/-m value must be a power of two.");
331 rc = -EINVAL; 373 rc = -EINVAL;
332 } else { 374 } else {
@@ -460,6 +502,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
460 struct perf_evlist *evsel_list = rec->evlist; 502 struct perf_evlist *evsel_list = rec->evlist;
461 const char *output_name = rec->output_name; 503 const char *output_name = rec->output_name;
462 struct perf_session *session; 504 struct perf_session *session;
505 bool disabled = false;
463 506
464 rec->progname = argv[0]; 507 rec->progname = argv[0];
465 508
@@ -659,7 +702,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
659 } 702 }
660 } 703 }
661 704
662 perf_evlist__enable(evsel_list); 705 /*
706 * When perf is starting the traced process, all the events
707 * (apart from group members) have enable_on_exec=1 set,
708 * so don't spoil it by prematurely enabling them.
709 */
710 if (!perf_target__none(&opts->target))
711 perf_evlist__enable(evsel_list);
663 712
664 /* 713 /*
665 * Let the child rip 714 * Let the child rip
@@ -682,8 +731,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
682 waking++; 731 waking++;
683 } 732 }
684 733
685 if (done) 734 /*
735 * When perf is starting the traced process, at the end events
736 * die with the process and we wait for that. Thus no need to
737 * disable events in this case.
738 */
739 if (done && !disabled && !perf_target__none(&opts->target)) {
686 perf_evlist__disable(evsel_list); 740 perf_evlist__disable(evsel_list);
741 disabled = true;
742 }
687 } 743 }
688 744
689 if (quiet || signr == SIGUSR1) 745 if (quiet || signr == SIGUSR1)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a61725d89d3e..fc251005dd3d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -33,13 +33,13 @@
33#include "util/thread.h" 33#include "util/thread.h"
34#include "util/sort.h" 34#include "util/sort.h"
35#include "util/hist.h" 35#include "util/hist.h"
36#include "arch/common.h"
36 37
37#include <linux/bitmap.h> 38#include <linux/bitmap.h>
38 39
39struct perf_report { 40struct perf_report {
40 struct perf_tool tool; 41 struct perf_tool tool;
41 struct perf_session *session; 42 struct perf_session *session;
42 char const *input_name;
43 bool force, use_tui, use_gtk, use_stdio; 43 bool force, use_tui, use_gtk, use_stdio;
44 bool hide_unresolved; 44 bool hide_unresolved;
45 bool dont_use_callchains; 45 bool dont_use_callchains;
@@ -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);
@@ -556,8 +557,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
556 .sample = process_sample_event, 557 .sample = process_sample_event,
557 .mmap = perf_event__process_mmap, 558 .mmap = perf_event__process_mmap,
558 .comm = perf_event__process_comm, 559 .comm = perf_event__process_comm,
559 .exit = perf_event__process_task, 560 .exit = perf_event__process_exit,
560 .fork = perf_event__process_task, 561 .fork = perf_event__process_fork,
561 .lost = perf_event__process_lost, 562 .lost = perf_event__process_lost,
562 .read = process_read_event, 563 .read = process_read_event,
563 .attr = perf_event__process_attr, 564 .attr = perf_event__process_attr,
@@ -570,7 +571,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
570 .pretty_printing_style = "normal", 571 .pretty_printing_style = "normal",
571 }; 572 };
572 const struct option options[] = { 573 const struct option options[] = {
573 OPT_STRING('i', "input", &report.input_name, "file", 574 OPT_STRING('i', "input", &input_name, "file",
574 "input file name"), 575 "input file name"),
575 OPT_INCR('v', "verbose", &verbose, 576 OPT_INCR('v', "verbose", &verbose,
576 "be more verbose (show symbol address, etc)"), 577 "be more verbose (show symbol address, etc)"),
@@ -656,13 +657,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
656 if (report.inverted_callchain) 657 if (report.inverted_callchain)
657 callchain_param.order = ORDER_CALLER; 658 callchain_param.order = ORDER_CALLER;
658 659
659 if (!report.input_name || !strlen(report.input_name)) { 660 if (!input_name || !strlen(input_name)) {
660 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 661 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
661 report.input_name = "-"; 662 input_name = "-";
662 else 663 else
663 report.input_name = "perf.data"; 664 input_name = "perf.data";
664 } 665 }
665 session = perf_session__new(report.input_name, O_RDONLY, 666 session = perf_session__new(input_name, O_RDONLY,
666 report.force, false, &report.tool); 667 report.force, false, &report.tool);
667 if (session == NULL) 668 if (session == NULL)
668 return -ENOMEM; 669 return -ENOMEM;
@@ -687,7 +688,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
687 688
688 } 689 }
689 690
690 if (strcmp(report.input_name, "-") != 0) 691 if (strcmp(input_name, "-") != 0)
691 setup_browser(true); 692 setup_browser(true);
692 else { 693 else {
693 use_browser = 0; 694 use_browser = 0;
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 3488ead3b60c..cc28b85dabd5 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -120,7 +120,6 @@ struct trace_sched_handler {
120 120
121struct perf_sched { 121struct perf_sched {
122 struct perf_tool tool; 122 struct perf_tool tool;
123 const char *input_name;
124 const char *sort_order; 123 const char *sort_order;
125 unsigned long nr_tasks; 124 unsigned long nr_tasks;
126 struct task_desc *pid_to_task[MAX_PID]; 125 struct task_desc *pid_to_task[MAX_PID];
@@ -1460,7 +1459,7 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
1460 }; 1459 };
1461 struct perf_session *session; 1460 struct perf_session *session;
1462 1461
1463 session = perf_session__new(sched->input_name, O_RDONLY, 0, false, &sched->tool); 1462 session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool);
1464 if (session == NULL) { 1463 if (session == NULL) {
1465 pr_debug("No Memory for session\n"); 1464 pr_debug("No Memory for session\n");
1466 return -1; 1465 return -1;
@@ -1672,7 +1671,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1672 .sample = perf_sched__process_tracepoint_sample, 1671 .sample = perf_sched__process_tracepoint_sample,
1673 .comm = perf_event__process_comm, 1672 .comm = perf_event__process_comm,
1674 .lost = perf_event__process_lost, 1673 .lost = perf_event__process_lost,
1675 .fork = perf_event__process_task, 1674 .exit = perf_event__process_exit,
1675 .fork = perf_event__process_fork,
1676 .ordered_samples = true, 1676 .ordered_samples = true,
1677 }, 1677 },
1678 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1678 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
@@ -1707,7 +1707,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1707 OPT_END() 1707 OPT_END()
1708 }; 1708 };
1709 const struct option sched_options[] = { 1709 const struct option sched_options[] = {
1710 OPT_STRING('i', "input", &sched.input_name, "file", 1710 OPT_STRING('i', "input", &input_name, "file",
1711 "input file name"), 1711 "input file name"),
1712 OPT_INCR('v', "verbose", &verbose, 1712 OPT_INCR('v', "verbose", &verbose,
1713 "be more verbose (show symbol address, etc)"), 1713 "be more verbose (show symbol address, etc)"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index fb9625083a2e..b363e7b292b2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -520,8 +520,8 @@ static struct perf_tool perf_script = {
520 .sample = process_sample_event, 520 .sample = process_sample_event,
521 .mmap = perf_event__process_mmap, 521 .mmap = perf_event__process_mmap,
522 .comm = perf_event__process_comm, 522 .comm = perf_event__process_comm,
523 .exit = perf_event__process_task, 523 .exit = perf_event__process_exit,
524 .fork = perf_event__process_task, 524 .fork = perf_event__process_fork,
525 .attr = perf_event__process_attr, 525 .attr = perf_event__process_attr,
526 .event_type = perf_event__process_event_type, 526 .event_type = perf_event__process_event_type,
527 .tracing_data = perf_event__process_tracing_data, 527 .tracing_data = perf_event__process_tracing_data,
@@ -1030,6 +1030,68 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1030} 1030}
1031 1031
1032/* 1032/*
1033 * Some scripts specify the required events in their "xxx-record" file,
1034 * this function will check if the events in perf.data match those
1035 * mentioned in the "xxx-record".
1036 *
1037 * Fixme: All existing "xxx-record" are all in good formats "-e event ",
1038 * which is covered well now. And new parsing code should be added to
1039 * cover the future complexing formats like event groups etc.
1040 */
1041static int check_ev_match(char *dir_name, char *scriptname,
1042 struct perf_session *session)
1043{
1044 char filename[MAXPATHLEN], evname[128];
1045 char line[BUFSIZ], *p;
1046 struct perf_evsel *pos;
1047 int match, len;
1048 FILE *fp;
1049
1050 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname);
1051
1052 fp = fopen(filename, "r");
1053 if (!fp)
1054 return -1;
1055
1056 while (fgets(line, sizeof(line), fp)) {
1057 p = ltrim(line);
1058 if (*p == '#')
1059 continue;
1060
1061 while (strlen(p)) {
1062 p = strstr(p, "-e");
1063 if (!p)
1064 break;
1065
1066 p += 2;
1067 p = ltrim(p);
1068 len = strcspn(p, " \t");
1069 if (!len)
1070 break;
1071
1072 snprintf(evname, len + 1, "%s", p);
1073
1074 match = 0;
1075 list_for_each_entry(pos,
1076 &session->evlist->entries, node) {
1077 if (!strcmp(perf_evsel__name(pos), evname)) {
1078 match = 1;
1079 break;
1080 }
1081 }
1082
1083 if (!match) {
1084 fclose(fp);
1085 return -1;
1086 }
1087 }
1088 }
1089
1090 fclose(fp);
1091 return 0;
1092}
1093
1094/*
1033 * Return -1 if none is found, otherwise the actual scripts number. 1095 * Return -1 if none is found, otherwise the actual scripts number.
1034 * 1096 *
1035 * Currently the only user of this function is the script browser, which 1097 * Currently the only user of this function is the script browser, which
@@ -1039,17 +1101,23 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1039int find_scripts(char **scripts_array, char **scripts_path_array) 1101int find_scripts(char **scripts_array, char **scripts_path_array)
1040{ 1102{
1041 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1103 struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
1042 char scripts_path[MAXPATHLEN]; 1104 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
1043 DIR *scripts_dir, *lang_dir; 1105 DIR *scripts_dir, *lang_dir;
1044 char lang_path[MAXPATHLEN]; 1106 struct perf_session *session;
1045 char *temp; 1107 char *temp;
1046 int i = 0; 1108 int i = 0;
1047 1109
1110 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL);
1111 if (!session)
1112 return -1;
1113
1048 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1114 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
1049 1115
1050 scripts_dir = opendir(scripts_path); 1116 scripts_dir = opendir(scripts_path);
1051 if (!scripts_dir) 1117 if (!scripts_dir) {
1118 perf_session__delete(session);
1052 return -1; 1119 return -1;
1120 }
1053 1121
1054 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1122 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
1055 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 1123 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
@@ -1077,10 +1145,18 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1077 snprintf(scripts_array[i], 1145 snprintf(scripts_array[i],
1078 (temp - script_dirent.d_name) + 1, 1146 (temp - script_dirent.d_name) + 1,
1079 "%s", script_dirent.d_name); 1147 "%s", script_dirent.d_name);
1148
1149 if (check_ev_match(lang_path,
1150 scripts_array[i], session))
1151 continue;
1152
1080 i++; 1153 i++;
1081 } 1154 }
1155 closedir(lang_dir);
1082 } 1156 }
1083 1157
1158 closedir(scripts_dir);
1159 perf_session__delete(session);
1084 return i; 1160 return i;
1085} 1161}
1086 1162
@@ -1175,7 +1251,6 @@ static int have_cmd(int argc, const char **argv)
1175int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 1251int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1176{ 1252{
1177 bool show_full_info = false; 1253 bool show_full_info = false;
1178 const char *input_name = NULL;
1179 char *rec_script_path = NULL; 1254 char *rec_script_path = NULL;
1180 char *rep_script_path = NULL; 1255 char *rep_script_path = NULL;
1181 struct perf_session *session; 1256 struct perf_session *session;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 93b9011fa3e2..c247faca7127 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -57,6 +57,7 @@
57#include "util/thread.h" 57#include "util/thread.h"
58#include "util/thread_map.h" 58#include "util/thread_map.h"
59 59
60#include <stdlib.h>
60#include <sys/prctl.h> 61#include <sys/prctl.h>
61#include <locale.h> 62#include <locale.h>
62 63
@@ -83,6 +84,9 @@ static const char *csv_sep = NULL;
83static bool csv_output = false; 84static bool csv_output = false;
84static bool group = false; 85static bool group = false;
85static FILE *output = NULL; 86static FILE *output = NULL;
87static const char *pre_cmd = NULL;
88static const char *post_cmd = NULL;
89static bool sync_run = false;
86 90
87static volatile int done = 0; 91static volatile int done = 0;
88 92
@@ -125,8 +129,7 @@ static struct stats runtime_itlb_cache_stats[MAX_NR_CPUS];
125static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS]; 129static struct stats runtime_dtlb_cache_stats[MAX_NR_CPUS];
126static struct stats walltime_nsecs_stats; 130static struct stats walltime_nsecs_stats;
127 131
128static int create_perf_stat_counter(struct perf_evsel *evsel, 132static int create_perf_stat_counter(struct perf_evsel *evsel)
129 struct perf_evsel *first)
130{ 133{
131 struct perf_event_attr *attr = &evsel->attr; 134 struct perf_event_attr *attr = &evsel->attr;
132 bool exclude_guest_missing = false; 135 bool exclude_guest_missing = false;
@@ -149,7 +152,8 @@ retry:
149 return 0; 152 return 0;
150 } 153 }
151 154
152 if (!perf_target__has_task(&target) && (!group || evsel == first)) { 155 if (!perf_target__has_task(&target) &&
156 !perf_evsel__is_group_member(evsel)) {
153 attr->disabled = 1; 157 attr->disabled = 1;
154 attr->enable_on_exec = 1; 158 attr->enable_on_exec = 1;
155 } 159 }
@@ -265,10 +269,10 @@ static int read_counter(struct perf_evsel *counter)
265 return 0; 269 return 0;
266} 270}
267 271
268static int run_perf_stat(int argc __maybe_unused, const char **argv) 272static int __run_perf_stat(int argc __maybe_unused, const char **argv)
269{ 273{
270 unsigned long long t0, t1; 274 unsigned long long t0, t1;
271 struct perf_evsel *counter, *first; 275 struct perf_evsel *counter;
272 int status = 0; 276 int status = 0;
273 int child_ready_pipe[2], go_pipe[2]; 277 int child_ready_pipe[2], go_pipe[2];
274 const bool forks = (argc > 0); 278 const bool forks = (argc > 0);
@@ -328,10 +332,8 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
328 if (group) 332 if (group)
329 perf_evlist__set_leader(evsel_list); 333 perf_evlist__set_leader(evsel_list);
330 334
331 first = perf_evlist__first(evsel_list);
332
333 list_for_each_entry(counter, &evsel_list->entries, node) { 335 list_for_each_entry(counter, &evsel_list->entries, node) {
334 if (create_perf_stat_counter(counter, first) < 0) { 336 if (create_perf_stat_counter(counter) < 0) {
335 /* 337 /*
336 * PPC returns ENXIO for HW counters until 2.6.37 338 * PPC returns ENXIO for HW counters until 2.6.37
337 * (behavior changed with commit b0a873e). 339 * (behavior changed with commit b0a873e).
@@ -405,6 +407,32 @@ static int run_perf_stat(int argc __maybe_unused, const char **argv)
405 return WEXITSTATUS(status); 407 return WEXITSTATUS(status);
406} 408}
407 409
410static int run_perf_stat(int argc __maybe_unused, const char **argv)
411{
412 int ret;
413
414 if (pre_cmd) {
415 ret = system(pre_cmd);
416 if (ret)
417 return ret;
418 }
419
420 if (sync_run)
421 sync();
422
423 ret = __run_perf_stat(argc, argv);
424 if (ret)
425 return ret;
426
427 if (post_cmd) {
428 ret = system(post_cmd);
429 if (ret)
430 return ret;
431 }
432
433 return ret;
434}
435
408static void print_noise_pct(double total, double avg) 436static void print_noise_pct(double total, double avg)
409{ 437{
410 double pct = rel_stddev_stats(total, avg); 438 double pct = rel_stddev_stats(total, avg);
@@ -1069,8 +1097,7 @@ static int add_default_attributes(void)
1069 1097
1070int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused) 1098int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1071{ 1099{
1072 bool append_file = false, 1100 bool append_file = false;
1073 sync_run = false;
1074 int output_fd = 0; 1101 int output_fd = 0;
1075 const char *output_name = NULL; 1102 const char *output_name = NULL;
1076 const struct option options[] = { 1103 const struct option options[] = {
@@ -1114,6 +1141,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1114 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"), 1141 OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
1115 OPT_INTEGER(0, "log-fd", &output_fd, 1142 OPT_INTEGER(0, "log-fd", &output_fd,
1116 "log output to fd, instead of stderr"), 1143 "log output to fd, instead of stderr"),
1144 OPT_STRING(0, "pre", &pre_cmd, "command",
1145 "command to run prior to the measured command"),
1146 OPT_STRING(0, "post", &post_cmd, "command",
1147 "command to run after to the measured command"),
1117 OPT_END() 1148 OPT_END()
1118 }; 1149 };
1119 const char * const stat_usage[] = { 1150 const char * const stat_usage[] = {
@@ -1238,9 +1269,6 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1238 fprintf(output, "[ perf stat: executing run #%d ... ]\n", 1269 fprintf(output, "[ perf stat: executing run #%d ... ]\n",
1239 run_idx + 1); 1270 run_idx + 1);
1240 1271
1241 if (sync_run)
1242 sync();
1243
1244 status = run_perf_stat(argc, argv); 1272 status = run_perf_stat(argc, argv);
1245 } 1273 }
1246 1274
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
deleted file mode 100644
index 5acd6e8e658b..000000000000
--- a/tools/perf/builtin-test.c
+++ /dev/null
@@ -1,1547 +0,0 @@
1/*
2 * builtin-test.c
3 *
4 * Builtin regression testing command: ever growing number of sanity tests
5 */
6#include "builtin.h"
7
8#include "util/cache.h"
9#include "util/debug.h"
10#include "util/debugfs.h"
11#include "util/evlist.h"
12#include "util/parse-options.h"
13#include "util/parse-events.h"
14#include "util/symbol.h"
15#include "util/thread_map.h"
16#include "util/pmu.h"
17#include "event-parse.h"
18#include <linux/hw_breakpoint.h>
19
20#include <sys/mman.h>
21
22static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
23 struct symbol *sym)
24{
25 bool *visited = symbol__priv(sym);
26 *visited = true;
27 return 0;
28}
29
30static int test__vmlinux_matches_kallsyms(void)
31{
32 int err = -1;
33 struct rb_node *nd;
34 struct symbol *sym;
35 struct map *kallsyms_map, *vmlinux_map;
36 struct machine kallsyms, vmlinux;
37 enum map_type type = MAP__FUNCTION;
38 long page_size = sysconf(_SC_PAGE_SIZE);
39 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
40
41 /*
42 * Step 1:
43 *
44 * Init the machines that will hold kernel, modules obtained from
45 * both vmlinux + .ko files and from /proc/kallsyms split by modules.
46 */
47 machine__init(&kallsyms, "", HOST_KERNEL_ID);
48 machine__init(&vmlinux, "", HOST_KERNEL_ID);
49
50 /*
51 * Step 2:
52 *
53 * Create the kernel maps for kallsyms and the DSO where we will then
54 * load /proc/kallsyms. Also create the modules maps from /proc/modules
55 * and find the .ko files that match them in /lib/modules/`uname -r`/.
56 */
57 if (machine__create_kernel_maps(&kallsyms) < 0) {
58 pr_debug("machine__create_kernel_maps ");
59 return -1;
60 }
61
62 /*
63 * Step 3:
64 *
65 * Load and split /proc/kallsyms into multiple maps, one per module.
66 */
67 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {
68 pr_debug("dso__load_kallsyms ");
69 goto out;
70 }
71
72 /*
73 * Step 4:
74 *
75 * kallsyms will be internally on demand sorted by name so that we can
76 * find the reference relocation * symbol, i.e. the symbol we will use
77 * to see if the running kernel was relocated by checking if it has the
78 * same value in the vmlinux file we load.
79 */
80 kallsyms_map = machine__kernel_map(&kallsyms, type);
81
82 sym = map__find_symbol_by_name(kallsyms_map, ref_reloc_sym.name, NULL);
83 if (sym == NULL) {
84 pr_debug("dso__find_symbol_by_name ");
85 goto out;
86 }
87
88 ref_reloc_sym.addr = sym->start;
89
90 /*
91 * Step 5:
92 *
93 * Now repeat step 2, this time for the vmlinux file we'll auto-locate.
94 */
95 if (machine__create_kernel_maps(&vmlinux) < 0) {
96 pr_debug("machine__create_kernel_maps ");
97 goto out;
98 }
99
100 vmlinux_map = machine__kernel_map(&vmlinux, type);
101 map__kmap(vmlinux_map)->ref_reloc_sym = &ref_reloc_sym;
102
103 /*
104 * Step 6:
105 *
106 * Locate a vmlinux file in the vmlinux path that has a buildid that
107 * matches the one of the running kernel.
108 *
109 * While doing that look if we find the ref reloc symbol, if we find it
110 * we'll have its ref_reloc_symbol.unrelocated_addr and then
111 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
112 * to fixup the symbols.
113 */
114 if (machine__load_vmlinux_path(&vmlinux, type,
115 vmlinux_matches_kallsyms_filter) <= 0) {
116 pr_debug("machine__load_vmlinux_path ");
117 goto out;
118 }
119
120 err = 0;
121 /*
122 * Step 7:
123 *
124 * Now look at the symbols in the vmlinux DSO and check if we find all of them
125 * in the kallsyms dso. For the ones that are in both, check its names and
126 * end addresses too.
127 */
128 for (nd = rb_first(&vmlinux_map->dso->symbols[type]); nd; nd = rb_next(nd)) {
129 struct symbol *pair, *first_pair;
130 bool backwards = true;
131
132 sym = rb_entry(nd, struct symbol, rb_node);
133
134 if (sym->start == sym->end)
135 continue;
136
137 first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL);
138 pair = first_pair;
139
140 if (pair && pair->start == sym->start) {
141next_pair:
142 if (strcmp(sym->name, pair->name) == 0) {
143 /*
144 * kallsyms don't have the symbol end, so we
145 * set that by using the next symbol start - 1,
146 * in some cases we get this up to a page
147 * wrong, trace_kmalloc when I was developing
148 * this code was one such example, 2106 bytes
149 * off the real size. More than that and we
150 * _really_ have a problem.
151 */
152 s64 skew = sym->end - pair->end;
153 if (llabs(skew) < page_size)
154 continue;
155
156 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
157 sym->start, sym->name, sym->end, pair->end);
158 } else {
159 struct rb_node *nnd;
160detour:
161 nnd = backwards ? rb_prev(&pair->rb_node) :
162 rb_next(&pair->rb_node);
163 if (nnd) {
164 struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
165
166 if (next->start == sym->start) {
167 pair = next;
168 goto next_pair;
169 }
170 }
171
172 if (backwards) {
173 backwards = false;
174 pair = first_pair;
175 goto detour;
176 }
177
178 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
179 sym->start, sym->name, pair->name);
180 }
181 } else
182 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name);
183
184 err = -1;
185 }
186
187 if (!verbose)
188 goto out;
189
190 pr_info("Maps only in vmlinux:\n");
191
192 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
193 struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
194 /*
195 * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while
196 * the kernel will have the path for the vmlinux file being used,
197 * so use the short name, less descriptive but the same ("[kernel]" in
198 * both cases.
199 */
200 pair = map_groups__find_by_name(&kallsyms.kmaps, type,
201 (pos->dso->kernel ?
202 pos->dso->short_name :
203 pos->dso->name));
204 if (pair)
205 pair->priv = 1;
206 else
207 map__fprintf(pos, stderr);
208 }
209
210 pr_info("Maps in vmlinux with a different name in kallsyms:\n");
211
212 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
213 struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
214
215 pair = map_groups__find(&kallsyms.kmaps, type, pos->start);
216 if (pair == NULL || pair->priv)
217 continue;
218
219 if (pair->start == pos->start) {
220 pair->priv = 1;
221 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
222 pos->start, pos->end, pos->pgoff, pos->dso->name);
223 if (pos->pgoff != pair->pgoff || pos->end != pair->end)
224 pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "",
225 pair->start, pair->end, pair->pgoff);
226 pr_info(" %s\n", pair->dso->name);
227 pair->priv = 1;
228 }
229 }
230
231 pr_info("Maps only in kallsyms:\n");
232
233 for (nd = rb_first(&kallsyms.kmaps.maps[type]);
234 nd; nd = rb_next(nd)) {
235 struct map *pos = rb_entry(nd, struct map, rb_node);
236
237 if (!pos->priv)
238 map__fprintf(pos, stderr);
239 }
240out:
241 return err;
242}
243
244#include "util/cpumap.h"
245#include "util/evsel.h"
246#include <sys/types.h>
247
248static int trace_event__id(const char *evname)
249{
250 char *filename;
251 int err = -1, fd;
252
253 if (asprintf(&filename,
254 "%s/syscalls/%s/id",
255 tracing_events_path, evname) < 0)
256 return -1;
257
258 fd = open(filename, O_RDONLY);
259 if (fd >= 0) {
260 char id[16];
261 if (read(fd, id, sizeof(id)) > 0)
262 err = atoi(id);
263 close(fd);
264 }
265
266 free(filename);
267 return err;
268}
269
270static int test__open_syscall_event(void)
271{
272 int err = -1, fd;
273 struct thread_map *threads;
274 struct perf_evsel *evsel;
275 struct perf_event_attr attr;
276 unsigned int nr_open_calls = 111, i;
277 int id = trace_event__id("sys_enter_open");
278
279 if (id < 0) {
280 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
281 return -1;
282 }
283
284 threads = thread_map__new(-1, getpid(), UINT_MAX);
285 if (threads == NULL) {
286 pr_debug("thread_map__new\n");
287 return -1;
288 }
289
290 memset(&attr, 0, sizeof(attr));
291 attr.type = PERF_TYPE_TRACEPOINT;
292 attr.config = id;
293 evsel = perf_evsel__new(&attr, 0);
294 if (evsel == NULL) {
295 pr_debug("perf_evsel__new\n");
296 goto out_thread_map_delete;
297 }
298
299 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
300 pr_debug("failed to open counter: %s, "
301 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
302 strerror(errno));
303 goto out_evsel_delete;
304 }
305
306 for (i = 0; i < nr_open_calls; ++i) {
307 fd = open("/etc/passwd", O_RDONLY);
308 close(fd);
309 }
310
311 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
312 pr_debug("perf_evsel__read_on_cpu\n");
313 goto out_close_fd;
314 }
315
316 if (evsel->counts->cpu[0].val != nr_open_calls) {
317 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
318 nr_open_calls, evsel->counts->cpu[0].val);
319 goto out_close_fd;
320 }
321
322 err = 0;
323out_close_fd:
324 perf_evsel__close_fd(evsel, 1, threads->nr);
325out_evsel_delete:
326 perf_evsel__delete(evsel);
327out_thread_map_delete:
328 thread_map__delete(threads);
329 return err;
330}
331
332#include <sched.h>
333
334static int test__open_syscall_event_on_all_cpus(void)
335{
336 int err = -1, fd, cpu;
337 struct thread_map *threads;
338 struct cpu_map *cpus;
339 struct perf_evsel *evsel;
340 struct perf_event_attr attr;
341 unsigned int nr_open_calls = 111, i;
342 cpu_set_t cpu_set;
343 int id = trace_event__id("sys_enter_open");
344
345 if (id < 0) {
346 pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
347 return -1;
348 }
349
350 threads = thread_map__new(-1, getpid(), UINT_MAX);
351 if (threads == NULL) {
352 pr_debug("thread_map__new\n");
353 return -1;
354 }
355
356 cpus = cpu_map__new(NULL);
357 if (cpus == NULL) {
358 pr_debug("cpu_map__new\n");
359 goto out_thread_map_delete;
360 }
361
362
363 CPU_ZERO(&cpu_set);
364
365 memset(&attr, 0, sizeof(attr));
366 attr.type = PERF_TYPE_TRACEPOINT;
367 attr.config = id;
368 evsel = perf_evsel__new(&attr, 0);
369 if (evsel == NULL) {
370 pr_debug("perf_evsel__new\n");
371 goto out_thread_map_delete;
372 }
373
374 if (perf_evsel__open(evsel, cpus, threads) < 0) {
375 pr_debug("failed to open counter: %s, "
376 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
377 strerror(errno));
378 goto out_evsel_delete;
379 }
380
381 for (cpu = 0; cpu < cpus->nr; ++cpu) {
382 unsigned int ncalls = nr_open_calls + cpu;
383 /*
384 * XXX eventually lift this restriction in a way that
385 * keeps perf building on older glibc installations
386 * without CPU_ALLOC. 1024 cpus in 2010 still seems
387 * a reasonable upper limit tho :-)
388 */
389 if (cpus->map[cpu] >= CPU_SETSIZE) {
390 pr_debug("Ignoring CPU %d\n", cpus->map[cpu]);
391 continue;
392 }
393
394 CPU_SET(cpus->map[cpu], &cpu_set);
395 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
396 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
397 cpus->map[cpu],
398 strerror(errno));
399 goto out_close_fd;
400 }
401 for (i = 0; i < ncalls; ++i) {
402 fd = open("/etc/passwd", O_RDONLY);
403 close(fd);
404 }
405 CPU_CLR(cpus->map[cpu], &cpu_set);
406 }
407
408 /*
409 * Here we need to explicitely preallocate the counts, as if
410 * we use the auto allocation it will allocate just for 1 cpu,
411 * as we start by cpu 0.
412 */
413 if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
414 pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
415 goto out_close_fd;
416 }
417
418 err = 0;
419
420 for (cpu = 0; cpu < cpus->nr; ++cpu) {
421 unsigned int expected;
422
423 if (cpus->map[cpu] >= CPU_SETSIZE)
424 continue;
425
426 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
427 pr_debug("perf_evsel__read_on_cpu\n");
428 err = -1;
429 break;
430 }
431
432 expected = nr_open_calls + cpu;
433 if (evsel->counts->cpu[cpu].val != expected) {
434 pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
435 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
436 err = -1;
437 }
438 }
439
440out_close_fd:
441 perf_evsel__close_fd(evsel, 1, threads->nr);
442out_evsel_delete:
443 perf_evsel__delete(evsel);
444out_thread_map_delete:
445 thread_map__delete(threads);
446 return err;
447}
448
449/*
450 * This test will generate random numbers of calls to some getpid syscalls,
451 * then establish an mmap for a group of events that are created to monitor
452 * the syscalls.
453 *
454 * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
455 * sample.id field to map back to its respective perf_evsel instance.
456 *
457 * Then it checks if the number of syscalls reported as perf events by
458 * the kernel corresponds to the number of syscalls made.
459 */
460static int test__basic_mmap(void)
461{
462 int err = -1;
463 union perf_event *event;
464 struct thread_map *threads;
465 struct cpu_map *cpus;
466 struct perf_evlist *evlist;
467 struct perf_event_attr attr = {
468 .type = PERF_TYPE_TRACEPOINT,
469 .read_format = PERF_FORMAT_ID,
470 .sample_type = PERF_SAMPLE_ID,
471 .watermark = 0,
472 };
473 cpu_set_t cpu_set;
474 const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
475 "getpgid", };
476 pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
477 (void*)getpgid };
478#define nsyscalls ARRAY_SIZE(syscall_names)
479 int ids[nsyscalls];
480 unsigned int nr_events[nsyscalls],
481 expected_nr_events[nsyscalls], i, j;
482 struct perf_evsel *evsels[nsyscalls], *evsel;
483
484 for (i = 0; i < nsyscalls; ++i) {
485 char name[64];
486
487 snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
488 ids[i] = trace_event__id(name);
489 if (ids[i] < 0) {
490 pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
491 return -1;
492 }
493 nr_events[i] = 0;
494 expected_nr_events[i] = random() % 257;
495 }
496
497 threads = thread_map__new(-1, getpid(), UINT_MAX);
498 if (threads == NULL) {
499 pr_debug("thread_map__new\n");
500 return -1;
501 }
502
503 cpus = cpu_map__new(NULL);
504 if (cpus == NULL) {
505 pr_debug("cpu_map__new\n");
506 goto out_free_threads;
507 }
508
509 CPU_ZERO(&cpu_set);
510 CPU_SET(cpus->map[0], &cpu_set);
511 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
512 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
513 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
514 cpus->map[0], strerror(errno));
515 goto out_free_cpus;
516 }
517
518 evlist = perf_evlist__new(cpus, threads);
519 if (evlist == NULL) {
520 pr_debug("perf_evlist__new\n");
521 goto out_free_cpus;
522 }
523
524 /* anonymous union fields, can't be initialized above */
525 attr.wakeup_events = 1;
526 attr.sample_period = 1;
527
528 for (i = 0; i < nsyscalls; ++i) {
529 attr.config = ids[i];
530 evsels[i] = perf_evsel__new(&attr, i);
531 if (evsels[i] == NULL) {
532 pr_debug("perf_evsel__new\n");
533 goto out_free_evlist;
534 }
535
536 perf_evlist__add(evlist, evsels[i]);
537
538 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
539 pr_debug("failed to open counter: %s, "
540 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
541 strerror(errno));
542 goto out_close_fd;
543 }
544 }
545
546 if (perf_evlist__mmap(evlist, 128, true) < 0) {
547 pr_debug("failed to mmap events: %d (%s)\n", errno,
548 strerror(errno));
549 goto out_close_fd;
550 }
551
552 for (i = 0; i < nsyscalls; ++i)
553 for (j = 0; j < expected_nr_events[i]; ++j) {
554 int foo = syscalls[i]();
555 ++foo;
556 }
557
558 while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) {
559 struct perf_sample sample;
560
561 if (event->header.type != PERF_RECORD_SAMPLE) {
562 pr_debug("unexpected %s event\n",
563 perf_event__name(event->header.type));
564 goto out_munmap;
565 }
566
567 err = perf_evlist__parse_sample(evlist, event, &sample);
568 if (err) {
569 pr_err("Can't parse sample, err = %d\n", err);
570 goto out_munmap;
571 }
572
573 evsel = perf_evlist__id2evsel(evlist, sample.id);
574 if (evsel == NULL) {
575 pr_debug("event with id %" PRIu64
576 " doesn't map to an evsel\n", sample.id);
577 goto out_munmap;
578 }
579 nr_events[evsel->idx]++;
580 }
581
582 list_for_each_entry(evsel, &evlist->entries, node) {
583 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
584 pr_debug("expected %d %s events, got %d\n",
585 expected_nr_events[evsel->idx],
586 perf_evsel__name(evsel), nr_events[evsel->idx]);
587 goto out_munmap;
588 }
589 }
590
591 err = 0;
592out_munmap:
593 perf_evlist__munmap(evlist);
594out_close_fd:
595