aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2015-02-10 14:35:36 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2015-02-10 14:35:36 -0500
commit4ba24fef3eb3b142197135223b90ced2f319cd53 (patch)
treea20c125b27740ec7b4c761b11d801108e1b316b2 /tools/perf
parent47c1ffb2b6b630894e9a16442611c056ab21c057 (diff)
parent98a4a59ee31a12105a2b84f5b8b515ac2cb208ef (diff)
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.20.
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/.gitignore3
-rw-r--r--tools/perf/Documentation/perf-diff.txt6
-rw-r--r--tools/perf/Documentation/perf-kvm.txt4
-rw-r--r--tools/perf/Documentation/perf-list.txt2
-rw-r--r--tools/perf/Documentation/perf-probe.txt3
-rw-r--r--tools/perf/Documentation/perf-record.txt8
-rw-r--r--tools/perf/Documentation/perf-report.txt17
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt4
-rw-r--r--tools/perf/Documentation/perf-script-python.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/Documentation/perf-test.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt9
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/Documentation/perf.txt4
-rw-r--r--tools/perf/MANIFEST16
-rw-r--r--tools/perf/Makefile.perf77
-rw-r--r--tools/perf/arch/arm/tests/dwarf-unwind.c1
-rw-r--r--tools/perf/arch/arm/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/arm64/include/perf_regs.h2
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c1
-rw-r--r--tools/perf/arch/common.c9
-rw-r--r--tools/perf/arch/powerpc/Makefile2
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c39
-rw-r--r--tools/perf/bench/futex-hash.c7
-rw-r--r--tools/perf/bench/futex-requeue.c28
-rw-r--r--tools/perf/bench/futex-wake.c15
-rw-r--r--tools/perf/bench/mem-memcpy.c286
-rw-r--r--tools/perf/bench/mem-memset.c304
-rw-r--r--tools/perf/bench/sched-messaging.c2
-rw-r--r--tools/perf/builtin-annotate.c91
-rw-r--r--tools/perf/builtin-buildid-cache.c57
-rw-r--r--tools/perf/builtin-diff.c79
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c20
-rw-r--r--tools/perf/builtin-inject.c37
-rw-r--r--tools/perf/builtin-kmem.c56
-rw-r--r--tools/perf/builtin-kvm.c141
-rw-r--r--tools/perf/builtin-list.c13
-rw-r--r--tools/perf/builtin-lock.c7
-rw-r--r--tools/perf/builtin-mem.c6
-rw-r--r--tools/perf/builtin-probe.c77
-rw-r--r--tools/perf/builtin-record.c168
-rw-r--r--tools/perf/builtin-report.c105
-rw-r--r--tools/perf/builtin-sched.c12
-rw-r--r--tools/perf/builtin-script.c104
-rw-r--r--tools/perf/builtin-stat.c117
-rw-r--r--tools/perf/builtin-timechart.c17
-rw-r--r--tools/perf/builtin-top.c135
-rw-r--r--tools/perf/builtin-trace.c87
-rw-r--r--tools/perf/config/Makefile101
-rw-r--r--tools/perf/config/Makefile.arch8
-rw-r--r--tools/perf/config/feature-checks/Makefile34
-rw-r--r--tools/perf/config/feature-checks/test-all.c5
-rw-r--r--tools/perf/config/feature-checks/test-compile.c4
-rw-r--r--tools/perf/config/feature-checks/test-zlib.c9
-rw-r--r--tools/perf/config/utilities.mak2
-rw-r--r--tools/perf/perf-read-vdso.c34
-rw-r--r--tools/perf/perf-sys.h30
-rw-r--r--tools/perf/perf-with-kcore.sh259
-rw-r--r--tools/perf/perf.c24
-rw-r--r--tools/perf/perf.h7
-rw-r--r--tools/perf/scripts/python/bin/export-to-postgresql-record8
-rw-r--r--tools/perf/scripts/python/bin/export-to-postgresql-report29
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py444
-rw-r--r--tools/perf/tests/attr/base-record2
-rw-r--r--tools/perf/tests/attr/base-stat2
-rw-r--r--tools/perf/tests/builtin-test.c25
-rw-r--r--tools/perf/tests/code-reading.c13
-rw-r--r--tools/perf/tests/dwarf-unwind.c21
-rw-r--r--tools/perf/tests/fdarray.c174
-rw-r--r--tools/perf/tests/hists_cumulate.c74
-rw-r--r--tools/perf/tests/hists_filter.c27
-rw-r--r--tools/perf/tests/hists_link.c23
-rw-r--r--tools/perf/tests/hists_output.c30
-rw-r--r--tools/perf/tests/mmap-basic.c7
-rw-r--r--tools/perf/tests/mmap-thread-lookup.c2
-rw-r--r--tools/perf/tests/open-syscall-all-cpus.c5
-rw-r--r--tools/perf/tests/open-syscall-tp-fields.c9
-rw-r--r--tools/perf/tests/open-syscall.c3
-rw-r--r--tools/perf/tests/parse-events.c36
-rw-r--r--tools/perf/tests/perf-record.c15
-rw-r--r--tools/perf/tests/pmu.c2
-rw-r--r--tools/perf/tests/rdpmc.c6
-rw-r--r--tools/perf/tests/sample-parsing.c55
-rw-r--r--tools/perf/tests/sw-clock.c6
-rw-r--r--tools/perf/tests/switch-tracking.c572
-rw-r--r--tools/perf/tests/task-exit.c8
-rw-r--r--tools/perf/tests/tests.h3
-rw-r--r--tools/perf/ui/browsers/annotate.c13
-rw-r--r--tools/perf/ui/browsers/header.c1
-rw-r--r--tools/perf/ui/browsers/hists.c462
-rw-r--r--tools/perf/ui/gtk/hists.c31
-rw-r--r--tools/perf/ui/hist.c291
-rw-r--r--tools/perf/ui/stdio/hist.c27
-rw-r--r--tools/perf/ui/tui/setup.c26
-rw-r--r--tools/perf/util/annotate.c63
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/build-id.c345
-rw-r--r--tools/perf/util/build-id.h12
-rw-r--r--tools/perf/util/cache.h1
-rw-r--r--tools/perf/util/callchain.c307
-rw-r--r--tools/perf/util/callchain.h21
-rw-r--r--tools/perf/util/cloexec.c35
-rw-r--r--tools/perf/util/color.c16
-rw-r--r--tools/perf/util/color.h1
-rw-r--r--tools/perf/util/comm.c7
-rw-r--r--tools/perf/util/comm.h10
-rw-r--r--tools/perf/util/config.c50
-rw-r--r--tools/perf/util/data.c8
-rw-r--r--tools/perf/util/db-export.c428
-rw-r--r--tools/perf/util/db-export.h107
-rw-r--r--tools/perf/util/debug.c40
-rw-r--r--tools/perf/util/debug.h11
-rw-r--r--tools/perf/util/dso.c192
-rw-r--r--tools/perf/util/dso.h29
-rw-r--r--tools/perf/util/event.c34
-rw-r--r--tools/perf/util/event.h72
-rw-r--r--tools/perf/util/evlist.c374
-rw-r--r--tools/perf/util/evlist.h24
-rw-r--r--tools/perf/util/evsel.c292
-rw-r--r--tools/perf/util/evsel.h69
-rw-r--r--tools/perf/util/find-vdso-map.c30
-rw-r--r--tools/perf/util/header.c394
-rw-r--r--tools/perf/util/header.h8
-rw-r--r--tools/perf/util/hist.c113
-rw-r--r--tools/perf/util/hist.h69
-rw-r--r--tools/perf/util/include/asm/hash.h6
-rw-r--r--tools/perf/util/include/linux/bitmap.h17
-rw-r--r--tools/perf/util/include/linux/bitops.h160
-rw-r--r--tools/perf/util/include/linux/string.h1
-rw-r--r--tools/perf/util/kvm-stat.h1
-rw-r--r--tools/perf/util/machine.c416
-rw-r--r--tools/perf/util/machine.h43
-rw-r--r--tools/perf/util/map.c19
-rw-r--r--tools/perf/util/map.h4
-rw-r--r--tools/perf/util/ordered-events.c286
-rw-r--r--tools/perf/util/ordered-events.h59
-rw-r--r--tools/perf/util/parse-events.c164
-rw-r--r--tools/perf/util/parse-events.h14
-rw-r--r--tools/perf/util/parse-events.l30
-rw-r--r--tools/perf/util/parse-events.y50
-rw-r--r--tools/perf/util/parse-options.c78
-rw-r--r--tools/perf/util/parse-options.h4
-rw-r--r--tools/perf/util/pmu.c236
-rw-r--r--tools/perf/util/pmu.h40
-rw-r--r--tools/perf/util/probe-event.c205
-rw-r--r--tools/perf/util/probe-event.h3
-rw-r--r--tools/perf/util/probe-finder.c41
-rw-r--r--tools/perf/util/python.c6
-rw-r--r--tools/perf/util/record.c51
-rw-r--r--tools/perf/util/run-command.c9
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c35
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c557
-rw-r--r--tools/perf/util/session.c508
-rw-r--r--tools/perf/util/session.h48
-rw-r--r--tools/perf/util/sort.c227
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/srcline.c23
-rw-r--r--tools/perf/util/string.c114
-rw-r--r--tools/perf/util/symbol-elf.c87
-rw-r--r--tools/perf/util/symbol-minimal.c9
-rw-r--r--tools/perf/util/symbol.c70
-rw-r--r--tools/perf/util/symbol.h41
-rw-r--r--tools/perf/util/thread-stack.c747
-rw-r--r--tools/perf/util/thread-stack.h111
-rw-r--r--tools/perf/util/thread.c45
-rw-r--r--tools/perf/util/thread.h19
-rw-r--r--tools/perf/util/thread_map.c21
-rw-r--r--tools/perf/util/thread_map.h1
-rw-r--r--tools/perf/util/tool.h5
-rw-r--r--tools/perf/util/trace-event-scripting.c7
-rw-r--r--tools/perf/util/trace-event.h1
-rw-r--r--tools/perf/util/unwind-libdw.c8
-rw-r--r--tools/perf/util/unwind-libunwind.c66
-rw-r--r--tools/perf/util/unwind.h22
-rw-r--r--tools/perf/util/util.c88
-rw-r--r--tools/perf/util/util.h65
-rw-r--r--tools/perf/util/vdso.c217
-rw-r--r--tools/perf/util/vdso.h4
-rw-r--r--tools/perf/util/zlib.c78
180 files changed, 9959 insertions, 3536 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 782d86e961b9..40399c3d97d6 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -2,6 +2,8 @@ PERF-CFLAGS
2PERF-GUI-VARS 2PERF-GUI-VARS
3PERF-VERSION-FILE 3PERF-VERSION-FILE
4perf 4perf
5perf-read-vdso32
6perf-read-vdsox32
5perf-help 7perf-help
6perf-record 8perf-record
7perf-report 9perf-report
@@ -15,6 +17,7 @@ perf.data
15perf.data.old 17perf.data.old
16output.svg 18output.svg
17perf-archive 19perf-archive
20perf-with-kcore
18tags 21tags
19TAGS 22TAGS
20cscope* 23cscope*
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index b3b8abae62b8..e463caa3eb49 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -196,10 +196,10 @@ If specified the 'Weighted diff' column is displayed with value 'd' computed as:
196 196
197 - period being the hist entry period value 197 - period being the hist entry period value
198 198
199 - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option 199 - WEIGHT-A/WEIGHT-B being user supplied weights in the the '-c' option
200 behind ':' separator like '-c wdiff:1,2'. 200 behind ':' separator like '-c wdiff:1,2'.
201 - WIEGHT-A being the weight of the data file 201 - WEIGHT-A being the weight of the data file
202 - WIEGHT-B being the weight of the baseline data file 202 - WEIGHT-B being the weight of the baseline data file
203 203
204SEE ALSO 204SEE ALSO
205-------- 205--------
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 6e689dc89a2f..6252e776009c 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -100,7 +100,7 @@ OPTIONS
100STAT REPORT OPTIONS 100STAT REPORT OPTIONS
101------------------- 101-------------------
102--vcpu=<value>:: 102--vcpu=<value>::
103 analyze events which occures on this vcpu. (default: all vcpus) 103 analyze events which occur on this vcpu. (default: all vcpus)
104 104
105--event=<value>:: 105--event=<value>::
106 event to be analyzed. Possible values: vmexit, mmio (x86 only), 106 event to be analyzed. Possible values: vmexit, mmio (x86 only),
@@ -134,7 +134,7 @@ STAT LIVE OPTIONS
134 Analyze events only for given process ID(s) (comma separated list). 134 Analyze events only for given process ID(s) (comma separated list).
135 135
136--vcpu=<value>:: 136--vcpu=<value>::
137 analyze events which occures on this vcpu. (default: all vcpus) 137 analyze events which occur on this vcpu. (default: all vcpus)
138 138
139 139
140--event=<value>:: 140--event=<value>::
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 6fce6a622206..cbb4f743d921 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -19,7 +19,7 @@ various perf commands with the -e option.
19EVENT MODIFIERS 19EVENT MODIFIERS
20--------------- 20---------------
21 21
22Events can optionally have a modifer by appending a colon and one or 22Events can optionally have a modifier by appending a colon and one or
23more modifiers. Modifiers allow the user to restrict the events to be 23more modifiers. Modifiers allow the user to restrict the events to be
24counted. The following modifiers exist: 24counted. The following modifiers exist:
25 25
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 1513935c399b..aaa869be3dc1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -104,6 +104,9 @@ OPTIONS
104 Specify path to the executable or shared library file for user 104 Specify path to the executable or shared library file for user
105 space tracing. Can also be used with --funcs option. 105 space tracing. Can also be used with --funcs option.
106 106
107--demangle-kernel::
108 Demangle kernel symbols.
109
107In absence of -m/-x options, perf probe checks if the first argument after 110In absence of -m/-x options, perf probe checks if the first argument after
108the options is an absolute path name. If its an absolute path, perf probe 111the options is an absolute path name. If its an absolute path, perf probe
109uses it as a target module/target user space binary to probe. 112uses it as a target module/target user space binary to probe.
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index d460049cae8e..af9a54ece024 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -146,7 +146,7 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
146 146
147-N:: 147-N::
148--no-buildid-cache:: 148--no-buildid-cache::
149Do not update the builid cache. This saves some overhead in situations 149Do not update the buildid cache. This saves some overhead in situations
150where the information in the perf.data file (which includes buildids) 150where the information in the perf.data file (which includes buildids)
151is sufficient. 151is sufficient.
152 152
@@ -214,6 +214,12 @@ if combined with -a or -C options.
214After starting the program, wait msecs before measuring. This is useful to 214After starting the program, wait msecs before measuring. This is useful to
215filter out the startup phase of the program, which is often very different. 215filter out the startup phase of the program, which is often very different.
216 216
217-I::
218--intr-regs::
219Capture machine state (registers) at interrupt, i.e., on counter overflows for
220each sample. List of captured registers depends on the architecture. This option
221is off by default.
222
217SEE ALSO 223SEE ALSO
218-------- 224--------
219linkperf:perf-stat[1], linkperf:perf-list[1] 225linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index d2b59af62bc0..dd7cccdde498 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -147,7 +147,7 @@ OPTIONS
147-w:: 147-w::
148--column-widths=<width[,width...]>:: 148--column-widths=<width[,width...]>::
149 Force each column width to the provided list, for large terminal 149 Force each column width to the provided list, for large terminal
150 readability. 150 readability. 0 means no limit (default behavior).
151 151
152-t:: 152-t::
153--field-separator=:: 153--field-separator=::
@@ -159,7 +159,7 @@ OPTIONS
159--dump-raw-trace:: 159--dump-raw-trace::
160 Dump raw trace in ASCII. 160 Dump raw trace in ASCII.
161 161
162-g [type,min[,limit],order[,key]]:: 162-g [type,min[,limit],order[,key][,branch]]::
163--call-graph:: 163--call-graph::
164 Display call chains using type, min percent threshold, optional print 164 Display call chains using type, min percent threshold, optional print
165 limit and order. 165 limit and order.
@@ -177,6 +177,11 @@ OPTIONS
177 - function: compare on functions 177 - function: compare on functions
178 - address: compare on individual code addresses 178 - address: compare on individual code addresses
179 179
180 branch can be:
181 - branch: include last branch information in callgraph
182 when available. Usually more convenient to use --branch-history
183 for this.
184
180 Default: fractal,0.5,callee,function. 185 Default: fractal,0.5,callee,function.
181 186
182--children:: 187--children::
@@ -266,6 +271,11 @@ OPTIONS
266 branch stacks and it will automatically switch to the branch view mode, 271 branch stacks and it will automatically switch to the branch view mode,
267 unless --no-branch-stack is used. 272 unless --no-branch-stack is used.
268 273
274--branch-history::
275 Add the addresses of sampled taken branches to the callstack.
276 This allows to examine the path the program took to each sample.
277 The data collection must have used -b (or -j) and -g.
278
269--objdump=<path>:: 279--objdump=<path>::
270 Path to objdump binary. 280 Path to objdump binary.
271 281
@@ -276,6 +286,9 @@ OPTIONS
276 Demangle symbol names to human readable form. It's enabled by default, 286 Demangle symbol names to human readable form. It's enabled by default,
277 disable with --no-demangle. 287 disable with --no-demangle.
278 288
289--demangle-kernel::
290 Demangle kernel symbol names to human readable form (for C++ kernels).
291
279--mem-mode:: 292--mem-mode::
280 Use the data addresses of samples in addition to instruction addresses 293 Use the data addresses of samples in addition to instruction addresses
281 to build the histograms. To generate meaningful output, the perf.data 294 to build the histograms. To generate meaningful output, the perf.data
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index d00bef231340..dfbb506d2c34 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -181,8 +181,8 @@ strings for flag and symbolic fields. These correspond to the strings
181and values parsed from the 'print fmt' fields of the event format 181and values parsed from the 'print fmt' fields of the event format
182files: 182files:
183 183
184 flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name 184 flag_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the flag field $field_name of event $event_name
185 symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name 185 symbol_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the symbolic field $field_name of event $event_name
186 186
187Perf::Trace::Context Module 187Perf::Trace::Context Module
188~~~~~~~~~~~~~~~~~~~~~~~~~~~ 188~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 9f1f054b8432..54acba221558 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -263,7 +263,7 @@ and having the counts we've tallied as values.
263 263
264The print_syscall_totals() function iterates over the entries in the 264The print_syscall_totals() function iterates over the entries in the
265dictionary and displays a line for each entry containing the syscall 265dictionary and displays a line for each entry containing the syscall
266name (the dictonary keys contain the syscall ids, which are passed to 266name (the dictionary keys contain the syscall ids, which are passed to
267the Util function syscall_name(), which translates the raw syscall 267the Util function syscall_name(), which translates the raw syscall
268numbers to the corresponding syscall name strings). The output is 268numbers to the corresponding syscall name strings). The output is
269displayed after all the events in the trace have been processed, by 269displayed after all the events in the trace have been processed, by
@@ -576,8 +576,8 @@ strings for flag and symbolic fields. These correspond to the strings
576and values parsed from the 'print fmt' fields of the event format 576and values parsed from the 'print fmt' fields of the event format
577files: 577files:
578 578
579 flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name 579 flag_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the flag field field_name of event event_name
580 symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name 580 symbol_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the symbolic field field_name of event event_name
581 581
582The *autodict* function returns a special kind of Python 582The *autodict* function returns a special kind of Python
583dictionary that implements Perl's 'autovivifying' hashes in Python 583dictionary that implements Perl's 'autovivifying' hashes in Python
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 05f9a0a6784c..21494806c0ab 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,7 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline, period.
119 Field list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -140,7 +140,7 @@ OPTIONS
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternativey, consider the order: 143 Alternatively, consider the order:
144 144
145 -f comm,tid,time,ip,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index d1d3e5121f89..31a5c3ea7f74 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -25,7 +25,7 @@ OPTIONS
25------- 25-------
26-s:: 26-s::
27--skip:: 27--skip::
28 Tests to skip (comma separater numeric list). 28 Tests to skip (comma separated numeric list).
29 29
30-v:: 30-v::
31--verbose:: 31--verbose::
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 180ae02137a5..3265b1070518 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -98,6 +98,9 @@ Default is to monitor all CPUS.
98--hide_user_symbols:: 98--hide_user_symbols::
99 Hide user symbols. 99 Hide user symbols.
100 100
101--demangle-kernel::
102 Demangle kernel symbols.
103
101-D:: 104-D::
102--dump-symtab:: 105--dump-symtab::
103 Dump the symbol table used for profiling. 106 Dump the symbol table used for profiling.
@@ -193,6 +196,12 @@ Default is to monitor all CPUS.
193 sum of shown entries will be always 100%. "absolute" means it retains 196 sum of shown entries will be always 100%. "absolute" means it retains
194 the original value before and after the filter is applied. 197 the original value before and after the filter is applied.
195 198
199-w::
200--column-widths=<width[,width...]>::
201 Force each column width to the provided list, for large terminal
202 readability. 0 means no limit (default behavior).
203
204
196INTERACTIVE PROMPTING KEYS 205INTERACTIVE PROMPTING KEYS
197-------------------------- 206--------------------------
198 207
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 02aac831bdd9..7e1b1f2bb83c 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -20,7 +20,7 @@ scheduling events, etc.
20This is a live mode tool in addition to working with perf.data files like 20This is a live mode tool in addition to working with perf.data files like
21the other perf tools. Files can be generated using the 'perf record' command 21the other perf tools. Files can be generated using the 'perf record' command
22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*'). 22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
23Alernatively, the 'perf trace record' can be used as a shortcut to 23Alternatively, 'perf trace record' can be used as a shortcut to
24automatically include the raw_syscalls events when writing events to a file. 24automatically include the raw_syscalls events when writing events to a file.
25 25
26The following options apply to perf trace; options to perf trace record are 26The following options apply to perf trace; options to perf trace record are
diff --git a/tools/perf/Documentation/perf.txt b/tools/perf/Documentation/perf.txt
index d240bb2e5b22..1e8e400b4493 100644
--- a/tools/perf/Documentation/perf.txt
+++ b/tools/perf/Documentation/perf.txt
@@ -18,6 +18,10 @@ OPTIONS
18 --debug verbose # sets verbose = 1 18 --debug verbose # sets verbose = 1
19 --debug verbose=2 # sets verbose = 2 19 --debug verbose=2 # sets verbose = 2
20 20
21--buildid-dir::
22 Setup buildid cache directory. It has higher priority than
23 buildid.dir config file option.
24
21DESCRIPTION 25DESCRIPTION
22----------- 26-----------
23Performance counters for Linux are a new kernel-based subsystem 27Performance counters for Linux are a new kernel-based subsystem
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 344c4d3d0a4a..83e2887f91a3 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -4,17 +4,31 @@ tools/lib/traceevent
4tools/lib/api 4tools/lib/api
5tools/lib/symbol/kallsyms.c 5tools/lib/symbol/kallsyms.c
6tools/lib/symbol/kallsyms.h 6tools/lib/symbol/kallsyms.h
7tools/lib/util/find_next_bit.c
7tools/include/asm/bug.h 8tools/include/asm/bug.h
9tools/include/asm-generic/bitops/atomic.h
10tools/include/asm-generic/bitops/__ffs.h
11tools/include/asm-generic/bitops/__fls.h
12tools/include/asm-generic/bitops/find.h
13tools/include/asm-generic/bitops/fls64.h
14tools/include/asm-generic/bitops/fls.h
15tools/include/asm-generic/bitops.h
16tools/include/linux/bitops.h
8tools/include/linux/compiler.h 17tools/include/linux/compiler.h
9tools/include/linux/hash.h
10tools/include/linux/export.h 18tools/include/linux/export.h
19tools/include/linux/hash.h
20tools/include/linux/log2.h
11tools/include/linux/types.h 21tools/include/linux/types.h
22include/asm-generic/bitops/fls64.h
23include/asm-generic/bitops/__fls.h
24include/asm-generic/bitops/fls.h
12include/linux/const.h 25include/linux/const.h
13include/linux/perf_event.h 26include/linux/perf_event.h
14include/linux/rbtree.h 27include/linux/rbtree.h
15include/linux/list.h 28include/linux/list.h
16include/linux/hash.h 29include/linux/hash.h
17include/linux/stringify.h 30include/linux/stringify.h
31lib/find_next_bit.c
18lib/rbtree.c 32lib/rbtree.c
19include/linux/swab.h 33include/linux/swab.h
20arch/*/include/asm/unistd*.h 34arch/*/include/asm/unistd*.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2240974b7745..67a03a825b3c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -60,6 +60,15 @@ include config/utilities.mak
60# 60#
61# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support 61# Define NO_LIBDW_DWARF_UNWIND if you do not want libdw support
62# for dwarf backtrace post unwind. 62# for dwarf backtrace post unwind.
63#
64# Define NO_PERF_READ_VDSO32 if you do not want to build perf-read-vdso32
65# for reading the 32-bit compatibility VDSO in 64-bit mode
66#
67# Define NO_PERF_READ_VDSOX32 if you do not want to build perf-read-vdsox32
68# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
69#
70# Define NO_ZLIB if you do not want to support compressed kernel modules
71
63 72
64ifeq ($(srctree),) 73ifeq ($(srctree),)
65srctree := $(patsubst %/,%,$(dir $(shell pwd))) 74srctree := $(patsubst %/,%,$(dir $(shell pwd)))
@@ -126,6 +135,7 @@ PYRF_OBJS =
126SCRIPT_SH = 135SCRIPT_SH =
127 136
128SCRIPT_SH += perf-archive.sh 137SCRIPT_SH += perf-archive.sh
138SCRIPT_SH += perf-with-kcore.sh
129 139
130grep-libs = $(filter -l%,$(1)) 140grep-libs = $(filter -l%,$(1))
131strip-libs = $(filter-out -l%,$(1)) 141strip-libs = $(filter-out -l%,$(1))
@@ -170,11 +180,16 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
170 180
171SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 181SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
172 182
173#
174# Single 'perf' binary right now:
175#
176PROGRAMS += $(OUTPUT)perf 183PROGRAMS += $(OUTPUT)perf
177 184
185ifndef NO_PERF_READ_VDSO32
186PROGRAMS += $(OUTPUT)perf-read-vdso32
187endif
188
189ifndef NO_PERF_READ_VDSOX32
190PROGRAMS += $(OUTPUT)perf-read-vdsox32
191endif
192
178# what 'all' will build and 'install' will install, in perfexecdir 193# what 'all' will build and 'install' will install, in perfexecdir
179ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS) 194ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
180 195
@@ -216,8 +231,16 @@ LIB_H += ../../include/uapi/linux/const.h
216LIB_H += ../include/linux/hash.h 231LIB_H += ../include/linux/hash.h
217LIB_H += ../../include/linux/stringify.h 232LIB_H += ../../include/linux/stringify.h
218LIB_H += util/include/linux/bitmap.h 233LIB_H += util/include/linux/bitmap.h
219LIB_H += util/include/linux/bitops.h 234LIB_H += ../include/linux/bitops.h
235LIB_H += ../include/asm-generic/bitops/atomic.h
236LIB_H += ../include/asm-generic/bitops/find.h
237LIB_H += ../include/asm-generic/bitops/fls64.h
238LIB_H += ../include/asm-generic/bitops/fls.h
239LIB_H += ../include/asm-generic/bitops/__ffs.h
240LIB_H += ../include/asm-generic/bitops/__fls.h
241LIB_H += ../include/asm-generic/bitops.h
220LIB_H += ../include/linux/compiler.h 242LIB_H += ../include/linux/compiler.h
243LIB_H += ../include/linux/log2.h
221LIB_H += util/include/linux/const.h 244LIB_H += util/include/linux/const.h
222LIB_H += util/include/linux/ctype.h 245LIB_H += util/include/linux/ctype.h
223LIB_H += util/include/linux/kernel.h 246LIB_H += util/include/linux/kernel.h
@@ -246,12 +269,14 @@ LIB_H += util/annotate.h
246LIB_H += util/cache.h 269LIB_H += util/cache.h
247LIB_H += util/callchain.h 270LIB_H += util/callchain.h
248LIB_H += util/build-id.h 271LIB_H += util/build-id.h
272LIB_H += util/db-export.h
249LIB_H += util/debug.h 273LIB_H += util/debug.h
250LIB_H += util/pmu.h 274LIB_H += util/pmu.h
251LIB_H += util/event.h 275LIB_H += util/event.h
252LIB_H += util/evsel.h 276LIB_H += util/evsel.h
253LIB_H += util/evlist.h 277LIB_H += util/evlist.h
254LIB_H += util/exec_cmd.h 278LIB_H += util/exec_cmd.h
279LIB_H += util/find-vdso-map.c
255LIB_H += util/levenshtein.h 280LIB_H += util/levenshtein.h
256LIB_H += util/machine.h 281LIB_H += util/machine.h
257LIB_H += util/map.h 282LIB_H += util/map.h
@@ -263,6 +288,7 @@ LIB_H += util/xyarray.h
263LIB_H += util/header.h 288LIB_H += util/header.h
264LIB_H += util/help.h 289LIB_H += util/help.h
265LIB_H += util/session.h 290LIB_H += util/session.h
291LIB_H += util/ordered-events.h
266LIB_H += util/strbuf.h 292LIB_H += util/strbuf.h
267LIB_H += util/strlist.h 293LIB_H += util/strlist.h
268LIB_H += util/strfilter.h 294LIB_H += util/strfilter.h
@@ -302,6 +328,7 @@ LIB_H += ui/util.h
302LIB_H += ui/ui.h 328LIB_H += ui/ui.h
303LIB_H += util/data.h 329LIB_H += util/data.h
304LIB_H += util/kvm-stat.h 330LIB_H += util/kvm-stat.h
331LIB_H += util/thread-stack.h
305 332
306LIB_OBJS += $(OUTPUT)util/abspath.o 333LIB_OBJS += $(OUTPUT)util/abspath.o
307LIB_OBJS += $(OUTPUT)util/alias.o 334LIB_OBJS += $(OUTPUT)util/alias.o
@@ -309,12 +336,14 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
309LIB_OBJS += $(OUTPUT)util/build-id.o 336LIB_OBJS += $(OUTPUT)util/build-id.o
310LIB_OBJS += $(OUTPUT)util/config.o 337LIB_OBJS += $(OUTPUT)util/config.o
311LIB_OBJS += $(OUTPUT)util/ctype.o 338LIB_OBJS += $(OUTPUT)util/ctype.o
339LIB_OBJS += $(OUTPUT)util/db-export.o
312LIB_OBJS += $(OUTPUT)util/pmu.o 340LIB_OBJS += $(OUTPUT)util/pmu.o
313LIB_OBJS += $(OUTPUT)util/environment.o 341LIB_OBJS += $(OUTPUT)util/environment.o
314LIB_OBJS += $(OUTPUT)util/event.o 342LIB_OBJS += $(OUTPUT)util/event.o
315LIB_OBJS += $(OUTPUT)util/evlist.o 343LIB_OBJS += $(OUTPUT)util/evlist.o
316LIB_OBJS += $(OUTPUT)util/evsel.o 344LIB_OBJS += $(OUTPUT)util/evsel.o
317LIB_OBJS += $(OUTPUT)util/exec_cmd.o 345LIB_OBJS += $(OUTPUT)util/exec_cmd.o
346LIB_OBJS += $(OUTPUT)util/find_next_bit.o
318LIB_OBJS += $(OUTPUT)util/help.o 347LIB_OBJS += $(OUTPUT)util/help.o
319LIB_OBJS += $(OUTPUT)util/kallsyms.o 348LIB_OBJS += $(OUTPUT)util/kallsyms.o
320LIB_OBJS += $(OUTPUT)util/levenshtein.o 349LIB_OBJS += $(OUTPUT)util/levenshtein.o
@@ -347,6 +376,7 @@ LIB_OBJS += $(OUTPUT)util/machine.o
347LIB_OBJS += $(OUTPUT)util/map.o 376LIB_OBJS += $(OUTPUT)util/map.o
348LIB_OBJS += $(OUTPUT)util/pstack.o 377LIB_OBJS += $(OUTPUT)util/pstack.o
349LIB_OBJS += $(OUTPUT)util/session.o 378LIB_OBJS += $(OUTPUT)util/session.o
379LIB_OBJS += $(OUTPUT)util/ordered-events.o
350LIB_OBJS += $(OUTPUT)util/comm.o 380LIB_OBJS += $(OUTPUT)util/comm.o
351LIB_OBJS += $(OUTPUT)util/thread.o 381LIB_OBJS += $(OUTPUT)util/thread.o
352LIB_OBJS += $(OUTPUT)util/thread_map.o 382LIB_OBJS += $(OUTPUT)util/thread_map.o
@@ -377,6 +407,7 @@ LIB_OBJS += $(OUTPUT)util/srcline.o
377LIB_OBJS += $(OUTPUT)util/data.o 407LIB_OBJS += $(OUTPUT)util/data.o
378LIB_OBJS += $(OUTPUT)util/tsc.o 408LIB_OBJS += $(OUTPUT)util/tsc.o
379LIB_OBJS += $(OUTPUT)util/cloexec.o 409LIB_OBJS += $(OUTPUT)util/cloexec.o
410LIB_OBJS += $(OUTPUT)util/thread-stack.o
380 411
381LIB_OBJS += $(OUTPUT)ui/setup.o 412LIB_OBJS += $(OUTPUT)ui/setup.o
382LIB_OBJS += $(OUTPUT)ui/helpline.o 413LIB_OBJS += $(OUTPUT)ui/helpline.o
@@ -399,6 +430,7 @@ LIB_OBJS += $(OUTPUT)tests/perf-record.o
399LIB_OBJS += $(OUTPUT)tests/rdpmc.o 430LIB_OBJS += $(OUTPUT)tests/rdpmc.o
400LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o 431LIB_OBJS += $(OUTPUT)tests/evsel-roundtrip-name.o
401LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o 432LIB_OBJS += $(OUTPUT)tests/evsel-tp-sched.o
433LIB_OBJS += $(OUTPUT)tests/fdarray.o
402LIB_OBJS += $(OUTPUT)tests/pmu.o 434LIB_OBJS += $(OUTPUT)tests/pmu.o
403LIB_OBJS += $(OUTPUT)tests/hists_common.o 435LIB_OBJS += $(OUTPUT)tests/hists_common.o
404LIB_OBJS += $(OUTPUT)tests/hists_link.o 436LIB_OBJS += $(OUTPUT)tests/hists_link.o
@@ -423,6 +455,7 @@ endif
423endif 455endif
424LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o 456LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
425LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o 457LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
458LIB_OBJS += $(OUTPUT)tests/switch-tracking.o
426 459
427BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 460BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
428BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 461BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
@@ -434,7 +467,6 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
434BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o 467BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
435endif 468endif
436BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 469BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
437BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
438BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o 470BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o
439BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o 471BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o
440BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o 472BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
@@ -473,8 +505,6 @@ ifneq ($(OUTPUT),)
473endif 505endif
474 506
475ifdef NO_LIBELF 507ifdef NO_LIBELF
476EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
477
478# Remove ELF/DWARF dependent codes 508# Remove ELF/DWARF dependent codes
479LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS)) 509LIB_OBJS := $(filter-out $(OUTPUT)util/symbol-elf.o,$(LIB_OBJS))
480LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS)) 510LIB_OBJS := $(filter-out $(OUTPUT)util/dwarf-aux.o,$(LIB_OBJS))
@@ -563,6 +593,10 @@ ifndef NO_LIBNUMA
563 BUILTIN_OBJS += $(OUTPUT)bench/numa.o 593 BUILTIN_OBJS += $(OUTPUT)bench/numa.o
564endif 594endif
565 595
596ifndef NO_ZLIB
597 LIB_OBJS += $(OUTPUT)util/zlib.o
598endif
599
566ifdef ASCIIDOC8 600ifdef ASCIIDOC8
567 export ASCIIDOC8 601 export ASCIIDOC8
568endif 602endif
@@ -709,6 +743,9 @@ $(OUTPUT)util/kallsyms.o: ../lib/symbol/kallsyms.c $(OUTPUT)PERF-CFLAGS
709$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 743$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
710 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 744 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
711 745
746$(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c $(OUTPUT)PERF-CFLAGS
747 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
748
712$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS 749$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
713 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $< 750 $(QUIET_CC)$(CC) -o $@ -c $(CFLAGS) -Wno-redundant-decls $<
714 751
@@ -727,6 +764,16 @@ $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Uti
727$(OUTPUT)perf-%: %.o $(PERFLIBS) 764$(OUTPUT)perf-%: %.o $(PERFLIBS)
728 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS) 765 $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
729 766
767ifndef NO_PERF_READ_VDSO32
768$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-vdso-map.c
769 $(QUIET_CC)$(CC) -m32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
770endif
771
772ifndef NO_PERF_READ_VDSOX32
773$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
774 $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
775endif
776
730$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) 777$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
731$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) 778$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
732 779
@@ -765,7 +812,7 @@ $(LIBTRACEEVENT)-clean:
765install-traceevent-plugins: $(LIBTRACEEVENT) 812install-traceevent-plugins: $(LIBTRACEEVENT)
766 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins 813 $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(LIBTRACEEVENT_FLAGS) install_plugins
767 814
768LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch]) 815LIBAPIKFS_SOURCES = $(wildcard $(LIB_PATH)fs/*.[ch] $(LIB_PATH)fd/*.[ch])
769 816
770# if subdir is set, we've been called from above so target has been built 817# if subdir is set, we've been called from above so target has been built
771# already 818# already
@@ -871,10 +918,20 @@ install-bin: all install-gtk
871 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \ 918 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'; \
872 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \ 919 $(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'; \
873 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace' 920 $(LN) '$(DESTDIR_SQ)$(bindir_SQ)/perf' '$(DESTDIR_SQ)$(bindir_SQ)/trace'
921ifndef NO_PERF_READ_VDSO32
922 $(call QUIET_INSTALL, perf-read-vdso32) \
923 $(INSTALL) $(OUTPUT)perf-read-vdso32 '$(DESTDIR_SQ)$(bindir_SQ)';
924endif
925ifndef NO_PERF_READ_VDSOX32
926 $(call QUIET_INSTALL, perf-read-vdsox32) \
927 $(INSTALL) $(OUTPUT)perf-read-vdsox32 '$(DESTDIR_SQ)$(bindir_SQ)';
928endif
874 $(call QUIET_INSTALL, libexec) \ 929 $(call QUIET_INSTALL, libexec) \
875 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 930 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
876 $(call QUIET_INSTALL, perf-archive) \ 931 $(call QUIET_INSTALL, perf-archive) \
877 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)' 932 $(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
933 $(call QUIET_INSTALL, perf-with-kcore) \
934 $(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
878ifndef NO_LIBPERL 935ifndef NO_LIBPERL
879 $(call QUIET_INSTALL, perl-scripts) \ 936 $(call QUIET_INSTALL, perl-scripts) \
880 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \ 937 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -920,8 +977,8 @@ config-clean:
920 @$(MAKE) -C config/feature-checks clean >/dev/null 977 @$(MAKE) -C config/feature-checks clean >/dev/null
921 978
922clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean 979clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
923 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS) 980 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
924 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf 981 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
925 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* 982 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
926 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 983 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
927 $(python-clean) 984 $(python-clean)
diff --git a/tools/perf/arch/arm/tests/dwarf-unwind.c b/tools/perf/arch/arm/tests/dwarf-unwind.c
index 9f870d27cb39..62eff847f91c 100644
--- a/tools/perf/arch/arm/tests/dwarf-unwind.c
+++ b/tools/perf/arch/arm/tests/dwarf-unwind.c
@@ -3,6 +3,7 @@
3#include "thread.h" 3#include "thread.h"
4#include "map.h" 4#include "map.h"
5#include "event.h" 5#include "event.h"
6#include "debug.h"
6#include "tests/tests.h" 7#include "tests/tests.h"
7 8
8#define STACK_SIZE 8192 9#define STACK_SIZE 8192
diff --git a/tools/perf/arch/arm/util/unwind-libunwind.c b/tools/perf/arch/arm/util/unwind-libunwind.c
index 729ed69a6664..62c397ed3d97 100644
--- a/tools/perf/arch/arm/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
index e9441b9e2a30..1d3f39c3aa56 100644
--- a/tools/perf/arch/arm64/include/perf_regs.h
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -6,6 +6,8 @@
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) 8#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_ARM64_MAX
10
9#define PERF_REG_IP PERF_REG_ARM64_PC 11#define PERF_REG_IP PERF_REG_ARM64_PC
10#define PERF_REG_SP PERF_REG_ARM64_SP 12#define PERF_REG_SP PERF_REG_ARM64_SP
11 13
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index 436ee43859dc..a87afa91a99e 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -3,6 +3,7 @@
3#include <libunwind.h> 3#include <libunwind.h>
4#include "perf_regs.h" 4#include "perf_regs.h"
5#include "../../util/unwind.h" 5#include "../../util/unwind.h"
6#include "../../util/debug.h"
6 7
7int libunwind__arch_reg_id(int regnum) 8int libunwind__arch_reg_id(int regnum)
8{ 9{
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index 42faf369211c..49776f190abf 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -12,6 +12,11 @@ const char *const arm_triplets[] = {
12 NULL 12 NULL
13}; 13};
14 14
15const char *const arm64_triplets[] = {
16 "aarch64-linux-android-",
17 NULL
18};
19
15const char *const powerpc_triplets[] = { 20const char *const powerpc_triplets[] = {
16 "powerpc-unknown-linux-gnu-", 21 "powerpc-unknown-linux-gnu-",
17 "powerpc64-unknown-linux-gnu-", 22 "powerpc64-unknown-linux-gnu-",
@@ -105,6 +110,8 @@ static const char *normalize_arch(char *arch)
105 return "x86"; 110 return "x86";
106 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5)) 111 if (!strcmp(arch, "sun4u") || !strncmp(arch, "sparc", 5))
107 return "sparc"; 112 return "sparc";
113 if (!strcmp(arch, "aarch64") || !strcmp(arch, "arm64"))
114 return "arm64";
108 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110")) 115 if (!strncmp(arch, "arm", 3) || !strcmp(arch, "sa110"))
109 return "arm"; 116 return "arm";
110 if (!strncmp(arch, "s390", 4)) 117 if (!strncmp(arch, "s390", 4))
@@ -159,6 +166,8 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env,
159 166
160 if (!strcmp(arch, "arm")) 167 if (!strcmp(arch, "arm"))
161 path_list = arm_triplets; 168 path_list = arm_triplets;
169 else if (!strcmp(arch, "arm64"))
170 path_list = arm64_triplets;
162 else if (!strcmp(arch, "powerpc")) 171 else if (!strcmp(arch, "powerpc"))
163 path_list = powerpc_triplets; 172 path_list = powerpc_triplets;
164 else if (!strcmp(arch, "sh")) 173 else if (!strcmp(arch, "sh"))
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index b92219b1900d..6f7782bea5dd 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -1,6 +1,6 @@
1ifndef NO_DWARF 1ifndef NO_DWARF
2PERF_HAVE_DWARF_REGS := 1 2PERF_HAVE_DWARF_REGS := 1
3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o 3LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
4LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
4endif 5endif
5LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o 6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
6LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index a7c23a4b3778..3bb50eac5542 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -15,6 +15,7 @@
15 15
16#include "util/thread.h" 16#include "util/thread.h"
17#include "util/callchain.h" 17#include "util/callchain.h"
18#include "util/debug.h"
18 19
19/* 20/*
20 * When saving the callchain on Power, the kernel conservatively saves 21 * When saving the callchain on Power, the kernel conservatively saves
@@ -144,7 +145,7 @@ static Dwarf_Frame *get_dwarf_frame(Dwfl_Module *mod, Dwarf_Addr pc)
144 * yet used) 145 * yet used)
145 * -1 in case of errors 146 * -1 in case of errors
146 */ 147 */
147static int check_return_addr(const char *exec_file, Dwarf_Addr pc) 148static int check_return_addr(struct dso *dso, Dwarf_Addr pc)
148{ 149{
149 int rc = -1; 150 int rc = -1;
150 Dwfl *dwfl; 151 Dwfl *dwfl;
@@ -155,15 +156,27 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
155 Dwarf_Addr end = pc; 156 Dwarf_Addr end = pc;
156 bool signalp; 157 bool signalp;
157 158
158 dwfl = dwfl_begin(&offline_callbacks); 159 dwfl = dso->dwfl;
159 if (!dwfl) {
160 pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
161 return -1;
162 }
163 160
164 if (dwfl_report_offline(dwfl, "", exec_file, -1) == NULL) { 161 if (!dwfl) {
165 pr_debug("dwfl_report_offline() failed %s\n", dwarf_errmsg(-1)); 162 dwfl = dwfl_begin(&offline_callbacks);
166 goto out; 163 if (!dwfl) {
164 pr_debug("dwfl_begin() failed: %s\n", dwarf_errmsg(-1));
165 return -1;
166 }
167
168 if (dwfl_report_offline(dwfl, "", dso->long_name, -1) == NULL) {
169 pr_debug("dwfl_report_offline() failed %s\n",
170 dwarf_errmsg(-1));
171 /*
172 * We normally cache the DWARF debug info and never
173 * call dwfl_end(). But to prevent fd leak, free in
174 * case of error.
175 */
176 dwfl_end(dwfl);
177 goto out;
178 }
179 dso->dwfl = dwfl;
167 } 180 }
168 181
169 mod = dwfl_addrmodule(dwfl, pc); 182 mod = dwfl_addrmodule(dwfl, pc);
@@ -193,7 +206,6 @@ static int check_return_addr(const char *exec_file, Dwarf_Addr pc)
193 rc = check_return_reg(ra_regno, frame); 206 rc = check_return_reg(ra_regno, frame);
194 207
195out: 208out:
196 dwfl_end(dwfl);
197 return rc; 209 return rc;
198} 210}
199 211
@@ -220,8 +232,7 @@ out:
220 * index: of callchain entry that needs to be ignored (if any) 232 * index: of callchain entry that needs to be ignored (if any)
221 * -1 if no entry needs to be ignored or in case of errors 233 * -1 if no entry needs to be ignored or in case of errors
222 */ 234 */
223int arch_skip_callchain_idx(struct machine *machine, struct thread *thread, 235int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
224 struct ip_callchain *chain)
225{ 236{
226 struct addr_location al; 237 struct addr_location al;
227 struct dso *dso = NULL; 238 struct dso *dso = NULL;
@@ -234,7 +245,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
234 245
235 ip = chain->ips[2]; 246 ip = chain->ips[2];
236 247
237 thread__find_addr_location(thread, machine, PERF_RECORD_MISC_USER, 248 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
238 MAP__FUNCTION, ip, &al); 249 MAP__FUNCTION, ip, &al);
239 250
240 if (al.map) 251 if (al.map)
@@ -245,7 +256,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread,
245 return skip_slot; 256 return skip_slot;
246 } 257 }
247 258
248 rc = check_return_addr(dso->long_name, ip); 259 rc = check_return_addr(dso, ip);
249 260
250 pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n", 261 pr_debug("DSO %s, nr %" PRIx64 ", ip 0x%" PRIx64 "rc %d\n",
251 dso->long_name, chain->nr, ip, rc); 262 dso->long_name, chain->nr, ip, rc);
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index a84206e9c4aa..fc9bebd2cca0 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -26,6 +26,7 @@ static unsigned int nsecs = 10;
26/* amount of futexes per thread */ 26/* amount of futexes per thread */
27static unsigned int nfutexes = 1024; 27static unsigned int nfutexes = 1024;
28static bool fshared = false, done = false, silent = false; 28static bool fshared = false, done = false, silent = false;
29static int futex_flag = 0;
29 30
30struct timeval start, end, runtime; 31struct timeval start, end, runtime;
31static pthread_mutex_t thread_lock; 32static pthread_mutex_t thread_lock;
@@ -75,8 +76,7 @@ static void *workerfn(void *arg)
75 * such as internal waitqueue handling, thus enlarging 76 * such as internal waitqueue handling, thus enlarging
76 * the critical region protected by hb->lock. 77 * the critical region protected by hb->lock.
77 */ 78 */
78 ret = futex_wait(&w->futex[i], 1234, NULL, 79 ret = futex_wait(&w->futex[i], 1234, NULL, futex_flag);
79 fshared ? 0 : FUTEX_PRIVATE_FLAG);
80 if (!silent && 80 if (!silent &&
81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK)) 81 (!ret || errno != EAGAIN || errno != EWOULDBLOCK))
82 warn("Non-expected futex return call"); 82 warn("Non-expected futex return call");
@@ -135,6 +135,9 @@ int bench_futex_hash(int argc, const char **argv,
135 if (!worker) 135 if (!worker)
136 goto errmem; 136 goto errmem;
137 137
138 if (!fshared)
139 futex_flag = FUTEX_PRIVATE_FLAG;
140
138 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n", 141 printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
139 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs); 142 getpid(), nthreads, nfutexes, fshared ? "shared":"private", nsecs);
140 143
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 732403bfd31a..bedff6b5b3cf 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -30,16 +30,18 @@ static u_int32_t futex1 = 0, futex2 = 0;
30static unsigned int nrequeue = 1; 30static unsigned int nrequeue = 1;
31 31
32static pthread_t *worker; 32static pthread_t *worker;
33static bool done = 0, silent = 0; 33static bool done = false, silent = false, fshared = false;
34static pthread_mutex_t thread_lock; 34static pthread_mutex_t thread_lock;
35static pthread_cond_t thread_parent, thread_worker; 35static pthread_cond_t thread_parent, thread_worker;
36static struct stats requeuetime_stats, requeued_stats; 36static struct stats requeuetime_stats, requeued_stats;
37static unsigned int ncpus, threads_starting, nthreads = 0; 37static unsigned int ncpus, threads_starting, nthreads = 0;
38static int futex_flag = 0;
38 39
39static const struct option options[] = { 40static const struct option options[] = {
40 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
41 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"), 42 OPT_UINTEGER('q', "nrequeue", &nrequeue, "Specify amount of threads to requeue at once"),
42 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
44 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
43 OPT_END() 45 OPT_END()
44}; 46};
45 47
@@ -70,7 +72,7 @@ static void *workerfn(void *arg __maybe_unused)
70 pthread_cond_wait(&thread_worker, &thread_lock); 72 pthread_cond_wait(&thread_worker, &thread_lock);
71 pthread_mutex_unlock(&thread_lock); 73 pthread_mutex_unlock(&thread_lock);
72 74
73 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 75 futex_wait(&futex1, 0, NULL, futex_flag);
74 return NULL; 76 return NULL;
75} 77}
76 78
@@ -127,9 +129,12 @@ int bench_futex_requeue(int argc, const char **argv,
127 if (!worker) 129 if (!worker)
128 err(EXIT_FAILURE, "calloc"); 130 err(EXIT_FAILURE, "calloc");
129 131
130 printf("Run summary [PID %d]: Requeuing %d threads (from %p to %p), " 132 if (!fshared)
131 "%d at a time.\n\n", 133 futex_flag = FUTEX_PRIVATE_FLAG;
132 getpid(), nthreads, &futex1, &futex2, nrequeue); 134
135 printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
136 "%d at a time.\n\n", getpid(), nthreads,
137 fshared ? "shared":"private", &futex1, &futex2, nrequeue);
133 138
134 init_stats(&requeued_stats); 139 init_stats(&requeued_stats);
135 init_stats(&requeuetime_stats); 140 init_stats(&requeuetime_stats);
@@ -156,16 +161,20 @@ int bench_futex_requeue(int argc, const char **argv,
156 161
157 /* Ok, all threads are patiently blocked, start requeueing */ 162 /* Ok, all threads are patiently blocked, start requeueing */
158 gettimeofday(&start, NULL); 163 gettimeofday(&start, NULL);
159 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) 164 for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
160 /* 165 /*
161 * Do not wakeup any tasks blocked on futex1, allowing 166 * Do not wakeup any tasks blocked on futex1, allowing
162 * us to really measure futex_wait functionality. 167 * us to really measure futex_wait functionality.
163 */ 168 */
164 futex_cmp_requeue(&futex1, 0, &futex2, 0, nrequeue, 169 futex_cmp_requeue(&futex1, 0, &futex2, 0,
165 FUTEX_PRIVATE_FLAG); 170 nrequeue, futex_flag);
171 }
166 gettimeofday(&end, NULL); 172 gettimeofday(&end, NULL);
167 timersub(&end, &start, &runtime); 173 timersub(&end, &start, &runtime);
168 174
175 if (nrequeued > nthreads)
176 nrequeued = nthreads;
177
169 update_stats(&requeued_stats, nrequeued); 178 update_stats(&requeued_stats, nrequeued);
170 update_stats(&requeuetime_stats, runtime.tv_usec); 179 update_stats(&requeuetime_stats, runtime.tv_usec);
171 180
@@ -175,7 +184,7 @@ int bench_futex_requeue(int argc, const char **argv,
175 } 184 }
176 185
177 /* everybody should be blocked on futex2, wake'em up */ 186 /* everybody should be blocked on futex2, wake'em up */
178 nrequeued = futex_wake(&futex2, nthreads, FUTEX_PRIVATE_FLAG); 187 nrequeued = futex_wake(&futex2, nthreads, futex_flag);
179 if (nthreads != nrequeued) 188 if (nthreads != nrequeued)
180 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads); 189 warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
181 190
@@ -184,7 +193,6 @@ int bench_futex_requeue(int argc, const char **argv,
184 if (ret) 193 if (ret)
185 err(EXIT_FAILURE, "pthread_join"); 194 err(EXIT_FAILURE, "pthread_join");
186 } 195 }
187
188 } 196 }
189 197
190 /* cleanup & report results */ 198 /* cleanup & report results */
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index 50022cbce87e..929f762be47e 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -31,16 +31,18 @@ static u_int32_t futex1 = 0;
31static unsigned int nwakes = 1; 31static unsigned int nwakes = 1;
32 32
33pthread_t *worker; 33pthread_t *worker;
34static bool done = false, silent = false; 34static bool done = false, silent = false, fshared = false;
35static pthread_mutex_t thread_lock; 35static pthread_mutex_t thread_lock;
36static pthread_cond_t thread_parent, thread_worker; 36static pthread_cond_t thread_parent, thread_worker;
37static struct stats waketime_stats, wakeup_stats; 37static struct stats waketime_stats, wakeup_stats;
38static unsigned int ncpus, threads_starting, nthreads = 0; 38static unsigned int ncpus, threads_starting, nthreads = 0;
39static int futex_flag = 0;
39 40
40static const struct option options[] = { 41static const struct option options[] = {
41 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"), 42 OPT_UINTEGER('t', "threads", &nthreads, "Specify amount of threads"),
42 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"), 43 OPT_UINTEGER('w', "nwakes", &nwakes, "Specify amount of threads to wake at once"),
43 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"), 44 OPT_BOOLEAN( 's', "silent", &silent, "Silent mode: do not display data/details"),
45 OPT_BOOLEAN( 'S', "shared", &fshared, "Use shared futexes instead of private ones"),
44 OPT_END() 46 OPT_END()
45}; 47};
46 48
@@ -58,7 +60,7 @@ static void *workerfn(void *arg __maybe_unused)
58 pthread_cond_wait(&thread_worker, &thread_lock); 60 pthread_cond_wait(&thread_worker, &thread_lock);
59 pthread_mutex_unlock(&thread_lock); 61 pthread_mutex_unlock(&thread_lock);
60 62
61 futex_wait(&futex1, 0, NULL, FUTEX_PRIVATE_FLAG); 63 futex_wait(&futex1, 0, NULL, futex_flag);
62 return NULL; 64 return NULL;
63} 65}
64 66
@@ -130,9 +132,12 @@ int bench_futex_wake(int argc, const char **argv,
130 if (!worker) 132 if (!worker)
131 err(EXIT_FAILURE, "calloc"); 133 err(EXIT_FAILURE, "calloc");
132 134
133 printf("Run summary [PID %d]: blocking on %d threads (at futex %p), " 135 if (!fshared)
136 futex_flag = FUTEX_PRIVATE_FLAG;
137
138 printf("Run summary [PID %d]: blocking on %d threads (at [%s] futex %p), "
134 "waking up %d at a time.\n\n", 139 "waking up %d at a time.\n\n",
135 getpid(), nthreads, &futex1, nwakes); 140 getpid(), nthreads, fshared ? "shared":"private", &futex1, nwakes);
136 141
137 init_stats(&wakeup_stats); 142 init_stats(&wakeup_stats);
138 init_stats(&waketime_stats); 143 init_stats(&waketime_stats);
@@ -160,7 +165,7 @@ int bench_futex_wake(int argc, const char **argv,
160 /* Ok, all threads are patiently blocked, start waking folks up */ 165 /* Ok, all threads are patiently blocked, start waking folks up */
161 gettimeofday(&start, NULL); 166 gettimeofday(&start, NULL);
162 while (nwoken != nthreads) 167 while (nwoken != nthreads)
163 nwoken += futex_wake(&futex1, nwakes, FUTEX_PRIVATE_FLAG); 168 nwoken += futex_wake(&futex1, nwakes, futex_flag);
164 gettimeofday(&end, NULL); 169 gettimeofday(&end, NULL);
165 timersub(&end, &start, &runtime); 170 timersub(&end, &start, &runtime);
166 171
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 2465141b554b..6c14afe8c1b1 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -13,6 +13,7 @@
13#include "../util/cloexec.h" 13#include "../util/cloexec.h"
14#include "bench.h" 14#include "bench.h"
15#include "mem-memcpy-arch.h" 15#include "mem-memcpy-arch.h"
16#include "mem-memset-arch.h"
16 17
17#include <stdio.h> 18#include <stdio.h>
18#include <stdlib.h> 19#include <stdlib.h>
@@ -48,20 +49,24 @@ static const struct option options[] = {
48}; 49};
49 50
50typedef void *(*memcpy_t)(void *, const void *, size_t); 51typedef void *(*memcpy_t)(void *, const void *, size_t);
52typedef void *(*memset_t)(void *, int, size_t);
51 53
52struct routine { 54struct routine {
53 const char *name; 55 const char *name;
54 const char *desc; 56 const char *desc;
55 memcpy_t fn; 57 union {
58 memcpy_t memcpy;
59 memset_t memset;
60 } fn;
56}; 61};
57 62
58struct routine routines[] = { 63struct routine memcpy_routines[] = {
59 { "default", 64 { .name = "default",
60 "Default memcpy() provided by glibc", 65 .desc = "Default memcpy() provided by glibc",
61 memcpy }, 66 .fn.memcpy = memcpy },
62#ifdef HAVE_ARCH_X86_64_SUPPORT 67#ifdef HAVE_ARCH_X86_64_SUPPORT
63 68
64#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, 69#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn},
65#include "mem-memcpy-x86-64-asm-def.h" 70#include "mem-memcpy-x86-64-asm-def.h"
66#undef MEMCPY_FN 71#undef MEMCPY_FN
67 72
@@ -69,7 +74,7 @@ struct routine routines[] = {
69 74
70 { NULL, 75 { NULL,
71 NULL, 76 NULL,
72 NULL } 77 {NULL} }
73}; 78};
74 79
75static const char * const bench_mem_memcpy_usage[] = { 80static const char * const bench_mem_memcpy_usage[] = {
@@ -110,63 +115,6 @@ static double timeval2double(struct timeval *ts)
110 (double)ts->tv_usec / (double)1000000; 115 (double)ts->tv_usec / (double)1000000;
111} 116}
112 117
113static void alloc_mem(void **dst, void **src, size_t length)
114{
115 *dst = zalloc(length);
116 if (!*dst)
117 die("memory allocation failed - maybe length is too large?\n");
118
119 *src = zalloc(length);
120 if (!*src)
121 die("memory allocation failed - maybe length is too large?\n");
122 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
123 memset(*src, 0, length);
124}
125
126static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
127{
128 u64 cycle_start = 0ULL, cycle_end = 0ULL;
129 void *src = NULL, *dst = NULL;
130 int i;
131
132 alloc_mem(&src, &dst, len);
133
134 if (prefault)
135 fn(dst, src, len);
136
137 cycle_start = get_cycle();
138 for (i = 0; i < iterations; ++i)
139 fn(dst, src, len);
140 cycle_end = get_cycle();
141
142 free(src);
143 free(dst);
144 return cycle_end - cycle_start;
145}
146
147static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
148{
149 struct timeval tv_start, tv_end, tv_diff;
150 void *src = NULL, *dst = NULL;
151 int i;
152
153 alloc_mem(&src, &dst, len);
154
155 if (prefault)
156 fn(dst, src, len);
157
158 BUG_ON(gettimeofday(&tv_start, NULL));
159 for (i = 0; i < iterations; ++i)
160 fn(dst, src, len);
161 BUG_ON(gettimeofday(&tv_end, NULL));
162
163 timersub(&tv_end, &tv_start, &tv_diff);
164
165 free(src);
166 free(dst);
167 return (double)((double)len / timeval2double(&tv_diff));
168}
169
170#define pf (no_prefault ? 0 : 1) 118#define pf (no_prefault ? 0 : 1)
171 119
172#define print_bps(x) do { \ 120#define print_bps(x) do { \
@@ -180,16 +128,25 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
180 printf(" %14lf GB/Sec", x / K / K / K); \ 128 printf(" %14lf GB/Sec", x / K / K / K); \
181 } while (0) 129 } while (0)
182 130
183int bench_mem_memcpy(int argc, const char **argv, 131struct bench_mem_info {
184 const char *prefix __maybe_unused) 132 const struct routine *routines;
133 u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault);
134 double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault);
135 const char *const *usage;
136};
137
138static int bench_mem_common(int argc, const char **argv,
139 const char *prefix __maybe_unused,
140 struct bench_mem_info *info)
185{ 141{
186 int i; 142 int i;
187 size_t len; 143 size_t len;
144 double totallen;
188 double result_bps[2]; 145 double result_bps[2];
189 u64 result_cycle[2]; 146 u64 result_cycle[2];
190 147
191 argc = parse_options(argc, argv, options, 148 argc = parse_options(argc, argv, options,
192 bench_mem_memcpy_usage, 0); 149 info->usage, 0);
193 150
194 if (no_prefault && only_prefault) { 151 if (no_prefault && only_prefault) {
195 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); 152 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
@@ -200,6 +157,7 @@ int bench_mem_memcpy(int argc, const char **argv,
200 init_cycle(); 157 init_cycle();
201 158
202 len = (size_t)perf_atoll((char *)length_str); 159 len = (size_t)perf_atoll((char *)length_str);
160 totallen = (double)len * iterations;
203 161
204 result_cycle[0] = result_cycle[1] = 0ULL; 162 result_cycle[0] = result_cycle[1] = 0ULL;
205 result_bps[0] = result_bps[1] = 0.0; 163 result_bps[0] = result_bps[1] = 0.0;
@@ -213,16 +171,16 @@ int bench_mem_memcpy(int argc, const char **argv,
213 if (only_prefault && no_prefault) 171 if (only_prefault && no_prefault)
214 only_prefault = no_prefault = false; 172 only_prefault = no_prefault = false;
215 173
216 for (i = 0; routines[i].name; i++) { 174 for (i = 0; info->routines[i].name; i++) {
217 if (!strcmp(routines[i].name, routine)) 175 if (!strcmp(info->routines[i].name, routine))
218 break; 176 break;
219 } 177 }
220 if (!routines[i].name) { 178 if (!info->routines[i].name) {
221 printf("Unknown routine:%s\n", routine); 179 printf("Unknown routine:%s\n", routine);
222 printf("Available routines...\n"); 180 printf("Available routines...\n");
223 for (i = 0; routines[i].name; i++) { 181 for (i = 0; info->routines[i].name; i++) {
224 printf("\t%s ... %s\n", 182 printf("\t%s ... %s\n",
225 routines[i].name, routines[i].desc); 183 info->routines[i].name, info->routines[i].desc);
226 } 184 }
227 return 1; 185 return 1;
228 } 186 }
@@ -234,25 +192,25 @@ int bench_mem_memcpy(int argc, const char **argv,
234 /* show both of results */ 192 /* show both of results */
235 if (use_cycle) { 193 if (use_cycle) {
236 result_cycle[0] = 194 result_cycle[0] =
237 do_memcpy_cycle(routines[i].fn, len, false); 195 info->do_cycle(&info->routines[i], len, false);
238 result_cycle[1] = 196 result_cycle[1] =
239 do_memcpy_cycle(routines[i].fn, len, true); 197 info->do_cycle(&info->routines[i], len, true);
240 } else { 198 } else {
241 result_bps[0] = 199 result_bps[0] =
242 do_memcpy_gettimeofday(routines[i].fn, 200 info->do_gettimeofday(&info->routines[i],
243 len, false); 201 len, false);
244 result_bps[1] = 202 result_bps[1] =
245 do_memcpy_gettimeofday(routines[i].fn, 203 info->do_gettimeofday(&info->routines[i],
246 len, true); 204 len, true);
247 } 205 }
248 } else { 206 } else {
249 if (use_cycle) { 207 if (use_cycle) {
250 result_cycle[pf] = 208 result_cycle[pf] =
251 do_memcpy_cycle(routines[i].fn, 209 info->do_cycle(&info->routines[i],
252 len, only_prefault); 210 len, only_prefault);
253 } else { 211 } else {
254 result_bps[pf] = 212 result_bps[pf] =
255 do_memcpy_gettimeofday(routines[i].fn, 213 info->do_gettimeofday(&info->routines[i],
256 len, only_prefault); 214 len, only_prefault);
257 } 215 }
258 } 216 }
@@ -263,10 +221,10 @@ int bench_mem_memcpy(int argc, const char **argv,
263 if (use_cycle) { 221 if (use_cycle) {
264 printf(" %14lf Cycle/Byte\n", 222 printf(" %14lf Cycle/Byte\n",
265 (double)result_cycle[0] 223 (double)result_cycle[0]
266 / (double)len); 224 / totallen);
267 printf(" %14lf Cycle/Byte (with prefault)\n", 225 printf(" %14lf Cycle/Byte (with prefault)\n",
268 (double)result_cycle[1] 226 (double)result_cycle[1]
269 / (double)len); 227 / totallen);
270 } else { 228 } else {
271 print_bps(result_bps[0]); 229 print_bps(result_bps[0]);
272 printf("\n"); 230 printf("\n");
@@ -277,7 +235,7 @@ int bench_mem_memcpy(int argc, const char **argv,
277 if (use_cycle) { 235 if (use_cycle) {
278 printf(" %14lf Cycle/Byte", 236 printf(" %14lf Cycle/Byte",
279 (double)result_cycle[pf] 237 (double)result_cycle[pf]
280 / (double)len); 238 / totallen);
281 } else 239 } else
282 print_bps(result_bps[pf]); 240 print_bps(result_bps[pf]);
283 241
@@ -288,8 +246,8 @@ int bench_mem_memcpy(int argc, const char **argv,
288 if (!only_prefault && !no_prefault) { 246 if (!only_prefault && !no_prefault) {
289 if (use_cycle) { 247 if (use_cycle) {
290 printf("%lf %lf\n", 248 printf("%lf %lf\n",
291 (double)result_cycle[0] / (double)len, 249 (double)result_cycle[0] / totallen,
292 (double)result_cycle[1] / (double)len); 250 (double)result_cycle[1] / totallen);
293 } else { 251 } else {
294 printf("%lf %lf\n", 252 printf("%lf %lf\n",
295 result_bps[0], result_bps[1]); 253 result_bps[0], result_bps[1]);
@@ -297,7 +255,7 @@ int bench_mem_memcpy(int argc, const char **argv,
297 } else { 255 } else {
298 if (use_cycle) { 256 if (use_cycle) {
299 printf("%lf\n", (double)result_cycle[pf] 257 printf("%lf\n", (double)result_cycle[pf]
300 / (double)len); 258 / totallen);
301 } else 259 } else
302 printf("%lf\n", result_bps[pf]); 260 printf("%lf\n", result_bps[pf]);
303 } 261 }
@@ -310,3 +268,163 @@ int bench_mem_memcpy(int argc, const char **argv,
310 268
311 return 0; 269 return 0;
312} 270}
271
272static void memcpy_alloc_mem(void **dst, void **src, size_t length)
273{
274 *dst = zalloc(length);
275 if (!*dst)
276 die("memory allocation failed - maybe length is too large?\n");
277
278 *src = zalloc(length);
279 if (!*src)
280 die("memory allocation failed - maybe length is too large?\n");
281 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
282 memset(*src, 0, length);
283}
284
285static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault)
286{
287 u64 cycle_start = 0ULL, cycle_end = 0ULL;
288 void *src = NULL, *dst = NULL;
289 memcpy_t fn = r->fn.memcpy;
290 int i;
291
292 memcpy_alloc_mem(&src, &dst, len);
293
294 if (prefault)
295 fn(dst, src, len);
296
297 cycle_start = get_cycle();
298 for (i = 0; i < iterations; ++i)
299 fn(dst, src, len);
300 cycle_end = get_cycle();
301
302 free(src);
303 free(dst);
304 return cycle_end - cycle_start;
305}
306
307static double do_memcpy_gettimeofday(const struct routine *r, size_t len,
308 bool prefault)
309{
310 struct timeval tv_start, tv_end, tv_diff;
311 memcpy_t fn = r->fn.memcpy;
312 void *src = NULL, *dst = NULL;
313 int i;
314
315 memcpy_alloc_mem(&src, &dst, len);
316
317 if (prefault)
318 fn(dst, src, len);
319
320 BUG_ON(gettimeofday(&tv_start, NULL));
321 for (i = 0; i < iterations; ++i)
322 fn(dst, src, len);
323 BUG_ON(gettimeofday(&tv_end, NULL));
324
325 timersub(&tv_end, &tv_start, &tv_diff);
326
327 free(src);
328 free(dst);
329 return (double)(((double)len * iterations) / timeval2double(&tv_diff));
330}
331
332int bench_mem_memcpy(int argc, const char **argv,
333 const char *prefix __maybe_unused)
334{
335 struct bench_mem_info info = {
336 .routines = memcpy_routines,
337 .do_cycle = do_memcpy_cycle,
338 .do_gettimeofday = do_memcpy_gettimeofday,
339 .usage = bench_mem_memcpy_usage,
340 };
341
342 return bench_mem_common(argc, argv, prefix, &info);
343}
344
345static void memset_alloc_mem(void **dst, size_t length)
346{
347 *dst = zalloc(length);
348 if (!*dst)
349 die("memory allocation failed - maybe length is too large?\n");
350}
351
352static u64 do_memset_cycle(const struct routine *r, size_t len, bool prefault)
353{
354 u64 cycle_start = 0ULL, cycle_end = 0ULL;
355 memset_t fn = r->fn.memset;
356 void *dst = NULL;
357 int i;
358
359 memset_alloc_mem(&dst, len);
360
361 if (prefault)
362 fn(dst, -1, len);
363
364 cycle_start = get_cycle();
365 for (i = 0; i < iterations; ++i)
366 fn(dst, i, len);
367 cycle_end = get_cycle();
368
369 free(dst);
370 return cycle_end - cycle_start;
371}
372
373static double do_memset_gettimeofday(const struct routine *r, size_t len,
374 bool prefault)
375{
376 struct timeval tv_start, tv_end, tv_diff;
377 memset_t fn = r->fn.memset;
378 void *dst = NULL;
379 int i;
380
381 memset_alloc_mem(&dst, len);
382
383 if (prefault)
384 fn(dst, -1, len);
385
386 BUG_ON(gettimeofday(&tv_start, NULL));
387 for (i = 0; i < iterations; ++i)
388 fn(dst, i, len);
389 BUG_ON(gettimeofday(&tv_end, NULL));
390
391 timersub(&tv_end, &tv_start, &tv_diff);
392
393 free(dst);
394 return (double)(((double)len * iterations) / timeval2double(&tv_diff));
395}
396
397static const char * const bench_mem_memset_usage[] = {
398 "perf bench mem memset <options>",
399 NULL
400};
401
402static const struct routine memset_routines[] = {
403 { .name ="default",
404 .desc = "Default memset() provided by glibc",
405 .fn.memset = memset },
406#ifdef HAVE_ARCH_X86_64_SUPPORT
407
408#define MEMSET_FN(_fn, _name, _desc) { .name = _name, .desc = _desc, .fn.memset = _fn },
409#include "mem-memset-x86-64-asm-def.h"
410#undef MEMSET_FN
411
412#endif
413
414 { .name = NULL,
415 .desc = NULL,
416 .fn.memset = NULL }
417};
418
419int bench_mem_memset(int argc, const char **argv,
420 const char *prefix __maybe_unused)
421{
422 struct bench_mem_info info = {
423 .routines = memset_routines,
424 .do_cycle = do_memset_cycle,
425 .do_gettimeofday = do_memset_gettimeofday,
426 .usage = bench_mem_memset_usage,
427 };
428
429 return bench_mem_common(argc, argv, prefix, &info);
430}
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
deleted file mode 100644
index 75fc3e65fb2a..000000000000
--- a/tools/perf/bench/mem-memset.c
+++ /dev/null
@@ -1,304 +0,0 @@
1/*
2 * mem-memset.c
3 *
4 * memset: Simple memory set in various ways
5 *
6 * Trivial clone of mem-memcpy.c.
7 */
8
9#include "../perf.h"
10#include "../util/util.h"
11#include "../util/parse-options.h"
12#include "../util/header.h"
13#include "../util/cloexec.h"
14#include "bench.h"
15#include "mem-memset-arch.h"
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/time.h>
21#include <errno.h>
22
23#define K 1024
24
25static const char *length_str = "1MB";
26static const char *routine = "default";
27static int iterations = 1;
28static bool use_cycle;
29static int cycle_fd;
30static bool only_prefault;
31static bool no_prefault;
32
33static const struct option options[] = {
34 OPT_STRING('l', "length", &length_str, "1MB",
35 "Specify length of memory to set. "
36 "Available units: B, KB, MB, GB and TB (upper and lower)"),
37 OPT_STRING('r', "routine", &routine, "default",
38 "Specify routine to set"),
39 OPT_INTEGER('i', "iterations", &iterations,
40 "repeat memset() invocation this number of times"),
41 OPT_BOOLEAN('c', "cycle", &use_cycle,
42 "Use cycles event instead of gettimeofday() for measuring"),
43 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
44 "Show only the result with page faults before memset()"),
45 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
46 "Show only the result without page faults before memset()"),
47 OPT_END()
48};
49
50typedef void *(*memset_t)(void *, int, size_t);
51
52struct routine {
53 const char *name;
54 const char *desc;
55 memset_t fn;
56};
57
58static const struct routine routines[] = {
59 { "default",
60 "Default memset() provided by glibc",
61 memset },
62#ifdef HAVE_ARCH_X86_64_SUPPORT
63
64#define MEMSET_FN(fn, name, desc) { name, desc, fn },
65#include "mem-memset-x86-64-asm-def.h"
66#undef MEMSET_FN
67
68#endif
69
70 { NULL,
71 NULL,
72 NULL }
73};
74
75static const char * const bench_mem_memset_usage[] = {
76 "perf bench mem memset <options>",
77 NULL
78};
79
80static struct perf_event_attr cycle_attr = {
81 .type = PERF_TYPE_HARDWARE,
82 .config = PERF_COUNT_HW_CPU_CYCLES
83};
84
85static void init_cycle(void)
86{
87 cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1,
88 perf_event_open_cloexec_flag());
89
90 if (cycle_fd < 0 && errno == ENOSYS)
91 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
92 else
93 BUG_ON(cycle_fd < 0);
94}
95
96static u64 get_cycle(void)
97{
98 int ret;
99 u64 clk;
100
101 ret = read(cycle_fd, &clk, sizeof(u64));
102 BUG_ON(ret != sizeof(u64));
103
104 return clk;
105}
106
107static double timeval2double(struct timeval *ts)
108{
109 return (double)ts->tv_sec +
110 (double)ts->tv_usec / (double)1000000;
111}
112
113static void alloc_mem(void **dst, size_t length)
114{
115 *dst = zalloc(length);
116 if (!*dst)
117 die("memory allocation failed - maybe length is too large?\n");
118}
119
120static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
121{
122 u64 cycle_start = 0ULL, cycle_end = 0ULL;
123 void *dst = NULL;
124 int i;
125
126 alloc_mem(&dst, len);
127
128 if (prefault)
129 fn(dst, -1, len);
130
131 cycle_start = get_cycle();
132 for (i = 0; i < iterations; ++i)
133 fn(dst, i, len);
134 cycle_end = get_cycle();
135
136 free(dst);
137 return cycle_end - cycle_start;
138}
139
140static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
141{
142 struct timeval tv_start, tv_end, tv_diff;
143 void *dst = NULL;
144 int i;
145
146 alloc_mem(&dst, len);
147
148 if (prefault)
149 fn(dst, -1, len);
150
151 BUG_ON(gettimeofday(&tv_start, NULL));
152 for (i = 0; i < iterations; ++i)
153 fn(dst, i, len);
154 BUG_ON(gettimeofday(&tv_end, NULL));
155
156 timersub(&tv_end, &tv_start, &tv_diff);
157
158 free(dst);
159 return (double)((double)len / timeval2double(&tv_diff));
160}
161
162#define pf (no_prefault ? 0 : 1)
163
164#define print_bps(x) do { \
165 if (x < K) \
166 printf(" %14lf B/Sec", x); \
167 else if (x < K * K) \
168 printf(" %14lfd KB/Sec", x / K); \
169 else if (x < K * K * K) \
170 printf(" %14lf MB/Sec", x / K / K); \
171 else \
172 printf(" %14lf GB/Sec", x / K / K / K); \
173 } while (0)
174
175int bench_mem_memset(int argc, const char **argv,
176 const char *prefix __maybe_unused)
177{
178 int i;
179 size_t len;
180 double result_bps[2];
181 u64 result_cycle[2];
182
183 argc = parse_options(argc, argv, options,
184 bench_mem_memset_usage, 0);
185
186 if (no_prefault && only_prefault) {
187 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
188 return 1;
189 }
190
191 if (use_cycle)
192 init_cycle();
193
194 len = (size_t)perf_atoll((char *)length_str);
195
196 result_cycle[0] = result_cycle[1] = 0ULL;
197 result_bps[0] = result_bps[1] = 0.0;
198
199 if ((s64)len <= 0) {
200 fprintf(stderr, "Invalid length:%s\n", length_str);
201 return 1;
202 }
203
204 /* same to without specifying either of prefault and no-prefault */
205 if (only_prefault && no_prefault)
206 only_prefault = no_prefault = false;
207
208 for (i = 0; routines[i].name; i++) {
209 if (!strcmp(routines[i].name, routine))
210 break;
211 }
212 if (!routines[i].name) {
213 printf("Unknown routine:%s\n", routine);
214 printf("Available routines...\n");
215 for (i = 0; routines[i].name; i++) {
216 printf("\t%s ... %s\n",
217 routines[i].name, routines[i].desc);
218 }
219 return 1;
220 }
221
222 if (bench_format == BENCH_FORMAT_DEFAULT)
223 printf("# Copying %s Bytes ...\n\n", length_str);
224
225 if (!only_prefault && !no_prefault) {
226 /* show both of results */
227 if (use_cycle) {
228 result_cycle[0] =
229 do_memset_cycle(routines[i].fn, len, false);
230 result_cycle[1] =
231 do_memset_cycle(routines[i].fn, len, true);
232 } else {
233 result_bps[0] =
234 do_memset_gettimeofday(routines[i].fn,
235 len, false);
236 result_bps[1] =
237 do_memset_gettimeofday(routines[i].fn,
238 len, true);
239 }
240 } else {
241 if (use_cycle) {
242 result_cycle[pf] =
243 do_memset_cycle(routines[i].fn,
244 len, only_prefault);
245 } else {
246 result_bps[pf] =
247 do_memset_gettimeofday(routines[i].fn,
248 len, only_prefault);
249 }
250 }
251
252 switch (bench_format) {
253 case BENCH_FORMAT_DEFAULT:
254 if (!only_prefault && !no_prefault) {
255 if (use_cycle) {
256 printf(" %14lf Cycle/Byte\n",
257 (double)result_cycle[0]
258 / (double)len);
259 printf(" %14lf Cycle/Byte (with prefault)\n ",
260 (double)result_cycle[1]
261 / (double)len);
262 } else {
263 print_bps(result_bps[0]);
264 printf("\n");
265 print_bps(result_bps[1]);
266 printf(" (with prefault)\n");
267 }
268 } else {
269 if (use_cycle) {
270 printf(" %14lf Cycle/Byte",
271 (double)result_cycle[pf]
272 / (double)len);
273 } else
274 print_bps(result_bps[pf]);
275
276 printf("%s\n", only_prefault ? " (with prefault)" : "");
277 }
278 break;
279 case BENCH_FORMAT_SIMPLE:
280 if (!only_prefault && !no_prefault) {
281 if (use_cycle) {
282 printf("%lf %lf\n",
283 (double)result_cycle[0] / (double)len,
284 (double)result_cycle[1] / (double)len);
285 } else {
286 printf("%lf %lf\n",
287 result_bps[0], result_bps[1]);
288 }
289 } else {
290 if (use_cycle) {
291 printf("%lf\n", (double)result_cycle[pf]
292 / (double)len);
293 } else
294 printf("%lf\n", result_bps[pf]);
295 }
296 break;
297 default:
298 /* reaching this means there's some disaster: */
299 die("unknown format: %d\n", bench_format);
300 break;
301 }
302
303 return 0;
304}
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index 52a56599a543..d7f281c2828d 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -26,7 +26,7 @@
26#include <sys/socket.h> 26#include <sys/socket.h>
27#include <sys/wait.h> 27#include <sys/wait.h>
28#include <sys/time.h> 28#include <sys/time.h>
29#include <sys/poll.h> 29#include <poll.h>
30#include <limits.h> 30#include <limits.h>
31#include <err.h> 31#include <err.h>
32 32
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 1ec429fef2be..747f86103599 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -36,7 +36,8 @@
36 36
37struct perf_annotate { 37struct perf_annotate {
38 struct perf_tool tool; 38 struct perf_tool tool;
39 bool force, use_tui, use_stdio, use_gtk; 39 struct perf_session *session;
40 bool use_tui, use_stdio, use_gtk;
40 bool full_paths; 41 bool full_paths;
41 bool print_line; 42 bool print_line;
42 bool skip_missing; 43 bool skip_missing;
@@ -50,6 +51,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
50 struct addr_location *al, 51 struct addr_location *al,
51 struct perf_annotate *ann) 52 struct perf_annotate *ann)
52{ 53{
54 struct hists *hists = evsel__hists(evsel);
53 struct hist_entry *he; 55 struct hist_entry *he;
54 int ret; 56 int ret;
55 57
@@ -65,13 +67,12 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
65 return 0; 67 return 0;
66 } 68 }
67 69
68 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0, 70 he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true);
69 true);
70 if (he == NULL) 71 if (he == NULL)
71 return -ENOMEM; 72 return -ENOMEM;
72 73
73 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 74 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
74 hists__inc_nr_samples(&evsel->hists, true); 75 hists__inc_nr_samples(hists, true);
75 return ret; 76 return ret;
76} 77}
77 78
@@ -188,18 +189,9 @@ find_next:
188static int __cmd_annotate(struct perf_annotate *ann) 189static int __cmd_annotate(struct perf_annotate *ann)
189{ 190{
190 int ret; 191 int ret;
191 struct perf_session *session; 192 struct perf_session *session = ann->session;
192 struct perf_evsel *pos; 193 struct perf_evsel *pos;
193 u64 total_nr_samples; 194 u64 total_nr_samples;
194 struct perf_data_file file = {
195 .path = input_name,
196 .mode = PERF_DATA_MODE_READ,
197 .force = ann->force,
198 };
199
200 session = perf_session__new(&file, false, &ann->tool);
201 if (session == NULL)
202 return -ENOMEM;
203 195
204 machines__set_symbol_filter(&session->machines, symbol__annotate_init); 196 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
205 197
@@ -207,22 +199,23 @@ static int __cmd_annotate(struct perf_annotate *ann)
207 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 199 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
208 ann->cpu_bitmap); 200 ann->cpu_bitmap);
209 if (ret) 201 if (ret)
210 goto out_delete; 202 goto out;
211 } 203 }
212 204
213 if (!objdump_path) { 205 if (!objdump_path) {
214 ret = perf_session_env__lookup_objdump(&session->header.env); 206 ret = perf_session_env__lookup_objdump(&session->header.env);
215 if (ret) 207 if (ret)
216 goto out_delete; 208 goto out;
217 } 209 }
218 210
219 ret = perf_session__process_events(session, &ann->tool); 211 ret = perf_session__process_events(session, &ann->tool);
220 if (ret) 212 if (ret)
221 goto out_delete; 213 goto out;
222 214
223 if (dump_trace) { 215 if (dump_trace) {
224 perf_session__fprintf_nr_events(session, stdout); 216 perf_session__fprintf_nr_events(session, stdout);
225 goto out_delete; 217 perf_evlist__fprintf_nr_events(session->evlist, stdout);
218 goto out;
226 } 219 }
227 220
228 if (verbose > 3) 221 if (verbose > 3)
@@ -233,13 +226,13 @@ static int __cmd_annotate(struct perf_annotate *ann)
233 226
234 total_nr_samples = 0; 227 total_nr_samples = 0;
235 evlist__for_each(session->evlist, pos) { 228 evlist__for_each(session->evlist, pos) {
236 struct hists *hists = &pos->hists; 229 struct hists *hists = evsel__hists(pos);
237 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 230 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
238 231
239 if (nr_samples > 0) { 232 if (nr_samples > 0) {
240 total_nr_samples += nr_samples; 233 total_nr_samples += nr_samples;
241 hists__collapse_resort(hists, NULL); 234 hists__collapse_resort(hists, NULL);
242 hists__output_resort(hists); 235 hists__output_resort(hists, NULL);
243 236
244 if (symbol_conf.event_group && 237 if (symbol_conf.event_group &&
245 !perf_evsel__is_group_leader(pos)) 238 !perf_evsel__is_group_leader(pos))
@@ -250,8 +243,8 @@ static int __cmd_annotate(struct perf_annotate *ann)
250 } 243 }
251 244
252 if (total_nr_samples == 0) { 245 if (total_nr_samples == 0) {
253 ui__error("The %s file has no samples!\n", file.path); 246 ui__error("The %s file has no samples!\n", session->file->path);
254 goto out_delete; 247 goto out;
255 } 248 }
256 249
257 if (use_browser == 2) { 250 if (use_browser == 2) {
@@ -261,24 +254,12 @@ static int __cmd_annotate(struct perf_annotate *ann)
261 "perf_gtk__show_annotations"); 254 "perf_gtk__show_annotations");
262 if (show_annotations == NULL) { 255 if (show_annotations == NULL) {
263 ui__error("GTK browser not found!\n"); 256 ui__error("GTK browser not found!\n");
264 goto out_delete; 257 goto out;
265 } 258 }
266 show_annotations(); 259 show_annotations();
267 } 260 }
268 261
269out_delete: 262out:
270 /*
271 * Speed up the exit process, for large files this can
272 * take quite a while.
273 *
274 * XXX Enable this when using valgrind or if we ever
275 * librarize this command.
276 *
277 * Also experiment with obstacks to see how much speed
278 * up we'll get here.
279 *
280 * perf_session__delete(session);
281 */
282 return ret; 263 return ret;
283} 264}
284 265
@@ -297,10 +278,14 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
297 .comm = perf_event__process_comm, 278 .comm = perf_event__process_comm,
298 .exit = perf_event__process_exit, 279 .exit = perf_event__process_exit,
299 .fork = perf_event__process_fork, 280 .fork = perf_event__process_fork,
300 .ordered_samples = true, 281 .ordered_events = true,
301 .ordering_requires_timestamps = true, 282 .ordering_requires_timestamps = true,
302 }, 283 },
303 }; 284 };
285 struct perf_data_file file = {
286 .path = input_name,
287 .mode = PERF_DATA_MODE_READ,
288 };
304 const struct option options[] = { 289 const struct option options[] = {
305 OPT_STRING('i', "input", &input_name, "file", 290 OPT_STRING('i', "input", &input_name, "file",
306 "input file name"), 291 "input file name"),
@@ -308,7 +293,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
308 "only consider symbols in these dsos"), 293 "only consider symbols in these dsos"),
309 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", 294 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
310 "symbol to annotate"), 295 "symbol to annotate"),
311 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"), 296 OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"),
312 OPT_INCR('v', "verbose", &verbose, 297 OPT_INCR('v', "verbose", &verbose,
313 "be more verbose (show symbol address, etc)"), 298 "be more verbose (show symbol address, etc)"),
314 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 299 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
@@ -341,6 +326,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
341 "Show event group information together"), 326 "Show event group information together"),
342 OPT_END() 327 OPT_END()
343 }; 328 };
329 int ret = hists__init();
330
331 if (ret < 0)
332 return ret;
344 333
345 argc = parse_options(argc, argv, options, annotate_usage, 0); 334 argc = parse_options(argc, argv, options, annotate_usage, 0);
346 335
@@ -353,11 +342,16 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
353 342
354 setup_browser(true); 343 setup_browser(true);
355 344
345 annotate.session = perf_session__new(&file, false, &annotate.tool);
346 if (annotate.session == NULL)
347 return -1;
348
356 symbol_conf.priv_size = sizeof(struct annotation); 349 symbol_conf.priv_size = sizeof(struct annotation);
357 symbol_conf.try_vmlinux_path = true; 350 symbol_conf.try_vmlinux_path = true;
358 351
359 if (symbol__init() < 0) 352 ret = symbol__init(&annotate.session->header.env);
360 return -1; 353 if (ret < 0)
354 goto out_delete;
361 355
362 if (setup_sorting() < 0) 356 if (setup_sorting() < 0)
363 usage_with_options(annotate_usage, options); 357 usage_with_options(annotate_usage, options);
@@ -373,5 +367,20 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
373 annotate.sym_hist_filter = argv[0]; 367 annotate.sym_hist_filter = argv[0];
374 } 368 }
375 369
376 return __cmd_annotate(&annotate); 370 ret = __cmd_annotate(&annotate);
371
372out_delete:
373 /*
374 * Speed up the exit process, for large files this can
375 * take quite a while.
376 *
377 * XXX Enable this when using valgrind or if we ever
378 * librarize this command.
379 *
380 * Also experiment with obstacks to see how much speed
381 * up we'll get here.
382 *
383 * perf_session__delete(session);
384 */
385 return ret;
377} 386}
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 2a2c78f80876..77d5cae54c6a 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -246,20 +246,9 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
246 return true; 246 return true;
247} 247}
248 248
249static int build_id_cache__fprintf_missing(const char *filename, bool force, FILE *fp) 249static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *fp)
250{ 250{
251 struct perf_data_file file = {
252 .path = filename,
253 .mode = PERF_DATA_MODE_READ,
254 .force = force,
255 };
256 struct perf_session *session = perf_session__new(&file, false, NULL);
257 if (session == NULL)
258 return -1;
259
260 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0); 251 perf_session__fprintf_dsos_buildid(session, fp, dso__missing_buildid_cache, 0);
261 perf_session__delete(session);
262
263 return 0; 252 return 0;
264} 253}
265 254
@@ -296,12 +285,17 @@ int cmd_buildid_cache(int argc, const char **argv,
296 struct str_node *pos; 285 struct str_node *pos;
297 int ret = 0; 286 int ret = 0;
298 bool force = false; 287 bool force = false;
299 char debugdir[PATH_MAX];
300 char const *add_name_list_str = NULL, 288 char const *add_name_list_str = NULL,
301 *remove_name_list_str = NULL, 289 *remove_name_list_str = NULL,
302 *missing_filename = NULL, 290 *missing_filename = NULL,
303 *update_name_list_str = NULL, 291 *update_name_list_str = NULL,
304 *kcore_filename; 292 *kcore_filename = NULL;
293 char sbuf[STRERR_BUFSIZE];
294
295 struct perf_data_file file = {
296 .mode = PERF_DATA_MODE_READ,
297 };
298 struct perf_session *session = NULL;
305 299
306 const struct option buildid_cache_options[] = { 300 const struct option buildid_cache_options[] = {
307 OPT_STRING('a', "add", &add_name_list_str, 301 OPT_STRING('a', "add", &add_name_list_str,
@@ -326,25 +320,32 @@ int cmd_buildid_cache(int argc, const char **argv,
326 argc = parse_options(argc, argv, buildid_cache_options, 320 argc = parse_options(argc, argv, buildid_cache_options,
327 buildid_cache_usage, 0); 321 buildid_cache_usage, 0);
328 322
329 if (symbol__init() < 0) 323 if (missing_filename) {
330 return -1; 324 file.path = missing_filename;
325 file.force = force;
331 326
332 setup_pager(); 327 session = perf_session__new(&file, false, NULL);
328 if (session == NULL)
329 return -1;
330 }
331
332 if (symbol__init(session ? &session->header.env : NULL) < 0)
333 goto out;
333 334
334 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir); 335 setup_pager();
335 336
336 if (add_name_list_str) { 337 if (add_name_list_str) {
337 list = strlist__new(true, add_name_list_str); 338 list = strlist__new(true, add_name_list_str);
338 if (list) { 339 if (list) {
339 strlist__for_each(pos, list) 340 strlist__for_each(pos, list)
340 if (build_id_cache__add_file(pos->s, debugdir)) { 341 if (build_id_cache__add_file(pos->s, buildid_dir)) {
341 if (errno == EEXIST) { 342 if (errno == EEXIST) {
342 pr_debug("%s already in the cache\n", 343 pr_debug("%s already in the cache\n",
343 pos->s); 344 pos->s);
344 continue; 345 continue;
345 } 346 }
346 pr_warning("Couldn't add %s: %s\n", 347 pr_warning("Couldn't add %s: %s\n",
347 pos->s, strerror(errno)); 348 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
348 } 349 }
349 350
350 strlist__delete(list); 351 strlist__delete(list);
@@ -355,14 +356,14 @@ int cmd_buildid_cache(int argc, const char **argv,
355 list = strlist__new(true, remove_name_list_str); 356 list = strlist__new(true, remove_name_list_str);
356 if (list) { 357 if (list) {
357 strlist__for_each(pos, list) 358 strlist__for_each(pos, list)
358 if (build_id_cache__remove_file(pos->s, debugdir)) { 359 if (build_id_cache__remove_file(pos->s, buildid_dir)) {
359 if (errno == ENOENT) { 360 if (errno == ENOENT) {
360 pr_debug("%s wasn't in the cache\n", 361 pr_debug("%s wasn't in the cache\n",
361 pos->s); 362 pos->s);
362 continue; 363 continue;
363 } 364 }
364 pr_warning("Couldn't remove %s: %s\n", 365 pr_warning("Couldn't remove %s: %s\n",
365 pos->s, strerror(errno)); 366 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
366 } 367 }
367 368
368 strlist__delete(list); 369 strlist__delete(list);
@@ -370,20 +371,20 @@ int cmd_buildid_cache(int argc, const char **argv,
370 } 371 }
371 372
372 if (missing_filename) 373 if (missing_filename)
373 ret = build_id_cache__fprintf_missing(missing_filename, force, stdout); 374 ret = build_id_cache__fprintf_missing(session, stdout);
374 375
375 if (update_name_list_str) { 376 if (update_name_list_str) {
376 list = strlist__new(true, update_name_list_str); 377 list = strlist__new(true, update_name_list_str);
377 if (list) { 378 if (list) {
378 strlist__for_each(pos, list) 379 strlist__for_each(pos, list)
379 if (build_id_cache__update_file(pos->s, debugdir)) { 380 if (build_id_cache__update_file(pos->s, buildid_dir)) {
380 if (errno == ENOENT) { 381 if (errno == ENOENT) {
381 pr_debug("%s wasn't in the cache\n", 382 pr_debug("%s wasn't in the cache\n",
382 pos->s); 383 pos->s);
383 continue; 384 continue;
384 } 385 }
385 pr_warning("Couldn't update %s: %s\n", 386 pr_warning("Couldn't update %s: %s\n",
386 pos->s, strerror(errno)); 387 pos->s, strerror_r(errno, sbuf, sizeof(sbuf)));
387 } 388 }
388 389
389 strlist__delete(list); 390 strlist__delete(list);
@@ -391,8 +392,12 @@ int cmd_buildid_cache(int argc, const char **argv,
391 } 392 }
392 393
393 if (kcore_filename && 394 if (kcore_filename &&
394 build_id_cache__add_kcore(kcore_filename, debugdir, force)) 395 build_id_cache__add_kcore(kcore_filename, buildid_dir, force))
395 pr_warning("Couldn't add %s\n", kcore_filename); 396 pr_warning("Couldn't add %s\n", kcore_filename);
396 397
398out:
399 if (session)
400 perf_session__delete(session);
401
397 return ret; 402 return ret;
398} 403}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 9a5a035cb426..1fd96c13f199 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -327,6 +327,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
327 struct machine *machine) 327 struct machine *machine)
328{ 328{
329 struct addr_location al; 329 struct addr_location al;
330 struct hists *hists = evsel__hists(evsel);
330 331
331 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 332 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
332 pr_warning("problem processing %d event, skipping it.\n", 333 pr_warning("problem processing %d event, skipping it.\n",
@@ -334,7 +335,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
334 return -1; 335 return -1;
335 } 336 }
336 337
337 if (hists__add_entry(&evsel->hists, &al, sample->period, 338 if (hists__add_entry(hists, &al, sample->period,
338 sample->weight, sample->transaction)) { 339 sample->weight, sample->transaction)) {
339 pr_warning("problem incrementing symbol period, skipping event\n"); 340 pr_warning("problem incrementing symbol period, skipping event\n");
340 return -1; 341 return -1;
@@ -346,9 +347,9 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
346 * hists__output_resort() and precompute needs the total 347 * hists__output_resort() and precompute needs the total
347 * period in order to sort entries by percentage delta. 348 * period in order to sort entries by percentage delta.
348 */ 349 */
349 evsel->hists.stats.total_period += sample->period; 350 hists->stats.total_period += sample->period;
350 if (!al.filtered) 351 if (!al.filtered)
351 evsel->hists.stats.total_non_filtered_period += sample->period; 352 hists->stats.total_non_filtered_period += sample->period;
352 353
353 return 0; 354 return 0;
354} 355}
@@ -356,11 +357,12 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
356static struct perf_tool tool = { 357static struct perf_tool tool = {
357 .sample = diff__process_sample_event, 358 .sample = diff__process_sample_event,
358 .mmap = perf_event__process_mmap, 359 .mmap = perf_event__process_mmap,
360 .mmap2 = perf_event__process_mmap2,
359 .comm = perf_event__process_comm, 361 .comm = perf_event__process_comm,
360 .exit = perf_event__process_exit, 362 .exit = perf_event__process_exit,
361 .fork = perf_event__process_fork, 363 .fork = perf_event__process_fork,
362 .lost = perf_event__process_lost, 364 .lost = perf_event__process_lost,
363 .ordered_samples = true, 365 .ordered_events = true,
364 .ordering_requires_timestamps = true, 366 .ordering_requires_timestamps = true,
365}; 367};
366 368
@@ -382,7 +384,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
382 struct perf_evsel *evsel; 384 struct perf_evsel *evsel;
383 385
384 evlist__for_each(evlist, evsel) { 386 evlist__for_each(evlist, evsel) {
385 struct hists *hists = &evsel->hists; 387 struct hists *hists = evsel__hists(evsel);
386 388
387 hists__collapse_resort(hists, NULL); 389 hists__collapse_resort(hists, NULL);
388 } 390 }
@@ -543,6 +545,42 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
543 return __hist_entry__cmp_compute(p_left, p_right, c); 545 return __hist_entry__cmp_compute(p_left, p_right, c);
544} 546}
545 547
548static int64_t
549hist_entry__cmp_nop(struct hist_entry *left __maybe_unused,
550 struct hist_entry *right __maybe_unused)
551{
552 return 0;
553}
554
555static int64_t
556hist_entry__cmp_baseline(struct hist_entry *left, struct hist_entry *right)
557{
558 if (sort_compute)
559 return 0;
560
561 if (left->stat.period == right->stat.period)
562 return 0;
563 return left->stat.period > right->stat.period ? 1 : -1;
564}
565
566static int64_t
567hist_entry__cmp_delta(struct hist_entry *left, struct hist_entry *right)
568{
569 return hist_entry__cmp_compute(right, left, COMPUTE_DELTA);
570}
571
572static int64_t
573hist_entry__cmp_ratio(struct hist_entry *left, struct hist_entry *right)
574{
575 return hist_entry__cmp_compute(right, left, COMPUTE_RATIO);
576}
577
578static int64_t
579hist_entry__cmp_wdiff(struct hist_entry *left, struct hist_entry *right)
580{
581 return hist_entry__cmp_compute(right, left, COMPUTE_WEIGHTED_DIFF);
582}
583
546static void insert_hist_entry_by_compute(struct rb_root *root, 584static void insert_hist_entry_by_compute(struct rb_root *root,
547 struct hist_entry *he, 585 struct hist_entry *he,
548 int c) 586 int c)
@@ -603,7 +641,7 @@ static void hists__process(struct hists *hists)
603 hists__precompute(hists); 641 hists__precompute(hists);
604 hists__compute_resort(hists); 642 hists__compute_resort(hists);
605 } else { 643 } else {
606 hists__output_resort(hists); 644 hists__output_resort(hists, NULL);
607 } 645 }
608 646
609 hists__fprintf(hists, true, 0, 0, 0, stdout); 647 hists__fprintf(hists, true, 0, 0, 0, stdout);
@@ -631,24 +669,26 @@ static void data_process(void)
631 bool first = true; 669 bool first = true;
632 670
633 evlist__for_each(evlist_base, evsel_base) { 671 evlist__for_each(evlist_base, evsel_base) {
672 struct hists *hists_base = evsel__hists(evsel_base);
634 struct data__file *d; 673 struct data__file *d;
635 int i; 674 int i;
636 675
637 data__for_each_file_new(i, d) { 676 data__for_each_file_new(i, d) {
638 struct perf_evlist *evlist = d->session->evlist; 677 struct perf_evlist *evlist = d->session->evlist;
639 struct perf_evsel *evsel; 678 struct perf_evsel *evsel;
679 struct hists *hists;
640 680
641 evsel = evsel_match(evsel_base, evlist); 681 evsel = evsel_match(evsel_base, evlist);
642 if (!evsel) 682 if (!evsel)
643 continue; 683 continue;
644 684
645 d->hists = &evsel->hists; 685 hists = evsel__hists(evsel);
686 d->hists = hists;
646 687
647 hists__match(&evsel_base->hists, &evsel->hists); 688 hists__match(hists_base, hists);
648 689
649 if (!show_baseline_only) 690 if (!show_baseline_only)
650 hists__link(&evsel_base->hists, 691 hists__link(hists_base, hists);
651 &evsel->hists);
652 } 692 }
653 693
654 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", 694 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
@@ -659,7 +699,7 @@ static void data_process(void)
659 if (verbose || data__files_cnt > 2) 699 if (verbose || data__files_cnt > 2)
660 data__fprintf(); 700 data__fprintf();
661 701
662 hists__process(&evsel_base->hists); 702 hists__process(hists_base);
663 } 703 }
664} 704}
665 705
@@ -683,7 +723,7 @@ static int __cmd_diff(void)
683 d->session = perf_session__new(&d->file, false, &tool); 723 d->session = perf_session__new(&d->file, false, &tool);
684 if (!d->session) { 724 if (!d->session) {
685 pr_err("Failed to open %s\n", d->file.path); 725 pr_err("Failed to open %s\n", d->file.path);
686 ret = -ENOMEM; 726 ret = -1;
687 goto out_delete; 727 goto out_delete;
688 } 728 }
689 729
@@ -1034,27 +1074,35 @@ static void data__hpp_register(struct data__file *d, int idx)
1034 fmt->header = hpp__header; 1074 fmt->header = hpp__header;
1035 fmt->width = hpp__width; 1075 fmt->width = hpp__width;
1036 fmt->entry = hpp__entry_global; 1076 fmt->entry = hpp__entry_global;
1077 fmt->cmp = hist_entry__cmp_nop;
1078 fmt->collapse = hist_entry__cmp_nop;
1037 1079
1038 /* TODO more colors */ 1080 /* TODO more colors */
1039 switch (idx) { 1081 switch (idx) {
1040 case PERF_HPP_DIFF__BASELINE: 1082 case PERF_HPP_DIFF__BASELINE:
1041 fmt->color = hpp__color_baseline; 1083 fmt->color = hpp__color_baseline;
1084 fmt->sort = hist_entry__cmp_baseline;
1042 break; 1085 break;
1043 case PERF_HPP_DIFF__DELTA: 1086 case PERF_HPP_DIFF__DELTA:
1044 fmt->color = hpp__color_delta; 1087 fmt->color = hpp__color_delta;
1088 fmt->sort = hist_entry__cmp_delta;
1045 break; 1089 break;
1046 case PERF_HPP_DIFF__RATIO: 1090 case PERF_HPP_DIFF__RATIO:
1047 fmt->color = hpp__color_ratio; 1091 fmt->color = hpp__color_ratio;
1092 fmt->sort = hist_entry__cmp_ratio;
1048 break; 1093 break;
1049 case PERF_HPP_DIFF__WEIGHTED_DIFF: 1094 case PERF_HPP_DIFF__WEIGHTED_DIFF:
1050 fmt->color = hpp__color_wdiff; 1095 fmt->color = hpp__color_wdiff;
1096 fmt->sort = hist_entry__cmp_wdiff;
1051 break; 1097 break;
1052 default: 1098 default:
1099 fmt->sort = hist_entry__cmp_nop;
1053 break; 1100 break;
1054 } 1101 }
1055 1102
1056 init_header(d, dfmt); 1103 init_header(d, dfmt);
1057 perf_hpp__column_register(fmt); 1104 perf_hpp__column_register(fmt);
1105 perf_hpp__register_sort_field(fmt);
1058} 1106}
1059 1107
1060static void ui_init(void) 1108static void ui_init(void)
@@ -1139,11 +1187,16 @@ static int data_init(int argc, const char **argv)
1139 1187
1140int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) 1188int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
1141{ 1189{
1190 int ret = hists__init();
1191
1192 if (ret < 0)
1193 return ret;
1194
1142 perf_config(perf_default_config, NULL); 1195 perf_config(perf_default_config, NULL);
1143 1196
1144 argc = parse_options(argc, argv, options, diff_usage, 0); 1197 argc = parse_options(argc, argv, options, diff_usage, 0);
1145 1198
1146 if (symbol__init() < 0) 1199 if (symbol__init(NULL) < 0)
1147 return -1; 1200 return -1;
1148 1201
1149 if (data_init(argc, argv) < 0) 1202 if (data_init(argc, argv) < 0)
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 66e12f55c052..0f93f859b782 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -28,7 +28,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
28 28
29 session = perf_session__new(&file, 0, NULL); 29 session = perf_session__new(&file, 0, NULL);
30 if (session == NULL) 30 if (session == NULL)
31 return -ENOMEM; 31 return -1;
32 32
33 evlist__for_each(session->evlist, pos) 33 evlist__for_each(session->evlist, pos)
34 perf_evsel__fprintf(pos, details, stdout); 34 perf_evsel__fprintf(pos, details, stdout);
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index 0384d930480b..25d20628212e 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -103,6 +103,8 @@ static int check_emacsclient_version(void)
103 103
104static void exec_woman_emacs(const char *path, const char *page) 104static void exec_woman_emacs(const char *path, const char *page)
105{ 105{
106 char sbuf[STRERR_BUFSIZE];
107
106 if (!check_emacsclient_version()) { 108 if (!check_emacsclient_version()) {
107 /* This works only with emacsclient version >= 22. */ 109 /* This works only with emacsclient version >= 22. */
108 struct strbuf man_page = STRBUF_INIT; 110 struct strbuf man_page = STRBUF_INIT;
@@ -111,16 +113,19 @@ static void exec_woman_emacs(const char *path, const char *page)
111 path = "emacsclient"; 113 path = "emacsclient";
112 strbuf_addf(&man_page, "(woman \"%s\")", page); 114 strbuf_addf(&man_page, "(woman \"%s\")", page);
113 execlp(path, "emacsclient", "-e", man_page.buf, NULL); 115 execlp(path, "emacsclient", "-e", man_page.buf, NULL);
114 warning("failed to exec '%s': %s", path, strerror(errno)); 116 warning("failed to exec '%s': %s", path,
117 strerror_r(errno, sbuf, sizeof(sbuf)));
115 } 118 }
116} 119}
117 120
118static void exec_man_konqueror(const char *path, const char *page) 121static void exec_man_konqueror(const char *path, const char *page)
119{ 122{
120 const char *display = getenv("DISPLAY"); 123 const char *display = getenv("DISPLAY");
124
121 if (display && *display) { 125 if (display && *display) {
122 struct strbuf man_page = STRBUF_INIT; 126 struct strbuf man_page = STRBUF_INIT;
123 const char *filename = "kfmclient"; 127 const char *filename = "kfmclient";
128 char sbuf[STRERR_BUFSIZE];
124 129
125 /* It's simpler to launch konqueror using kfmclient. */ 130 /* It's simpler to launch konqueror using kfmclient. */
126 if (path) { 131 if (path) {
@@ -139,24 +144,31 @@ static void exec_man_konqueror(const char *path, const char *page)
139 path = "kfmclient"; 144 path = "kfmclient";
140 strbuf_addf(&man_page, "man:%s(1)", page); 145 strbuf_addf(&man_page, "man:%s(1)", page);
141 execlp(path, filename, "newTab", man_page.buf, NULL); 146 execlp(path, filename, "newTab", man_page.buf, NULL);
142 warning("failed to exec '%s': %s", path, strerror(errno)); 147 warning("failed to exec '%s': %s", path,
148 strerror_r(errno, sbuf, sizeof(sbuf)));
143 } 149 }
144} 150}
145 151
146static void exec_man_man(const char *path, const char *page) 152static void exec_man_man(const char *path, const char *page)
147{ 153{
154 char sbuf[STRERR_BUFSIZE];
155
148 if (!path) 156 if (!path)
149 path = "man"; 157 path = "man";
150 execlp(path, "man", page, NULL); 158 execlp(path, "man", page, NULL);
151 warning("failed to exec '%s': %s", path, strerror(errno)); 159 warning("failed to exec '%s': %s", path,
160 strerror_r(errno, sbuf, sizeof(sbuf)));
152} 161}
153 162
154static void exec_man_cmd(const char *cmd, const char *page) 163static void exec_man_cmd(const char *cmd, const char *page)
155{ 164{
156 struct strbuf shell_cmd = STRBUF_INIT; 165 struct strbuf shell_cmd = STRBUF_INIT;
166 char sbuf[STRERR_BUFSIZE];
167
157 strbuf_addf(&shell_cmd, "%s %s", cmd, page); 168 strbuf_addf(&shell_cmd, "%s %s", cmd, page);
158 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); 169 execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL);
159 warning("failed to exec '%s': %s", cmd, strerror(errno)); 170 warning("failed to exec '%s': %s", cmd,
171 strerror_r(errno, sbuf, sizeof(sbuf)));
160} 172}
161 173
162static void add_man_viewer(const char *name) 174static void add_man_viewer(const char *name)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 9a02807387d6..84df2deed988 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -23,6 +23,7 @@
23 23
24struct perf_inject { 24struct perf_inject {
25 struct perf_tool tool; 25 struct perf_tool tool;
26 struct perf_session *session;
26 bool build_ids; 27 bool build_ids;
27 bool sched_stat; 28 bool sched_stat;
28 const char *input_name; 29 const char *input_name;
@@ -216,8 +217,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
216 goto repipe; 217 goto repipe;
217 } 218 }
218 219
219 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 220 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
220 sample->ip, &al);
221 221
222 if (al.map != NULL) { 222 if (al.map != NULL) {
223 if (!al.map->dso->hit) { 223 if (!al.map->dso->hit) {
@@ -340,12 +340,8 @@ static int perf_evsel__check_stype(struct perf_evsel *evsel,
340 340
341static int __cmd_inject(struct perf_inject *inject) 341static int __cmd_inject(struct perf_inject *inject)
342{ 342{
343 struct perf_session *session;
344 int ret = -EINVAL; 343 int ret = -EINVAL;
345 struct perf_data_file file = { 344 struct perf_session *session = inject->session;
346 .path = inject->input_name,
347 .mode = PERF_DATA_MODE_READ,
348 };
349 struct perf_data_file *file_out = &inject->output; 345 struct perf_data_file *file_out = &inject->output;
350 346
351 signal(SIGINT, sig_handler); 347 signal(SIGINT, sig_handler);
@@ -357,16 +353,12 @@ static int __cmd_inject(struct perf_inject *inject)
357 inject->tool.tracing_data = perf_event__repipe_tracing_data; 353 inject->tool.tracing_data = perf_event__repipe_tracing_data;
358 } 354 }
359 355
360 session = perf_session__new(&file, true, &inject->tool);
361 if (session == NULL)
362 return -ENOMEM;
363
364 if (inject->build_ids) { 356 if (inject->build_ids) {
365 inject->tool.sample = perf_event__inject_buildid; 357 inject->tool.sample = perf_event__inject_buildid;
366 } else if (inject->sched_stat) { 358 } else if (inject->sched_stat) {
367 struct perf_evsel *evsel; 359 struct perf_evsel *evsel;
368 360
369 inject->tool.ordered_samples = true; 361 inject->tool.ordered_events = true;
370 362
371 evlist__for_each(session->evlist, evsel) { 363 evlist__for_each(session->evlist, evsel) {
372 const char *name = perf_evsel__name(evsel); 364 const char *name = perf_evsel__name(evsel);
@@ -396,8 +388,6 @@ static int __cmd_inject(struct perf_inject *inject)
396 perf_session__write_header(session, session->evlist, file_out->fd, true); 388 perf_session__write_header(session, session->evlist, file_out->fd, true);
397 } 389 }
398 390
399 perf_session__delete(session);
400
401 return ret; 391 return ret;
402} 392}
403 393
@@ -419,6 +409,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
419 .tracing_data = perf_event__repipe_op2_synth, 409 .tracing_data = perf_event__repipe_op2_synth,
420 .finished_round = perf_event__repipe_op2_synth, 410 .finished_round = perf_event__repipe_op2_synth,
421 .build_id = perf_event__repipe_op2_synth, 411 .build_id = perf_event__repipe_op2_synth,
412 .id_index = perf_event__repipe_op2_synth,
422 }, 413 },
423 .input_name = "-", 414 .input_name = "-",
424 .samples = LIST_HEAD_INIT(inject.samples), 415 .samples = LIST_HEAD_INIT(inject.samples),
@@ -427,6 +418,11 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
427 .mode = PERF_DATA_MODE_WRITE, 418 .mode = PERF_DATA_MODE_WRITE,
428 }, 419 },
429 }; 420 };
421 struct perf_data_file file = {
422 .mode = PERF_DATA_MODE_READ,
423 };
424 int ret;
425
430 const struct option options[] = { 426 const struct option options[] = {
431 OPT_BOOLEAN('b', "build-ids", &inject.build_ids, 427 OPT_BOOLEAN('b', "build-ids", &inject.build_ids,
432 "Inject build-ids into the output stream"), 428 "Inject build-ids into the output stream"),
@@ -461,8 +457,17 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
461 return -1; 457 return -1;
462 } 458 }
463 459
464 if (symbol__init() < 0) 460 file.path = inject.input_name;
461 inject.session = perf_session__new(&file, true, &inject.tool);
462 if (inject.session == NULL)
463 return -1;
464
465 if (symbol__init(&inject.session->header.env) < 0)
465 return -1; 466 return -1;
466 467
467 return __cmd_inject(&inject); 468 ret = __cmd_inject(&inject);
469
470 perf_session__delete(inject.session);
471
472 return ret;
468} 473}
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index bef3376bfaf3..f295141025bc 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -256,7 +256,9 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
256static struct perf_tool perf_kmem = { 256static struct perf_tool perf_kmem = {
257 .sample = process_sample_event, 257 .sample = process_sample_event,
258 .comm = perf_event__process_comm, 258 .comm = perf_event__process_comm,
259 .ordered_samples = true, 259 .mmap = perf_event__process_mmap,
260 .mmap2 = perf_event__process_mmap2,
261 .ordered_events = true,
260}; 262};
261 263
262static double fragmentation(unsigned long n_req, unsigned long n_alloc) 264static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -403,10 +405,9 @@ static void sort_result(void)
403 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 405 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
404} 406}
405 407
406static int __cmd_kmem(void) 408static int __cmd_kmem(struct perf_session *session)
407{ 409{
408 int err = -EINVAL; 410 int err = -EINVAL;
409 struct perf_session *session;
410 const struct perf_evsel_str_handler kmem_tracepoints[] = { 411 const struct perf_evsel_str_handler kmem_tracepoints[] = {
411 { "kmem:kmalloc", perf_evsel__process_alloc_event, }, 412 { "kmem:kmalloc", perf_evsel__process_alloc_event, },
412 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, }, 413 { "kmem:kmem_cache_alloc", perf_evsel__process_alloc_event, },
@@ -415,34 +416,22 @@ static int __cmd_kmem(void)
415 { "kmem:kfree", perf_evsel__process_free_event, }, 416 { "kmem:kfree", perf_evsel__process_free_event, },
416 { "kmem:kmem_cache_free", perf_evsel__process_free_event, }, 417 { "kmem:kmem_cache_free", perf_evsel__process_free_event, },
417 }; 418 };
418 struct perf_data_file file = {
419 .path = input_name,
420 .mode = PERF_DATA_MODE_READ,
421 };
422
423 session = perf_session__new(&file, false, &perf_kmem);
424 if (session == NULL)
425 return -ENOMEM;
426
427 if (perf_session__create_kernel_maps(session) < 0)
428 goto out_delete;
429 419
430 if (!perf_session__has_traces(session, "kmem record")) 420 if (!perf_session__has_traces(session, "kmem record"))
431 goto out_delete; 421 goto out;
432 422
433 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) { 423 if (perf_session__set_tracepoints_handlers(session, kmem_tracepoints)) {
434 pr_err("Initializing perf session tracepoint handlers failed\n"); 424 pr_err("Initializing perf session tracepoint handlers failed\n");
435 return -1; 425 goto out;
436 } 426 }
437 427
438 setup_pager(); 428 setup_pager();
439 err = perf_session__process_events(session, &perf_kmem); 429 err = perf_session__process_events(session, &perf_kmem);
440 if (err != 0) 430 if (err != 0)
441 goto out_delete; 431 goto out;
442 sort_result(); 432 sort_result();
443 print_result(session); 433 print_result(session);
444out_delete: 434out:
445 perf_session__delete(session);
446 return err; 435 return err;
447} 436}
448 437
@@ -689,29 +678,46 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
689 NULL, 678 NULL,
690 NULL 679 NULL
691 }; 680 };
681 struct perf_session *session;
682 struct perf_data_file file = {
683 .path = input_name,
684 .mode = PERF_DATA_MODE_READ,
685 };
686 int ret = -1;
687
692 argc = parse_options_subcommand(argc, argv, kmem_options, 688 argc = parse_options_subcommand(argc, argv, kmem_options,
693 kmem_subcommands, kmem_usage, 0); 689 kmem_subcommands, kmem_usage, 0);
694 690
695 if (!argc) 691 if (!argc)
696 usage_with_options(kmem_usage, kmem_options); 692 usage_with_options(kmem_usage, kmem_options);
697 693
698 symbol__init();
699
700 if (!strncmp(argv[0], "rec", 3)) { 694 if (!strncmp(argv[0], "rec", 3)) {
695 symbol__init(NULL);
701 return __cmd_record(argc, argv); 696 return __cmd_record(argc, argv);
702 } else if (!strcmp(argv[0], "stat")) { 697 }
698
699 session = perf_session__new(&file, false, &perf_kmem);
700 if (session == NULL)
701 return -1;
702
703 symbol__init(&session->header.env);
704
705 if (!strcmp(argv[0], "stat")) {
703 if (cpu__setup_cpunode_map()) 706 if (cpu__setup_cpunode_map())
704 return -1; 707 goto out_delete;
705 708
706 if (list_empty(&caller_sort)) 709 if (list_empty(&caller_sort))
707 setup_sorting(&caller_sort, default_sort_order); 710 setup_sorting(&caller_sort, default_sort_order);
708 if (list_empty(&alloc_sort)) 711 if (list_empty(&alloc_sort))
709 setup_sorting(&alloc_sort, default_sort_order); 712 setup_sorting(&alloc_sort, default_sort_order);
710 713
711 return __cmd_kmem(); 714 ret = __cmd_kmem(session);
712 } else 715 } else
713 usage_with_options(kmem_usage, kmem_options); 716 usage_with_options(kmem_usage, kmem_options);
714 717
715 return 0; 718out_delete:
719 perf_session__delete(session);
720
721 return ret;
716} 722}
717 723
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 43367eb00510..0894a817f67e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -376,7 +376,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
376 struct perf_sample *sample) 376 struct perf_sample *sample)
377{ 377{
378 /* Only kvm_entry records vcpu id. */ 378 /* Only kvm_entry records vcpu id. */
379 if (!thread->priv && kvm_entry_event(evsel)) { 379 if (!thread__priv(thread) && kvm_entry_event(evsel)) {
380 struct vcpu_event_record *vcpu_record; 380 struct vcpu_event_record *vcpu_record;
381 381
382 vcpu_record = zalloc(sizeof(*vcpu_record)); 382 vcpu_record = zalloc(sizeof(*vcpu_record));
@@ -386,10 +386,10 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
386 } 386 }
387 387
388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); 388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
389 thread->priv = vcpu_record; 389 thread__set_priv(thread, vcpu_record);
390 } 390 }
391 391
392 return thread->priv; 392 return thread__priv(thread);
393} 393}
394 394
395static bool handle_kvm_event(struct perf_kvm_stat *kvm, 395static bool handle_kvm_event(struct perf_kvm_stat *kvm,
@@ -543,14 +543,12 @@ static void print_vcpu_info(struct perf_kvm_stat *kvm)
543 543
544 pr_info("Analyze events for "); 544 pr_info("Analyze events for ");
545 545
546 if (kvm->live) { 546 if (kvm->opts.target.system_wide)
547 if (kvm->opts.target.system_wide) 547 pr_info("all VMs, ");
548 pr_info("all VMs, "); 548 else if (kvm->opts.target.pid)
549 else if (kvm->opts.target.pid) 549 pr_info("pid(s) %s, ", kvm->opts.target.pid);
550 pr_info("pid(s) %s, ", kvm->opts.target.pid); 550 else
551 else 551 pr_info("dazed and confused on what is monitored, ");
552 pr_info("dazed and confused on what is monitored, ");
553 }
554 552
555 if (vcpu == -1) 553 if (vcpu == -1)
556 pr_info("all VCPUs:\n\n"); 554 pr_info("all VCPUs:\n\n");
@@ -592,8 +590,8 @@ static void print_result(struct perf_kvm_stat *kvm)
592 pr_info("%9s ", "Samples%"); 590 pr_info("%9s ", "Samples%");
593 591
594 pr_info("%9s ", "Time%"); 592 pr_info("%9s ", "Time%");
595 pr_info("%10s ", "Min Time"); 593 pr_info("%11s ", "Min Time");
596 pr_info("%10s ", "Max Time"); 594 pr_info("%11s ", "Max Time");
597 pr_info("%16s ", "Avg time"); 595 pr_info("%16s ", "Avg time");
598 pr_info("\n\n"); 596 pr_info("\n\n");
599 597
@@ -610,8 +608,8 @@ static void print_result(struct perf_kvm_stat *kvm)
610 pr_info("%10llu ", (unsigned long long)ecount); 608 pr_info("%10llu ", (unsigned long long)ecount);
611 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 609 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
612 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 610 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
613 pr_info("%8" PRIu64 "us ", min / 1000); 611 pr_info("%9.2fus ", (double)min / 1e3);
614 pr_info("%8" PRIu64 "us ", max / 1000); 612 pr_info("%9.2fus ", (double)max / 1e3);
615 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 613 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
616 kvm_event_rel_stddev(vcpu, event)); 614 kvm_event_rel_stddev(vcpu, event));
617 pr_info("\n"); 615 pr_info("\n");
@@ -732,7 +730,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
732 return -1; 730 return -1;
733 } 731 }
734 732
735 err = perf_session_queue_event(kvm->session, event, &sample, 0); 733 err = perf_session_queue_event(kvm->session, event, &kvm->tool, &sample, 0);
736 /* 734 /*
737 * FIXME: Here we can't consume the event, as perf_session_queue_event will 735 * FIXME: Here we can't consume the event, as perf_session_queue_event will
738 * point to it, and it'll get possibly overwritten by the kernel. 736 * point to it, and it'll get possibly overwritten by the kernel.
@@ -785,7 +783,7 @@ static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
785 783
786 /* flush queue after each round in which we processed events */ 784 /* flush queue after each round in which we processed events */
787 if (ntotal) { 785 if (ntotal) {
788 kvm->session->ordered_samples.next_flush = flush_time; 786 kvm->session->ordered_events.next_flush = flush_time;
789 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session); 787 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
790 if (err) { 788 if (err) {
791 if (kvm->lost_events) 789 if (kvm->lost_events)
@@ -885,15 +883,11 @@ static int fd_set_nonblock(int fd)
885 return 0; 883 return 0;
886} 884}
887 885
888static 886static int perf_kvm__handle_stdin(void)
889int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
890{ 887{
891 int c; 888 int c;
892 889
893 tcsetattr(0, TCSANOW, tc_now);
894 c = getc(stdin); 890 c = getc(stdin);
895 tcsetattr(0, TCSAFLUSH, tc_save);
896
897 if (c == 'q') 891 if (c == 'q')
898 return 1; 892 return 1;
899 893
@@ -902,9 +896,8 @@ int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
902 896
903static int kvm_events_live_report(struct perf_kvm_stat *kvm) 897static int kvm_events_live_report(struct perf_kvm_stat *kvm)
904{ 898{
905 struct pollfd *pollfds = NULL; 899 int nr_stdin, ret, err = -EINVAL;
906 int nr_fds, nr_stdin, ret, err = -EINVAL; 900 struct termios save;
907 struct termios tc, save;
908 901
909 /* live flag must be set first */ 902 /* live flag must be set first */
910 kvm->live = true; 903 kvm->live = true;
@@ -919,41 +912,25 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
919 goto out; 912 goto out;
920 } 913 }
921 914
915 set_term_quiet_input(&save);
922 init_kvm_event_record(kvm); 916 init_kvm_event_record(kvm);
923 917
924 tcgetattr(0, &save);
925 tc = save;
926 tc.c_lflag &= ~(ICANON | ECHO);
927 tc.c_cc[VMIN] = 0;
928 tc.c_cc[VTIME] = 0;
929
930 signal(SIGINT, sig_handler); 918 signal(SIGINT, sig_handler);
931 signal(SIGTERM, sig_handler); 919 signal(SIGTERM, sig_handler);
932 920
933 /* copy pollfds -- need to add timerfd and stdin */
934 nr_fds = kvm->evlist->nr_fds;
935 pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
936 if (!pollfds) {
937 err = -ENOMEM;
938 goto out;
939 }
940 memcpy(pollfds, kvm->evlist->pollfd,
941 sizeof(struct pollfd) * kvm->evlist->nr_fds);
942
943 /* add timer fd */ 921 /* add timer fd */
944 if (perf_kvm__timerfd_create(kvm) < 0) { 922 if (perf_kvm__timerfd_create(kvm) < 0) {
945 err = -1; 923 err = -1;
946 goto out; 924 goto out;
947 } 925 }
948 926
949 pollfds[nr_fds].fd = kvm->timerfd; 927 if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
950 pollfds[nr_fds].events = POLLIN; 928 goto out;
951 nr_fds++; 929
930 nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin));
931 if (nr_stdin < 0)
932 goto out;
952 933
953 pollfds[nr_fds].fd = fileno(stdin);
954 pollfds[nr_fds].events = POLLIN;
955 nr_stdin = nr_fds;
956 nr_fds++;
957 if (fd_set_nonblock(fileno(stdin)) != 0) 934 if (fd_set_nonblock(fileno(stdin)) != 0)
958 goto out; 935 goto out;
959 936
@@ -961,6 +938,7 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
961 perf_evlist__enable(kvm->evlist); 938 perf_evlist__enable(kvm->evlist);
962 939
963 while (!done) { 940 while (!done) {
941 struct fdarray *fda = &kvm->evlist->pollfd;
964 int rc; 942 int rc;
965 943
966 rc = perf_kvm__mmap_read(kvm); 944 rc = perf_kvm__mmap_read(kvm);
@@ -971,11 +949,11 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
971 if (err) 949 if (err)
972 goto out; 950 goto out;
973 951
974 if (pollfds[nr_stdin].revents & POLLIN) 952 if (fda->entries[nr_stdin].revents & POLLIN)
975 done = perf_kvm__handle_stdin(&tc, &save); 953 done = perf_kvm__handle_stdin();
976 954
977 if (!rc && !done) 955 if (!rc && !done)
978 err = poll(pollfds, nr_fds, 100); 956 err = fdarray__poll(fda, 100);
979 } 957 }
980 958
981 perf_evlist__disable(kvm->evlist); 959 perf_evlist__disable(kvm->evlist);
@@ -989,7 +967,7 @@ out:
989 if (kvm->timerfd >= 0) 967 if (kvm->timerfd >= 0)
990 close(kvm->timerfd); 968 close(kvm->timerfd);
991 969
992 free(pollfds); 970 tcsetattr(0, TCSAFLUSH, &save);
993 return err; 971 return err;
994} 972}
995 973
@@ -998,6 +976,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
998 int err, rc = -1; 976 int err, rc = -1;
999 struct perf_evsel *pos; 977 struct perf_evsel *pos;
1000 struct perf_evlist *evlist = kvm->evlist; 978 struct perf_evlist *evlist = kvm->evlist;
979 char sbuf[STRERR_BUFSIZE];
1001 980
1002 perf_evlist__config(evlist, &kvm->opts); 981 perf_evlist__config(evlist, &kvm->opts);
1003 982
@@ -1034,12 +1013,14 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1034 1013
1035 err = perf_evlist__open(evlist); 1014 err = perf_evlist__open(evlist);
1036 if (err < 0) { 1015 if (err < 0) {
1037 printf("Couldn't create the events: %s\n", strerror(errno)); 1016 printf("Couldn't create the events: %s\n",
1017 strerror_r(errno, sbuf, sizeof(sbuf)));
1038 goto out; 1018 goto out;
1039 } 1019 }
1040 1020
1041 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { 1021 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1042 ui__error("Failed to mmap the events: %s\n", strerror(errno)); 1022 ui__error("Failed to mmap the events: %s\n",
1023 strerror_r(errno, sbuf, sizeof(sbuf)));
1043 perf_evlist__close(evlist); 1024 perf_evlist__close(evlist);
1044 goto out; 1025 goto out;
1045 } 1026 }
@@ -1058,7 +1039,7 @@ static int read_events(struct perf_kvm_stat *kvm)
1058 struct perf_tool eops = { 1039 struct perf_tool eops = {
1059 .sample = process_sample_event, 1040 .sample = process_sample_event,
1060 .comm = perf_event__process_comm, 1041 .comm = perf_event__process_comm,
1061 .ordered_samples = true, 1042 .ordered_events = true,
1062 }; 1043 };
1063 struct perf_data_file file = { 1044 struct perf_data_file file = {
1064 .path = kvm->file_name, 1045 .path = kvm->file_name,
@@ -1069,9 +1050,11 @@ static int read_events(struct perf_kvm_stat *kvm)
1069 kvm->session = perf_session__new(&file, false, &kvm->tool); 1050 kvm->session = perf_session__new(&file, false, &kvm->tool);
1070 if (!kvm->session) { 1051 if (!kvm->session) {
1071 pr_err("Initializing perf session failed\n"); 1052 pr_err("Initializing perf session failed\n");
1072 return -EINVAL; 1053 return -1;
1073 } 1054 }
1074 1055
1056 symbol__init(&kvm->session->header.env);
1057
1075 if (!perf_session__has_traces(kvm->session, "kvm record")) 1058 if (!perf_session__has_traces(kvm->session, "kvm record"))
1076 return -EINVAL; 1059 return -EINVAL;
1077 1060
@@ -1088,8 +1071,8 @@ static int read_events(struct perf_kvm_stat *kvm)
1088 1071
1089static int parse_target_str(struct perf_kvm_stat *kvm) 1072static int parse_target_str(struct perf_kvm_stat *kvm)
1090{ 1073{
1091 if (kvm->pid_str) { 1074 if (kvm->opts.target.pid) {
1092 kvm->pid_list = intlist__new(kvm->pid_str); 1075 kvm->pid_list = intlist__new(kvm->opts.target.pid);
1093 if (kvm->pid_list == NULL) { 1076 if (kvm->pid_list == NULL) {
1094 pr_err("Error parsing process id string\n"); 1077 pr_err("Error parsing process id string\n");
1095 return -EINVAL; 1078 return -EINVAL;
@@ -1149,6 +1132,10 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1149 "-m", "1024", 1132 "-m", "1024",
1150 "-c", "1", 1133 "-c", "1",
1151 }; 1134 };
1135 const char * const kvm_stat_record_usage[] = {
1136 "perf kvm stat record [<options>]",
1137 NULL
1138 };
1152 const char * const *events_tp; 1139 const char * const *events_tp;
1153 events_tp_size = 0; 1140 events_tp_size = 0;
1154 1141
@@ -1176,6 +1163,27 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
1176 for (j = 1; j < (unsigned int)argc; j++, i++) 1163 for (j = 1; j < (unsigned int)argc; j++, i++)
1177 rec_argv[i] = argv[j]; 1164 rec_argv[i] = argv[j];
1178 1165
1166 set_option_flag(record_options, 'e', "event", PARSE_OPT_HIDDEN);
1167 set_option_flag(record_options, 0, "filter", PARSE_OPT_HIDDEN);
1168 set_option_flag(record_options, 'R', "raw-samples", PARSE_OPT_HIDDEN);
1169
1170 set_option_flag(record_options, 'F', "freq", PARSE_OPT_DISABLED);
1171 set_option_flag(record_options, 0, "group", PARSE_OPT_DISABLED);
1172 set_option_flag(record_options, 'g', NULL, PARSE_OPT_DISABLED);
1173 set_option_flag(record_options, 0, "call-graph", PARSE_OPT_DISABLED);
1174 set_option_flag(record_options, 'd', "data", PARSE_OPT_DISABLED);
1175 set_option_flag(record_options, 'T', "timestamp", PARSE_OPT_DISABLED);
1176 set_option_flag(record_options, 'P', "period", PARSE_OPT_DISABLED);
1177 set_option_flag(record_options, 'n', "no-samples", PARSE_OPT_DISABLED);
1178 set_option_flag(record_options, 'N', "no-buildid-cache", PARSE_OPT_DISABLED);
1179 set_option_flag(record_options, 'B', "no-buildid", PARSE_OPT_DISABLED);
1180 set_option_flag(record_options, 'G', "cgroup", PARSE_OPT_DISABLED);
1181 set_option_flag(record_options, 'b', "branch-any", PARSE_OPT_DISABLED);
1182 set_option_flag(record_options, 'j', "branch-filter", PARSE_OPT_DISABLED);
1183 set_option_flag(record_options, 'W', "weight", PARSE_OPT_DISABLED);
1184 set_option_flag(record_options, 0, "transaction", PARSE_OPT_DISABLED);
1185
1186 record_usage = kvm_stat_record_usage;
1179 return cmd_record(i, rec_argv, NULL); 1187 return cmd_record(i, rec_argv, NULL);
1180} 1188}
1181 1189
@@ -1191,7 +1199,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1191 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1199 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1192 "key for sorting: sample(sort by samples number)" 1200 "key for sorting: sample(sort by samples number)"
1193 " time (sort by avg time)"), 1201 " time (sort by avg time)"),
1194 OPT_STRING('p', "pid", &kvm->pid_str, "pid", 1202 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1195 "analyze events only for given process id(s)"), 1203 "analyze events only for given process id(s)"),
1196 OPT_END() 1204 OPT_END()
1197 }; 1205 };
@@ -1201,8 +1209,6 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1201 NULL 1209 NULL
1202 }; 1210 };
1203 1211
1204 symbol__init();
1205
1206 if (argc) { 1212 if (argc) {
1207 argc = parse_options(argc, argv, 1213 argc = parse_options(argc, argv,
1208 kvm_events_report_options, 1214 kvm_events_report_options,
@@ -1212,6 +1218,9 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
1212 kvm_events_report_options); 1218 kvm_events_report_options);
1213 } 1219 }
1214 1220
1221 if (!kvm->opts.target.pid)
1222 kvm->opts.target.system_wide = true;
1223
1215 return kvm_events_report_vcpu(kvm); 1224 return kvm_events_report_vcpu(kvm);
1216} 1225}
1217 1226
@@ -1284,7 +1293,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1284 OPT_UINTEGER('d', "display", &kvm->display_time, 1293 OPT_UINTEGER('d', "display", &kvm->display_time,
1285 "time in seconds between display updates"), 1294 "time in seconds between display updates"),
1286 OPT_STRING(0, "event", &kvm->report_event, "report event", 1295 OPT_STRING(0, "event", &kvm->report_event, "report event",
1287 "event for reporting: vmexit, mmio, ioport"), 1296 "event for reporting: "
1297 "vmexit, mmio (x86 only), ioport (x86 only)"),
1288 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu, 1298 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1289 "vcpu id to report"), 1299 "vcpu id to report"),
1290 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1300 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
@@ -1311,7 +1321,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1311 kvm->tool.exit = perf_event__process_exit; 1321 kvm->tool.exit = perf_event__process_exit;
1312 kvm->tool.fork = perf_event__process_fork; 1322 kvm->tool.fork = perf_event__process_fork;
1313 kvm->tool.lost = process_lost_event; 1323 kvm->tool.lost = process_lost_event;
1314 kvm->tool.ordered_samples = true; 1324 kvm->tool.ordered_events = true;
1315 perf_tool__fill_defaults(&kvm->tool); 1325 perf_tool__fill_defaults(&kvm->tool);
1316 1326
1317 /* set defaults */ 1327 /* set defaults */
@@ -1322,7 +1332,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1322 kvm->opts.target.uid_str = NULL; 1332 kvm->opts.target.uid_str = NULL;
1323 kvm->opts.target.uid = UINT_MAX; 1333 kvm->opts.target.uid = UINT_MAX;
1324 1334
1325 symbol__init(); 1335 symbol__init(NULL);
1326 disable_buildid_cache(); 1336 disable_buildid_cache();
1327 1337
1328 use_browser = 0; 1338 use_browser = 0;
@@ -1369,11 +1379,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1369 */ 1379 */
1370 kvm->session = perf_session__new(&file, false, &kvm->tool); 1380 kvm->session = perf_session__new(&file, false, &kvm->tool);
1371 if (kvm->session == NULL) { 1381 if (kvm->session == NULL) {
1372 err = -ENOMEM; 1382 err = -1;
1373 goto out; 1383 goto out;
1374 } 1384 }
1375 kvm->session->evlist = kvm->evlist; 1385 kvm->session->evlist = kvm->evlist;
1376 perf_session__set_id_hdr_size(kvm->session); 1386 perf_session__set_id_hdr_size(kvm->session);
1387 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
1377 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, 1388 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
1378 kvm->evlist->threads, false); 1389 kvm->evlist->threads, false);
1379 err = kvm_live_open_events(kvm); 1390 err = kvm_live_open_events(kvm);
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 011195e38f21..198f3c3aff95 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -19,7 +19,9 @@
19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
20{ 20{
21 int i; 21 int i;
22 const struct option list_options[] = { 22 bool raw_dump = false;
23 struct option list_options[] = {
24 OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
23 OPT_END() 25 OPT_END()
24 }; 26 };
25 const char * const list_usage[] = { 27 const char * const list_usage[] = {
@@ -27,11 +29,18 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
27 NULL 29 NULL
28 }; 30 };
29 31
32 set_option_flag(list_options, 0, "raw-dump", PARSE_OPT_HIDDEN);
33
30 argc = parse_options(argc, argv, list_options, list_usage, 34 argc = parse_options(argc, argv, list_options, list_usage,
31 PARSE_OPT_STOP_AT_NON_OPTION); 35 PARSE_OPT_STOP_AT_NON_OPTION);
32 36
33 setup_pager(); 37 setup_pager();
34 38
39 if (raw_dump) {
40 print_events(NULL, true);
41 return 0;
42 }
43
35 if (argc == 0) { 44 if (argc == 0) {
36 print_events(NULL, false); 45 print_events(NULL, false);
37 return 0; 46 return 0;
@@ -53,8 +62,6 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
53 print_hwcache_events(NULL, false); 62 print_hwcache_events(NULL, false);
54 else if (strcmp(argv[i], "pmu") == 0) 63 else if (strcmp(argv[i], "pmu") == 0)
55 print_pmu_events(NULL, false); 64 print_pmu_events(NULL, false);
56 else if (strcmp(argv[i], "--raw-dump") == 0)
57 print_events(NULL, true);
58 else { 65 else {
59 char *sep = strchr(argv[i], ':'), *s; 66 char *sep = strchr(argv[i], ':'), *s;
60 int sep_idx; 67 int sep_idx;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6148afc995c6..e7ec71589da6 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -852,7 +852,7 @@ static int __cmd_report(bool display_info)
852 struct perf_tool eops = { 852 struct perf_tool eops = {
853 .sample = process_sample_event, 853 .sample = process_sample_event,
854 .comm = perf_event__process_comm, 854 .comm = perf_event__process_comm,
855 .ordered_samples = true, 855 .ordered_events = true,
856 }; 856 };
857 struct perf_data_file file = { 857 struct perf_data_file file = {
858 .path = input_name, 858 .path = input_name,
@@ -862,9 +862,11 @@ static int __cmd_report(bool display_info)
862 session = perf_session__new(&file, false, &eops); 862 session = perf_session__new(&file, false, &eops);
863 if (!session) { 863 if (!session) {
864 pr_err("Initializing perf session failed\n"); 864 pr_err("Initializing perf session failed\n");
865 return -ENOMEM; 865 return -1;
866 } 866 }
867 867
868 symbol__init(&session->header.env);
869
868 if (!perf_session__has_traces(session, "lock record")) 870 if (!perf_session__has_traces(session, "lock record"))
869 goto out_delete; 871 goto out_delete;
870 872
@@ -974,7 +976,6 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
974 unsigned int i; 976 unsigned int i;
975 int rc = 0; 977 int rc = 0;
976 978
977 symbol__init();
978 for (i = 0; i < LOCKHASH_SIZE; i++) 979 for (i = 0; i < LOCKHASH_SIZE; i++)
979 INIT_LIST_HEAD(lockhash_table + i); 980 INIT_LIST_HEAD(lockhash_table + i);
980 981
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 4a1a6c94a5eb..24db6ffe2957 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -124,7 +124,7 @@ static int report_raw_events(struct perf_mem *mem)
124 &mem->tool); 124 &mem->tool);
125 125
126 if (session == NULL) 126 if (session == NULL)
127 return -ENOMEM; 127 return -1;
128 128
129 if (mem->cpu_list) { 129 if (mem->cpu_list) {
130 ret = perf_session__cpu_bitmap(session, mem->cpu_list, 130 ret = perf_session__cpu_bitmap(session, mem->cpu_list,
@@ -133,7 +133,7 @@ static int report_raw_events(struct perf_mem *mem)
133 goto out_delete; 133 goto out_delete;
134 } 134 }
135 135
136 if (symbol__init() < 0) 136 if (symbol__init(&session->header.env) < 0)
137 return -1; 137 return -1;
138 138
139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n"); 139 printf("# PID, TID, IP, ADDR, LOCAL WEIGHT, DSRC, SYMBOL\n");
@@ -194,7 +194,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
194 .lost = perf_event__process_lost, 194 .lost = perf_event__process_lost,
195 .fork = perf_event__process_fork, 195 .fork = perf_event__process_fork,
196 .build_id = perf_event__process_build_id, 196 .build_id = perf_event__process_build_id,
197 .ordered_samples = true, 197 .ordered_events = true,
198 }, 198 },
199 .input_name = "perf.data", 199 .input_name = "perf.data",
200 }; 200 };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c63fa2925075..921bb6942503 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -55,6 +55,7 @@ static struct {
55 bool show_funcs; 55 bool show_funcs;
56 bool mod_events; 56 bool mod_events;
57 bool uprobes; 57 bool uprobes;
58 bool quiet;
58 int nevents; 59 int nevents;
59 struct perf_probe_event events[MAX_PROBES]; 60 struct perf_probe_event events[MAX_PROBES];
60 struct strlist *dellist; 61 struct strlist *dellist;
@@ -290,8 +291,11 @@ static void cleanup_params(void)
290 291
291static void pr_err_with_code(const char *msg, int err) 292static void pr_err_with_code(const char *msg, int err)
292{ 293{
294 char sbuf[STRERR_BUFSIZE];
295
293 pr_err("%s", msg); 296 pr_err("%s", msg);
294 pr_debug(" Reason: %s (Code: %d)", strerror(-err), err); 297 pr_debug(" Reason: %s (Code: %d)",
298 strerror_r(-err, sbuf, sizeof(sbuf)), err);
295 pr_err("\n"); 299 pr_err("\n");
296} 300}
297 301
@@ -309,9 +313,11 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
309#endif 313#endif
310 NULL 314 NULL
311}; 315};
312 const struct option options[] = { 316 struct option options[] = {
313 OPT_INCR('v', "verbose", &verbose, 317 OPT_INCR('v', "verbose", &verbose,
314 "be more verbose (show parsed arguments, etc)"), 318 "be more verbose (show parsed arguments, etc)"),
319 OPT_BOOLEAN('q', "quiet", &params.quiet,
320 "be quiet (do not show any mesages)"),
315 OPT_BOOLEAN('l', "list", &params.list_events, 321 OPT_BOOLEAN('l', "list", &params.list_events,
316 "list up current probe events"), 322 "list up current probe events"),
317 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 323 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
@@ -372,11 +378,21 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
372 OPT_CALLBACK('x', "exec", NULL, "executable|path", 378 OPT_CALLBACK('x', "exec", NULL, "executable|path",
373 "target executable name or path", opt_set_target), 379 "target executable name or path", opt_set_target),
374 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 380 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
375 "Disable symbol demangling"), 381 "Enable symbol demangling"),
382 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
383 "Enable kernel symbol demangling"),
376 OPT_END() 384 OPT_END()
377 }; 385 };
378 int ret; 386 int ret;
379 387
388 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
389 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
390 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
391#ifdef HAVE_DWARF_SUPPORT
392 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
393 set_option_flag(options, 'V', "vars", PARSE_OPT_EXCLUSIVE);
394#endif
395
380 argc = parse_options(argc, argv, options, probe_usage, 396 argc = parse_options(argc, argv, options, probe_usage,
381 PARSE_OPT_STOP_AT_NON_OPTION); 397 PARSE_OPT_STOP_AT_NON_OPTION);
382 if (argc > 0) { 398 if (argc > 0) {
@@ -391,6 +407,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
391 } 407 }
392 } 408 }
393 409
410 if (params.quiet) {
411 if (verbose != 0) {
412 pr_err(" Error: -v and -q are exclusive.\n");
413 return -EINVAL;
414 }
415 verbose = -1;
416 }
417
394 if (params.max_probe_points == 0) 418 if (params.max_probe_points == 0)
395 params.max_probe_points = MAX_PROBES; 419 params.max_probe_points = MAX_PROBES;
396 420
@@ -404,22 +428,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
404 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 428 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
405 429
406 if (params.list_events) { 430 if (params.list_events) {
407 if (params.mod_events) {
408 pr_err(" Error: Don't use --list with --add/--del.\n");
409 usage_with_options(probe_usage, options);
410 }
411 if (params.show_lines) {
412 pr_err(" Error: Don't use --list with --line.\n");
413 usage_with_options(probe_usage, options);
414 }
415 if (params.show_vars) {
416 pr_err(" Error: Don't use --list with --vars.\n");
417 usage_with_options(probe_usage, options);
418 }
419 if (params.show_funcs) {
420 pr_err(" Error: Don't use --list with --funcs.\n");
421 usage_with_options(probe_usage, options);
422 }
423 if (params.uprobes) { 431 if (params.uprobes) {
424 pr_warning(" Error: Don't use --list with --exec.\n"); 432 pr_warning(" Error: Don't use --list with --exec.\n");
425 usage_with_options(probe_usage, options); 433 usage_with_options(probe_usage, options);
@@ -430,19 +438,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
430 return ret; 438 return ret;
431 } 439 }
432 if (params.show_funcs) { 440 if (params.show_funcs) {
433 if (params.nevents != 0 || params.dellist) {
434 pr_err(" Error: Don't use --funcs with"
435 " --add/--del.\n");
436 usage_with_options(probe_usage, options);
437 }
438 if (params.show_lines) {
439 pr_err(" Error: Don't use --funcs with --line.\n");
440 usage_with_options(probe_usage, options);
441 }
442 if (params.show_vars) {
443 pr_err(" Error: Don't use --funcs with --vars.\n");
444 usage_with_options(probe_usage, options);
445 }
446 if (!params.filter) 441 if (!params.filter)
447 params.filter = strfilter__new(DEFAULT_FUNC_FILTER, 442 params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
448 NULL); 443 NULL);
@@ -457,27 +452,13 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
457 452
458#ifdef HAVE_DWARF_SUPPORT 453#ifdef HAVE_DWARF_SUPPORT
459 if (params.show_lines) { 454 if (params.show_lines) {
460 if (params.mod_events) { 455 ret = show_line_range(&params.line_range, params.target,
461 pr_err(" Error: Don't use --line with" 456 params.uprobes);
462 " --add/--del.\n");
463 usage_with_options(probe_usage, options);
464 }
465 if (params.show_vars) {
466 pr_err(" Error: Don't use --line with --vars.\n");
467 usage_with_options(probe_usage, options);
468 }
469
470 ret = show_line_range(&params.line_range, params.target);
471 if (ret < 0) 457 if (ret < 0)
472 pr_err_with_code(" Error: Failed to show lines.", ret); 458 pr_err_with_code(" Error: Failed to show lines.", ret);
473 return ret; 459 return ret;
474 } 460 }
475 if (params.show_vars) { 461 if (params.show_vars) {
476 if (params.mod_events) {
477 pr_err(" Error: Don't use --vars with"
478 " --add/--del.\n");
479 usage_with_options(probe_usage, options);
480 }
481 if (!params.filter) 462 if (!params.filter)
482 params.filter = strfilter__new(DEFAULT_VAR_FILTER, 463 params.filter = strfilter__new(DEFAULT_VAR_FILTER,
483 NULL); 464 NULL);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 4869050e7194..8648c6d3003d 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -14,6 +14,8 @@
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16 16
17#include "util/callchain.h"
18#include "util/cgroup.h"
17#include "util/header.h" 19#include "util/header.h"
18#include "util/event.h" 20#include "util/event.h"
19#include "util/evlist.h" 21#include "util/evlist.h"
@@ -65,8 +67,9 @@ static int process_synthesized_event(struct perf_tool *tool,
65 return record__write(rec, event, event->header.size); 67 return record__write(rec, event, event->header.size);
66} 68}
67 69
68static int record__mmap_read(struct record *rec, struct perf_mmap *md) 70static int record__mmap_read(struct record *rec, int idx)
69{ 71{
72 struct perf_mmap *md = &rec->evlist->mmap[idx];
70 unsigned int head = perf_mmap__read_head(md); 73 unsigned int head = perf_mmap__read_head(md);
71 unsigned int old = md->prev; 74 unsigned int old = md->prev;
72 unsigned char *data = md->base + page_size; 75 unsigned char *data = md->base + page_size;
@@ -102,8 +105,7 @@ static int record__mmap_read(struct record *rec, struct perf_mmap *md)
102 } 105 }
103 106
104 md->prev = old; 107 md->prev = old;
105 perf_mmap__write_tail(md, old); 108 perf_evlist__mmap_consume(rec->evlist, idx);
106
107out: 109out:
108 return rc; 110 return rc;
109} 111}
@@ -161,7 +163,7 @@ try_again:
161 163
162 if (perf_evlist__apply_filters(evlist)) { 164 if (perf_evlist__apply_filters(evlist)) {
163 error("failed to set filter with %d (%s)\n", errno, 165 error("failed to set filter with %d (%s)\n", errno,
164 strerror(errno)); 166 strerror_r(errno, msg, sizeof(msg)));
165 rc = -1; 167 rc = -1;
166 goto out; 168 goto out;
167 } 169 }
@@ -175,7 +177,8 @@ try_again:
175 "(current value: %u)\n", opts->mmap_pages); 177 "(current value: %u)\n", opts->mmap_pages);
176 rc = -errno; 178 rc = -errno;
177 } else { 179 } else {
178 pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno)); 180 pr_err("failed to mmap with %d (%s)\n", errno,
181 strerror_r(errno, msg, sizeof(msg)));
179 rc = -errno; 182 rc = -errno;
180 } 183 }
181 goto out; 184 goto out;
@@ -197,6 +200,17 @@ static int process_buildids(struct record *rec)
197 if (size == 0) 200 if (size == 0)
198 return 0; 201 return 0;
199 202
203 /*
204 * During this process, it'll load kernel map and replace the
205 * dso->long_name to a real pathname it found. In this case
206 * we prefer the vmlinux path like
207 * /lib/modules/3.16.4/build/vmlinux
208 *
209 * rather than build-id path (in debug directory).
210 * $HOME/.debug/.build-id/f0/6e17aa50adf4d00b88925e03775de107611551
211 */
212 symbol_conf.ignore_vmlinux_buildid = true;
213
200 return __perf_session__process_events(session, start, 214 return __perf_session__process_events(session, start,
201 size - start, 215 size - start,
202 size, &build_id__mark_dso_hit_ops); 216 size, &build_id__mark_dso_hit_ops);
@@ -244,7 +258,7 @@ static int record__mmap_read_all(struct record *rec)
244 258
245 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 259 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
246 if (rec->evlist->mmap[i].base) { 260 if (rec->evlist->mmap[i].base) {
247 if (record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) { 261 if (record__mmap_read(rec, i) != 0) {
248 rc = -1; 262 rc = -1;
249 goto out; 263 goto out;
250 } 264 }
@@ -307,7 +321,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
307 struct record_opts *opts = &rec->opts; 321 struct record_opts *opts = &rec->opts;
308 struct perf_data_file *file = &rec->file; 322 struct perf_data_file *file = &rec->file;
309 struct perf_session *session; 323 struct perf_session *session;
310 bool disabled = false; 324 bool disabled = false, draining = false;
311 325
312 rec->progname = argv[0]; 326 rec->progname = argv[0];
313 327
@@ -456,9 +470,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
456 } 470 }
457 471
458 if (hits == rec->samples) { 472 if (hits == rec->samples) {
459 if (done) 473 if (done || draining)
460 break; 474 break;
461 err = poll(rec->evlist->pollfd, rec->evlist->nr_fds, -1); 475 err = perf_evlist__poll(rec->evlist, -1);
462 /* 476 /*
463 * Propagate error, only if there's any. Ignore positive 477 * Propagate error, only if there's any. Ignore positive
464 * number of returned events and interrupt error. 478 * number of returned events and interrupt error.
@@ -466,6 +480,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
466 if (err > 0 || (err < 0 && errno == EINTR)) 480 if (err > 0 || (err < 0 && errno == EINTR))
467 err = 0; 481 err = 0;
468 waking++; 482 waking++;
483
484 if (perf_evlist__filter_pollfd(rec->evlist, POLLERR | POLLHUP) == 0)
485 draining = true;
469 } 486 }
470 487
471 /* 488 /*
@@ -480,7 +497,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
480 } 497 }
481 498
482 if (forks && workload_exec_errno) { 499 if (forks && workload_exec_errno) {
483 char msg[512]; 500 char msg[STRERR_BUFSIZE];
484 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 501 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
485 pr_err("Workload failed: %s\n", emsg); 502 pr_err("Workload failed: %s\n", emsg);
486 err = -1; 503 err = -1;
@@ -620,154 +637,66 @@ error:
620 return ret; 637 return ret;
621} 638}
622 639
623#ifdef HAVE_DWARF_UNWIND_SUPPORT 640static void callchain_debug(void)
624static int get_stack_size(char *str, unsigned long *_size)
625{
626 char *endptr;
627 unsigned long size;
628 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
629
630 size = strtoul(str, &endptr, 0);
631
632 do {
633 if (*endptr)
634 break;
635
636 size = round_up(size, sizeof(u64));
637 if (!size || size > max_size)
638 break;
639
640 *_size = size;
641 return 0;
642
643 } while (0);
644
645 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
646 max_size, str);
647 return -1;
648}
649#endif /* HAVE_DWARF_UNWIND_SUPPORT */
650
651int record_parse_callchain(const char *arg, struct record_opts *opts)
652{
653 char *tok, *name, *saveptr = NULL;
654 char *buf;
655 int ret = -1;
656
657 /* We need buffer that we know we can write to. */
658 buf = malloc(strlen(arg) + 1);
659 if (!buf)
660 return -ENOMEM;
661
662 strcpy(buf, arg);
663
664 tok = strtok_r((char *)buf, ",", &saveptr);
665 name = tok ? : (char *)buf;
666
667 do {
668 /* Framepointer style */
669 if (!strncmp(name, "fp", sizeof("fp"))) {
670 if (!strtok_r(NULL, ",", &saveptr)) {
671 opts->call_graph = CALLCHAIN_FP;
672 ret = 0;
673 } else
674 pr_err("callchain: No more arguments "
675 "needed for -g fp\n");
676 break;
677
678#ifdef HAVE_DWARF_UNWIND_SUPPORT
679 /* Dwarf style */
680 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
681 const unsigned long default_stack_dump_size = 8192;
682
683 ret = 0;
684 opts->call_graph = CALLCHAIN_DWARF;
685 opts->stack_dump_size = default_stack_dump_size;
686
687 tok = strtok_r(NULL, ",", &saveptr);
688 if (tok) {
689 unsigned long size = 0;
690
691 ret = get_stack_size(tok, &size);
692 opts->stack_dump_size = size;
693 }
694#endif /* HAVE_DWARF_UNWIND_SUPPORT */
695 } else {
696 pr_err("callchain: Unknown --call-graph option "
697 "value: %s\n", arg);
698 break;
699 }
700
701 } while (0);
702
703 free(buf);
704 return ret;
705}
706
707static void callchain_debug(struct record_opts *opts)
708{ 641{
709 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" }; 642 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF" };
710 643
711 pr_debug("callchain: type %s\n", str[opts->call_graph]); 644 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);
712 645
713 if (opts->call_graph == CALLCHAIN_DWARF) 646 if (callchain_param.record_mode == CALLCHAIN_DWARF)
714 pr_debug("callchain: stack dump size %d\n", 647 pr_debug("callchain: stack dump size %d\n",
715 opts->stack_dump_size); 648 callchain_param.dump_size);
716} 649}
717 650
718int record_parse_callchain_opt(const struct option *opt, 651int record_parse_callchain_opt(const struct option *opt __maybe_unused,
719 const char *arg, 652 const char *arg,
720 int unset) 653 int unset)
721{ 654{
722 struct record_opts *opts = opt->value;
723 int ret; 655 int ret;
724 656
725 opts->call_graph_enabled = !unset; 657 callchain_param.enabled = !unset;
726 658
727 /* --no-call-graph */ 659 /* --no-call-graph */
728 if (unset) { 660 if (unset) {
729 opts->call_graph = CALLCHAIN_NONE; 661 callchain_param.record_mode = CALLCHAIN_NONE;
730 pr_debug("callchain: disabled\n"); 662 pr_debug("callchain: disabled\n");
731 return 0; 663 return 0;
732 } 664 }
733 665
734 ret = record_parse_callchain(arg, opts); 666 ret = parse_callchain_record_opt(arg);
735 if (!ret) 667 if (!ret)
736 callchain_debug(opts); 668 callchain_debug();
737 669
738 return ret; 670 return ret;
739} 671}
740 672
741int record_callchain_opt(const struct option *opt, 673int record_callchain_opt(const struct option *opt __maybe_unused,
742 const char *arg __maybe_unused, 674 const char *arg __maybe_unused,
743 int unset __maybe_unused) 675 int unset __maybe_unused)
744{ 676{
745 struct record_opts *opts = opt->value; 677 callchain_param.enabled = true;
746
747 opts->call_graph_enabled = !unset;
748 678
749 if (opts->call_graph == CALLCHAIN_NONE) 679 if (callchain_param.record_mode == CALLCHAIN_NONE)
750 opts->call_graph = CALLCHAIN_FP; 680 callchain_param.record_mode = CALLCHAIN_FP;
751 681
752 callchain_debug(opts); 682 callchain_debug();
753 return 0; 683 return 0;
754} 684}
755 685
756static int perf_record_config(const char *var, const char *value, void *cb) 686static int perf_record_config(const char *var, const char *value, void *cb)
757{ 687{
758 struct record *rec = cb;
759
760 if (!strcmp(var, "record.call-graph")) 688 if (!strcmp(var, "record.call-graph"))
761 return record_parse_callchain(value, &rec->opts); 689 var = "call-graph.record-mode"; /* fall-through */
762 690
763 return perf_default_config(var, value, cb); 691 return perf_default_config(var, value, cb);
764} 692}
765 693
766static const char * const record_usage[] = { 694static const char * const __record_usage[] = {
767 "perf record [<options>] [<command>]", 695 "perf record [<options>] [<command>]",
768 "perf record [<options>] -- <command> [<options>]", 696 "perf record [<options>] -- <command> [<options>]",
769 NULL 697 NULL
770}; 698};
699const char * const *record_usage = __record_usage;
771 700
772/* 701/*
773 * XXX Ideally would be local to cmd_record() and passed to a record__new 702 * XXX Ideally would be local to cmd_record() and passed to a record__new
@@ -781,6 +710,7 @@ static const char * const record_usage[] = {
781 */ 710 */
782static struct record record = { 711static struct record record = {
783 .opts = { 712 .opts = {
713 .sample_time = true,
784 .mmap_pages = UINT_MAX, 714 .mmap_pages = UINT_MAX,
785 .user_freq = UINT_MAX, 715 .user_freq = UINT_MAX,
786 .user_interval = ULLONG_MAX, 716 .user_interval = ULLONG_MAX,
@@ -807,7 +737,7 @@ const char record_callchain_help[] = CALLCHAIN_HELP "fp";
807 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', 737 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
808 * using pipes, etc. 738 * using pipes, etc.
809 */ 739 */
810const struct option record_options[] = { 740struct option __record_options[] = {
811 OPT_CALLBACK('e', "event", &record.evlist, "event", 741 OPT_CALLBACK('e', "event", &record.evlist, "event",
812 "event selector. use 'perf list' to list available events", 742 "event selector. use 'perf list' to list available events",
813 parse_events_option), 743 parse_events_option),
@@ -881,9 +811,13 @@ const struct option record_options[] = {
881 "sample transaction flags (special events only)"), 811 "sample transaction flags (special events only)"),
882 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread, 812 OPT_BOOLEAN(0, "per-thread", &record.opts.target.per_thread,
883 "use per-thread mmaps"), 813 "use per-thread mmaps"),
814 OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
815 "Sample machine registers on interrupt"),
884 OPT_END() 816 OPT_END()
885}; 817};
886 818
819struct option *record_options = __record_options;
820
887int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) 821int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
888{ 822{
889 int err = -ENOMEM; 823 int err = -ENOMEM;
@@ -907,7 +841,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
907 usage_with_options(record_usage, record_options); 841 usage_with_options(record_usage, record_options);
908 } 842 }
909 843
910 symbol__init(); 844 symbol__init(NULL);
911 845
912 if (symbol_conf.kptr_restrict) 846 if (symbol_conf.kptr_restrict)
913 pr_warning( 847 pr_warning(
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 21d830bafff3..072ae8ad67fc 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -58,17 +58,19 @@ struct report {
58 const char *symbol_filter_str; 58 const char *symbol_filter_str;
59 float min_percent; 59 float min_percent;
60 u64 nr_entries; 60 u64 nr_entries;
61 u64 queue_size;
61 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 62 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
62}; 63};
63 64
64static int report__config(const char *var, const char *value, void *cb) 65static int report__config(const char *var, const char *value, void *cb)
65{ 66{
67 struct report *rep = cb;
68
66 if (!strcmp(var, "report.group")) { 69 if (!strcmp(var, "report.group")) {
67 symbol_conf.event_group = perf_config_bool(var, value); 70 symbol_conf.event_group = perf_config_bool(var, value);
68 return 0; 71 return 0;
69 } 72 }
70 if (!strcmp(var, "report.percent-limit")) { 73 if (!strcmp(var, "report.percent-limit")) {
71 struct report *rep = cb;
72 rep->min_percent = strtof(value, NULL); 74 rep->min_percent = strtof(value, NULL);
73 return 0; 75 return 0;
74 } 76 }
@@ -76,6 +78,10 @@ static int report__config(const char *var, const char *value, void *cb)
76 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 78 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
77 return 0; 79 return 0;
78 } 80 }
81 if (!strcmp(var, "report.queue-size")) {
82 rep->queue_size = perf_config_u64(var, value);
83 return 0;
84 }
79 85
80 return perf_default_config(var, value, cb); 86 return perf_default_config(var, value, cb);
81} 87}
@@ -220,8 +226,9 @@ static int report__setup_sample_type(struct report *rep)
220 return -EINVAL; 226 return -EINVAL;
221 } 227 }
222 if (symbol_conf.use_callchain) { 228 if (symbol_conf.use_callchain) {
223 ui__error("Selected -g but no callchain data. Did " 229 ui__error("Selected -g or --branch-history but no "
224 "you call 'perf record' without -g?\n"); 230 "callchain data. Did\n"
231 "you call 'perf record' without -g?\n");
225 return -1; 232 return -1;
226 } 233 }
227 } else if (!rep->dont_use_callchains && 234 } else if (!rep->dont_use_callchains &&
@@ -251,6 +258,13 @@ static int report__setup_sample_type(struct report *rep)
251 } 258 }
252 } 259 }
253 260
261 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
262 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
263 (sample_type & PERF_SAMPLE_STACK_USER))
264 callchain_param.record_mode = CALLCHAIN_DWARF;
265 else
266 callchain_param.record_mode = CALLCHAIN_FP;
267 }
254 return 0; 268 return 0;
255} 269}
256 270
@@ -282,12 +296,14 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
282 evname = buf; 296 evname = buf;
283 297
284 for_each_group_member(pos, evsel) { 298 for_each_group_member(pos, evsel) {
299 const struct hists *pos_hists = evsel__hists(pos);
300
285 if (symbol_conf.filter_relative) { 301 if (symbol_conf.filter_relative) {
286 nr_samples += pos->hists.stats.nr_non_filtered_samples; 302 nr_samples += pos_hists->stats.nr_non_filtered_samples;
287 nr_events += pos->hists.stats.total_non_filtered_period; 303 nr_events += pos_hists->stats.total_non_filtered_period;
288 } else { 304 } else {
289 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 305 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
290 nr_events += pos->hists.stats.total_period; 306 nr_events += pos_hists->stats.total_period;
291 } 307 }
292 } 308 }
293 } 309 }
@@ -312,7 +328,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
312 struct perf_evsel *pos; 328 struct perf_evsel *pos;
313 329
314 evlist__for_each(evlist, pos) { 330 evlist__for_each(evlist, pos) {
315 struct hists *hists = &pos->hists; 331 struct hists *hists = evsel__hists(pos);
316 const char *evname = perf_evsel__name(pos); 332 const char *evname = perf_evsel__name(pos);
317 333
318 if (symbol_conf.event_group && 334 if (symbol_conf.event_group &&
@@ -421,7 +437,7 @@ static void report__collapse_hists(struct report *rep)
421 ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); 437 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
422 438
423 evlist__for_each(rep->session->evlist, pos) { 439 evlist__for_each(rep->session->evlist, pos) {
424 struct hists *hists = &pos->hists; 440 struct hists *hists = evsel__hists(pos);
425 441
426 if (pos->idx == 0) 442 if (pos->idx == 0)
427 hists->symbol_filter_str = rep->symbol_filter_str; 443 hists->symbol_filter_str = rep->symbol_filter_str;
@@ -431,7 +447,7 @@ static void report__collapse_hists(struct report *rep)
431 /* Non-group events are considered as leader */ 447 /* Non-group events are considered as leader */
432 if (symbol_conf.event_group && 448 if (symbol_conf.event_group &&
433 !perf_evsel__is_group_leader(pos)) { 449 !perf_evsel__is_group_leader(pos)) {
434 struct hists *leader_hists = &pos->leader->hists; 450 struct hists *leader_hists = evsel__hists(pos->leader);
435 451
436 hists__match(leader_hists, hists); 452 hists__match(leader_hists, hists);
437 hists__link(leader_hists, hists); 453 hists__link(leader_hists, hists);
@@ -441,6 +457,19 @@ static void report__collapse_hists(struct report *rep)
441 ui_progress__finish(); 457 ui_progress__finish();
442} 458}
443 459
460static void report__output_resort(struct report *rep)
461{
462 struct ui_progress prog;
463 struct perf_evsel *pos;
464
465 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
466
467 evlist__for_each(rep->session->evlist, pos)
468 hists__output_resort(evsel__hists(pos), &prog);
469
470 ui_progress__finish();
471}
472
444static int __cmd_report(struct report *rep) 473static int __cmd_report(struct report *rep)
445{ 474{
446 int ret; 475 int ret;
@@ -479,6 +508,7 @@ static int __cmd_report(struct report *rep)
479 508
480 if (dump_trace) { 509 if (dump_trace) {
481 perf_session__fprintf_nr_events(session, stdout); 510 perf_session__fprintf_nr_events(session, stdout);
511 perf_evlist__fprintf_nr_events(session->evlist, stdout);
482 return 0; 512 return 0;
483 } 513 }
484 } 514 }
@@ -488,13 +518,20 @@ static int __cmd_report(struct report *rep)
488 if (session_done()) 518 if (session_done())
489 return 0; 519 return 0;
490 520
521 /*
522 * recalculate number of entries after collapsing since it
523 * might be changed during the collapse phase.
524 */
525 rep->nr_entries = 0;
526 evlist__for_each(session->evlist, pos)
527 rep->nr_entries += evsel__hists(pos)->nr_entries;
528
491 if (rep->nr_entries == 0) { 529 if (rep->nr_entries == 0) {
492 ui__error("The %s file has no samples!\n", file->path); 530 ui__error("The %s file has no samples!\n", file->path);
493 return 0; 531 return 0;
494 } 532 }
495 533
496 evlist__for_each(session->evlist, pos) 534 report__output_resort(rep);
497 hists__output_resort(&pos->hists);
498 535
499 return report__browse_hists(rep); 536 return report__browse_hists(rep);
500} 537}
@@ -559,7 +596,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
559 struct stat st; 596 struct stat st;
560 bool has_br_stack = false; 597 bool has_br_stack = false;
561 int branch_mode = -1; 598 int branch_mode = -1;
562 int ret = -1; 599 bool branch_call_mode = false;
563 char callchain_default_opt[] = "fractal,0.5,callee"; 600 char callchain_default_opt[] = "fractal,0.5,callee";
564 const char * const report_usage[] = { 601 const char * const report_usage[] = {
565 "perf report [<options>]", 602 "perf report [<options>]",
@@ -578,7 +615,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
578 .attr = perf_event__process_attr, 615 .attr = perf_event__process_attr,
579 .tracing_data = perf_event__process_tracing_data, 616 .tracing_data = perf_event__process_tracing_data,
580 .build_id = perf_event__process_build_id, 617 .build_id = perf_event__process_build_id,
581 .ordered_samples = true, 618 .ordered_events = true,
582 .ordering_requires_timestamps = true, 619 .ordering_requires_timestamps = true,
583 }, 620 },
584 .max_stack = PERF_MAX_STACK_DEPTH, 621 .max_stack = PERF_MAX_STACK_DEPTH,
@@ -622,8 +659,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
622 "regex filter to identify parent, see: '--sort parent'"), 659 "regex filter to identify parent, see: '--sort parent'"),
623 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 660 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
624 "Only display entries with parent-match"), 661 "Only display entries with parent-match"),
625 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order", 662 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order[,branch]",
626 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address). " 663 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit, callchain order, key (function or address), add branches. "
627 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt), 664 "Default: fractal,0.5,callee,function", &report_parse_callchain_opt, callchain_default_opt),
628 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 665 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
629 "Accumulate callchains of children and show total overhead as well"), 666 "Accumulate callchains of children and show total overhead as well"),
@@ -669,11 +706,16 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
669 OPT_BOOLEAN(0, "group", &symbol_conf.event_group, 706 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
670 "Show event group information together"), 707 "Show event group information together"),
671 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "", 708 OPT_CALLBACK_NOOPT('b', "branch-stack", &branch_mode, "",
672 "use branch records for histogram filling", parse_branch_mode), 709 "use branch records for per branch histogram filling",
710 parse_branch_mode),
711 OPT_BOOLEAN(0, "branch-history", &branch_call_mode,
712 "add last branch records to call history"),
673 OPT_STRING(0, "objdump", &objdump_path, "path", 713 OPT_STRING(0, "objdump", &objdump_path, "path",
674 "objdump binary to use for disassembly and annotations"), 714 "objdump binary to use for disassembly and annotations"),
675 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle, 715 OPT_BOOLEAN(0, "demangle", &symbol_conf.demangle,
676 "Disable symbol demangling"), 716 "Disable symbol demangling"),
717 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
718 "Enable kernel symbol demangling"),
677 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"), 719 OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
678 OPT_CALLBACK(0, "percent-limit", &report, "percent", 720 OPT_CALLBACK(0, "percent-limit", &report, "percent",
679 "Don't show entries under that percent", parse_percent_limit), 721 "Don't show entries under that percent", parse_percent_limit),
@@ -684,6 +726,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
684 struct perf_data_file file = { 726 struct perf_data_file file = {
685 .mode = PERF_DATA_MODE_READ, 727 .mode = PERF_DATA_MODE_READ,
686 }; 728 };
729 int ret = hists__init();
730
731 if (ret < 0)
732 return ret;
687 733
688 perf_config(report__config, &report); 734 perf_config(report__config, &report);
689 735
@@ -712,17 +758,36 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
712repeat: 758repeat:
713 session = perf_session__new(&file, false, &report.tool); 759 session = perf_session__new(&file, false, &report.tool);
714 if (session == NULL) 760 if (session == NULL)
715 return -ENOMEM; 761 return -1;
762
763 if (report.queue_size) {
764 ordered_events__set_alloc_size(&session->ordered_events,
765 report.queue_size);
766 }
716 767
717 report.session = session; 768 report.session = session;
718 769
719 has_br_stack = perf_header__has_feat(&session->header, 770 has_br_stack = perf_header__has_feat(&session->header,
720 HEADER_BRANCH_STACK); 771 HEADER_BRANCH_STACK);
721 772
722 if (branch_mode == -1 && has_br_stack) { 773 /*
774 * Branch mode is a tristate:
775 * -1 means default, so decide based on the file having branch data.
776 * 0/1 means the user chose a mode.
777 */
778 if (((branch_mode == -1 && has_br_stack) || branch_mode == 1) &&
779 branch_call_mode == -1) {
723 sort__mode = SORT_MODE__BRANCH; 780 sort__mode = SORT_MODE__BRANCH;
724 symbol_conf.cumulate_callchain = false; 781 symbol_conf.cumulate_callchain = false;
725 } 782 }
783 if (branch_call_mode) {
784 callchain_param.key = CCKEY_ADDRESS;
785 callchain_param.branch_callstack = 1;
786 symbol_conf.use_callchain = true;
787 callchain_register_param(&callchain_param);
788 if (sort_order == NULL)
789 sort_order = "srcline,symbol,dso";
790 }
726 791
727 if (report.mem_mode) { 792 if (report.mem_mode) {
728 if (sort__mode == SORT_MODE__BRANCH) { 793 if (sort__mode == SORT_MODE__BRANCH) {
@@ -787,7 +852,7 @@ repeat:
787 } 852 }
788 } 853 }
789 854
790 if (symbol__init() < 0) 855 if (symbol__init(&session->header.env) < 0)
791 goto error; 856 goto error;
792 857
793 if (argc) { 858 if (argc) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index f83c08c0dd87..891c3930080e 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -428,6 +428,7 @@ static u64 get_cpu_usage_nsec_parent(void)
428static int self_open_counters(void) 428static int self_open_counters(void)
429{ 429{
430 struct perf_event_attr attr; 430 struct perf_event_attr attr;
431 char sbuf[STRERR_BUFSIZE];
431 int fd; 432 int fd;
432 433
433 memset(&attr, 0, sizeof(attr)); 434 memset(&attr, 0, sizeof(attr));
@@ -440,7 +441,8 @@ static int self_open_counters(void)
440 441
441 if (fd < 0) 442 if (fd < 0)
442 pr_err("Error: sys_perf_event_open() syscall returned " 443 pr_err("Error: sys_perf_event_open() syscall returned "
443 "with %d (%s)\n", fd, strerror(errno)); 444 "with %d (%s)\n", fd,
445 strerror_r(errno, sbuf, sizeof(sbuf)));
444 return fd; 446 return fd;
445} 447}
446 448
@@ -1429,9 +1431,6 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1429{ 1431{
1430 int err = 0; 1432 int err = 0;
1431 1433
1432 evsel->hists.stats.total_period += sample->period;
1433 hists__inc_nr_samples(&evsel->hists, true);
1434
1435 if (evsel->handler != NULL) { 1434 if (evsel->handler != NULL) {
1436 tracepoint_handler f = evsel->handler; 1435 tracepoint_handler f = evsel->handler;
1437 err = f(tool, evsel, sample, machine); 1436 err = f(tool, evsel, sample, machine);
@@ -1462,6 +1461,8 @@ static int perf_sched__read_events(struct perf_sched *sched,
1462 return -1; 1461 return -1;
1463 } 1462 }
1464 1463
1464 symbol__init(&session->header.env);
1465
1465 if (perf_session__set_tracepoints_handlers(session, handlers)) 1466 if (perf_session__set_tracepoints_handlers(session, handlers))
1466 goto out_delete; 1467 goto out_delete;
1467 1468
@@ -1662,7 +1663,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1662 .comm = perf_event__process_comm, 1663 .comm = perf_event__process_comm,
1663 .lost = perf_event__process_lost, 1664 .lost = perf_event__process_lost,
1664 .fork = perf_sched__process_fork_event, 1665 .fork = perf_sched__process_fork_event,
1665 .ordered_samples = true, 1666 .ordered_events = true,
1666 }, 1667 },
1667 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1668 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1668 .sort_list = LIST_HEAD_INIT(sched.sort_list), 1669 .sort_list = LIST_HEAD_INIT(sched.sort_list),
@@ -1747,7 +1748,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1747 if (!strcmp(argv[0], "script")) 1748 if (!strcmp(argv[0], "script"))
1748 return cmd_script(argc, argv, prefix); 1749 return cmd_script(argc, argv, prefix);
1749 1750
1750 symbol__init();
1751 if (!strncmp(argv[0], "rec", 3)) { 1751 if (!strncmp(argv[0], "rec", 3)) {
1752 return __cmd_record(argc, argv); 1752 return __cmd_record(argc, argv);
1753 } else if (!strncmp(argv[0], "lat", 3)) { 1753 } else if (!strncmp(argv[0], "lat", 3)) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index f57035b89c15..ce304dfd962a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -23,7 +23,6 @@ static char const *generate_script_lang;
23static bool debug_mode; 23static bool debug_mode;
24static u64 last_timestamp; 24static u64 last_timestamp;
25static u64 nr_unordered; 25static u64 nr_unordered;
26extern const struct option record_options[];
27static bool no_callchain; 26static bool no_callchain;
28static bool latency_format; 27static bool latency_format;
29static bool system_wide; 28static bool system_wide;
@@ -44,6 +43,7 @@ enum perf_output_field {
44 PERF_OUTPUT_ADDR = 1U << 10, 43 PERF_OUTPUT_ADDR = 1U << 10,
45 PERF_OUTPUT_SYMOFFSET = 1U << 11, 44 PERF_OUTPUT_SYMOFFSET = 1U << 11,
46 PERF_OUTPUT_SRCLINE = 1U << 12, 45 PERF_OUTPUT_SRCLINE = 1U << 12,
46 PERF_OUTPUT_PERIOD = 1U << 13,
47}; 47};
48 48
49struct output_option { 49struct output_option {
@@ -63,6 +63,7 @@ struct output_option {
63 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 63 {.str = "addr", .field = PERF_OUTPUT_ADDR},
64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
66 {.str = "period", .field = PERF_OUTPUT_PERIOD},
66}; 67};
67 68
68/* default set to maintain compatibility with current format */ 69/* default set to maintain compatibility with current format */
@@ -80,7 +81,8 @@ static struct {
80 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 81 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
81 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 82 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
82 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 83 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
83 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 84 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
85 PERF_OUTPUT_PERIOD,
84 86
85 .invalid_fields = PERF_OUTPUT_TRACE, 87 .invalid_fields = PERF_OUTPUT_TRACE,
86 }, 88 },
@@ -91,7 +93,8 @@ static struct {
91 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 93 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
92 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 94 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
93 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 95 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
94 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 96 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
97 PERF_OUTPUT_PERIOD,
95 98
96 .invalid_fields = PERF_OUTPUT_TRACE, 99 .invalid_fields = PERF_OUTPUT_TRACE,
97 }, 100 },
@@ -110,7 +113,8 @@ static struct {
110 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 113 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
111 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 114 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
112 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 115 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
113 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 116 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
117 PERF_OUTPUT_PERIOD,
114 118
115 .invalid_fields = PERF_OUTPUT_TRACE, 119 .invalid_fields = PERF_OUTPUT_TRACE,
116 }, 120 },
@@ -184,10 +188,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
184 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP", 188 if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
185 PERF_OUTPUT_IP)) 189 PERF_OUTPUT_IP))
186 return -EINVAL; 190 return -EINVAL;
187
188 if (!no_callchain &&
189 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
190 symbol_conf.use_callchain = false;
191 } 191 }
192 192
193 if (PRINT_FIELD(ADDR) && 193 if (PRINT_FIELD(ADDR) &&
@@ -233,6 +233,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
233 PERF_OUTPUT_CPU)) 233 PERF_OUTPUT_CPU))
234 return -EINVAL; 234 return -EINVAL;
235 235
236 if (PRINT_FIELD(PERIOD) &&
237 perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
238 PERF_OUTPUT_PERIOD))
239 return -EINVAL;
240
236 return 0; 241 return 0;
237} 242}
238 243
@@ -290,6 +295,19 @@ static int perf_session__check_output_opt(struct perf_session *session)
290 set_print_ip_opts(&evsel->attr); 295 set_print_ip_opts(&evsel->attr);
291 } 296 }
292 297
298 if (!no_callchain) {
299 bool use_callchain = false;
300
301 evlist__for_each(session->evlist, evsel) {
302 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
303 use_callchain = true;
304 break;
305 }
306 }
307 if (!use_callchain)
308 symbol_conf.use_callchain = false;
309 }
310
293 /* 311 /*
294 * set default for tracepoints to print symbols only 312 * set default for tracepoints to print symbols only
295 * if callchains are present 313 * if callchains are present
@@ -360,7 +378,6 @@ static void print_sample_start(struct perf_sample *sample,
360 378
361static void print_sample_addr(union perf_event *event, 379static void print_sample_addr(union perf_event *event,
362 struct perf_sample *sample, 380 struct perf_sample *sample,
363 struct machine *machine,
364 struct thread *thread, 381 struct thread *thread,
365 struct perf_event_attr *attr) 382 struct perf_event_attr *attr)
366{ 383{
@@ -371,7 +388,7 @@ static void print_sample_addr(union perf_event *event,
371 if (!sample_addr_correlates_sym(attr)) 388 if (!sample_addr_correlates_sym(attr))
372 return; 389 return;
373 390
374 perf_event__preprocess_sample_addr(event, sample, machine, thread, &al); 391 perf_event__preprocess_sample_addr(event, sample, thread, &al);
375 392
376 if (PRINT_FIELD(SYM)) { 393 if (PRINT_FIELD(SYM)) {
377 printf(" "); 394 printf(" ");
@@ -419,7 +436,7 @@ static void print_sample_bts(union perf_event *event,
419 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 436 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
420 !output[attr->type].user_set)) { 437 !output[attr->type].user_set)) {
421 printf(" => "); 438 printf(" => ");
422 print_sample_addr(event, sample, al->machine, thread, attr); 439 print_sample_addr(event, sample, thread, attr);
423 } 440 }
424 441
425 if (print_srcline_last) 442 if (print_srcline_last)
@@ -439,6 +456,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
439 456
440 print_sample_start(sample, thread, evsel); 457 print_sample_start(sample, thread, evsel);
441 458
459 if (PRINT_FIELD(PERIOD))
460 printf("%10" PRIu64 " ", sample->period);
461
442 if (PRINT_FIELD(EVNAME)) { 462 if (PRINT_FIELD(EVNAME)) {
443 const char *evname = perf_evsel__name(evsel); 463 const char *evname = perf_evsel__name(evsel);
444 printf("%s: ", evname ? evname : "[unknown]"); 464 printf("%s: ", evname ? evname : "[unknown]");
@@ -453,7 +473,7 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
453 event_format__print(evsel->tp_format, sample->cpu, 473 event_format__print(evsel->tp_format, sample->cpu,
454 sample->raw_data, sample->raw_size); 474 sample->raw_data, sample->raw_size);
455 if (PRINT_FIELD(ADDR)) 475 if (PRINT_FIELD(ADDR))
456 print_sample_addr(event, sample, al->machine, thread, attr); 476 print_sample_addr(event, sample, thread, attr);
457 477
458 if (PRINT_FIELD(IP)) { 478 if (PRINT_FIELD(IP)) {
459 if (!symbol_conf.use_callchain) 479 if (!symbol_conf.use_callchain)
@@ -476,6 +496,11 @@ static int default_start_script(const char *script __maybe_unused,
476 return 0; 496 return 0;
477} 497}
478 498
499static int default_flush_script(void)
500{
501 return 0;
502}
503
479static int default_stop_script(void) 504static int default_stop_script(void)
480{ 505{
481 return 0; 506 return 0;
@@ -489,6 +514,7 @@ static int default_generate_script(struct pevent *pevent __maybe_unused,
489 514
490static struct scripting_ops default_scripting_ops = { 515static struct scripting_ops default_scripting_ops = {
491 .start_script = default_start_script, 516 .start_script = default_start_script,
517 .flush_script = default_flush_script,
492 .stop_script = default_stop_script, 518 .stop_script = default_stop_script,
493 .process_event = process_event, 519 .process_event = process_event,
494 .generate_script = default_generate_script, 520 .generate_script = default_generate_script,
@@ -504,6 +530,11 @@ static void setup_scripting(void)
504 scripting_ops = &default_scripting_ops; 530 scripting_ops = &default_scripting_ops;
505} 531}
506 532
533static int flush_scripting(void)
534{
535 return scripting_ops->flush_script();
536}
537
507static int cleanup_scripting(void) 538static int cleanup_scripting(void)
508{ 539{
509 pr_debug("\nperf script stopped\n"); 540 pr_debug("\nperf script stopped\n");
@@ -552,7 +583,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
552 583
553 scripting_ops->process_event(event, sample, evsel, thread, &al); 584 scripting_ops->process_event(event, sample, evsel, thread, &al);
554 585
555 evsel->hists.stats.total_period += sample->period;
556 return 0; 586 return 0;
557} 587}
558 588
@@ -1471,12 +1501,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1471 bool show_full_info = false; 1501 bool show_full_info = false;
1472 bool header = false; 1502 bool header = false;
1473 bool header_only = false; 1503 bool header_only = false;
1504 bool script_started = false;
1474 char *rec_script_path = NULL; 1505 char *rec_script_path = NULL;
1475 char *rep_script_path = NULL; 1506 char *rep_script_path = NULL;
1476 struct perf_session *session; 1507 struct perf_session *session;
1477 char *script_path = NULL; 1508 char *script_path = NULL;
1478 const char **__argv; 1509 const char **__argv;
1479 int i, j, err; 1510 int i, j, err = 0;
1480 struct perf_script script = { 1511 struct perf_script script = {
1481 .tool = { 1512 .tool = {
1482 .sample = process_sample_event, 1513 .sample = process_sample_event,
@@ -1488,7 +1519,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1488 .attr = process_attr, 1519 .attr = process_attr,
1489 .tracing_data = perf_event__process_tracing_data, 1520 .tracing_data = perf_event__process_tracing_data,
1490 .build_id = perf_event__process_build_id, 1521 .build_id = perf_event__process_build_id,
1491 .ordered_samples = true, 1522 .ordered_events = true,
1492 .ordering_requires_timestamps = true, 1523 .ordering_requires_timestamps = true,
1493 }, 1524 },
1494 }; 1525 };
@@ -1523,7 +1554,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1523 "comma separated output fields prepend with 'type:'. " 1554 "comma separated output fields prepend with 'type:'. "
1524 "Valid types: hw,sw,trace,raw. " 1555 "Valid types: hw,sw,trace,raw. "
1525 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1556 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1526 "addr,symoff", parse_output_fields), 1557 "addr,symoff,period", parse_output_fields),
1527 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1558 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1528 "system-wide collection from all CPUs"), 1559 "system-wide collection from all CPUs"),
1529 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1560 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -1718,26 +1749,28 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1718 exit(-1); 1749 exit(-1);
1719 } 1750 }
1720 1751
1721 if (symbol__init() < 0)
1722 return -1;
1723 if (!script_name) 1752 if (!script_name)
1724 setup_pager(); 1753 setup_pager();
1725 1754
1726 session = perf_session__new(&file, false, &script.tool); 1755 session = perf_session__new(&file, false, &script.tool);
1727 if (session == NULL) 1756 if (session == NULL)
1728 return -ENOMEM; 1757 return -1;
1729 1758
1730 if (header || header_only) { 1759 if (header || header_only) {
1731 perf_session__fprintf_info(session, stdout, show_full_info); 1760 perf_session__fprintf_info(session, stdout, show_full_info);
1732 if (header_only) 1761 if (header_only)
1733 return 0; 1762 goto out_delete;
1734 } 1763 }
1735 1764
1765 if (symbol__init(&session->header.env) < 0)
1766 goto out_delete;
1767
1736 script.session = session; 1768 script.session = session;
1737 1769
1738 if (cpu_list) { 1770 if (cpu_list) {
1739 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap)) 1771 err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
1740 return -1; 1772 if (err < 0)
1773 goto out_delete;
1741 } 1774 }
1742 1775
1743 if (!no_callchain) 1776 if (!no_callchain)
@@ -1752,53 +1785,62 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1752 if (output_set_by_user()) { 1785 if (output_set_by_user()) {
1753 fprintf(stderr, 1786 fprintf(stderr,
1754 "custom fields not supported for generated scripts"); 1787 "custom fields not supported for generated scripts");
1755 return -1; 1788 err = -EINVAL;
1789 goto out_delete;
1756 } 1790 }
1757 1791
1758 input = open(file.path, O_RDONLY); /* input_name */ 1792 input = open(file.path, O_RDONLY); /* input_name */
1759 if (input < 0) { 1793 if (input < 0) {
1794 err = -errno;
1760 perror("failed to open file"); 1795 perror("failed to open file");
1761 return -1; 1796 goto out_delete;
1762 } 1797 }
1763 1798
1764 err = fstat(input, &perf_stat); 1799 err = fstat(input, &perf_stat);
1765 if (err < 0) { 1800 if (err < 0) {
1766 perror("failed to stat file"); 1801 perror("failed to stat file");
1767 return -1; 1802 goto out_delete;
1768 } 1803 }
1769 1804
1770 if (!perf_stat.st_size) { 1805 if (!perf_stat.st_size) {
1771 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1806 fprintf(stderr, "zero-sized file, nothing to do!\n");
1772 return 0; 1807 goto out_delete;
1773 } 1808 }
1774 1809
1775 scripting_ops = script_spec__lookup(generate_script_lang); 1810 scripting_ops = script_spec__lookup(generate_script_lang);
1776 if (!scripting_ops) { 1811 if (!scripting_ops) {
1777 fprintf(stderr, "invalid language specifier"); 1812 fprintf(stderr, "invalid language specifier");
1778 return -1; 1813 err = -ENOENT;
1814 goto out_delete;
1779 } 1815 }
1780 1816
1781 err = scripting_ops->generate_script(session->tevent.pevent, 1817 err = scripting_ops->generate_script(session->tevent.pevent,
1782 "perf-script"); 1818 "perf-script");
1783 goto out; 1819 goto out_delete;
1784 } 1820 }
1785 1821
1786 if (script_name) { 1822 if (script_name) {
1787 err = scripting_ops->start_script(script_name, argc, argv); 1823 err = scripting_ops->start_script(script_name, argc, argv);
1788 if (err) 1824 if (err)
1789 goto out; 1825 goto out_delete;
1790 pr_debug("perf script started with script %s\n\n", script_name); 1826 pr_debug("perf script started with script %s\n\n", script_name);
1827 script_started = true;
1791 } 1828 }
1792 1829
1793 1830
1794 err = perf_session__check_output_opt(session); 1831 err = perf_session__check_output_opt(session);
1795 if (err < 0) 1832 if (err < 0)
1796 goto out; 1833 goto out_delete;
1797 1834
1798 err = __cmd_script(&script); 1835 err = __cmd_script(&script);
1799 1836
1837 flush_scripting();
1838
1839out_delete:
1800 perf_session__delete(session); 1840 perf_session__delete(session);
1801 cleanup_scripting(); 1841
1842 if (script_started)
1843 cleanup_scripting();
1802out: 1844out:
1803 return err; 1845 return err;
1804} 1846}
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3e80aa10cfd8..891086376381 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
43 43
44#include "perf.h" 44#include "perf.h"
45#include "builtin.h" 45#include "builtin.h"
46#include "util/cgroup.h"
46#include "util/util.h" 47#include "util/util.h"
47#include "util/parse-options.h" 48#include "util/parse-options.h"
48#include "util/parse-events.h" 49#include "util/parse-events.h"
@@ -387,20 +388,102 @@ static void update_shadow_stats(struct perf_evsel *counter, u64 *count)
387 update_stats(&runtime_itlb_cache_stats[0], count[0]); 388 update_stats(&runtime_itlb_cache_stats[0], count[0]);
388} 389}
389 390
391static void zero_per_pkg(struct perf_evsel *counter)
392{
393 if (counter->per_pkg_mask)
394 memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
395}
396
397static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
398{
399 unsigned long *mask = counter->per_pkg_mask;
400 struct cpu_map *cpus = perf_evsel__cpus(counter);
401 int s;
402
403 *skip = false;
404
405 if (!counter->per_pkg)
406 return 0;
407
408 if (cpu_map__empty(cpus))
409 return 0;
410
411 if (!mask) {
412 mask = zalloc(MAX_NR_CPUS);
413 if (!mask)
414 return -ENOMEM;
415
416 counter->per_pkg_mask = mask;
417 }
418
419 s = cpu_map__get_socket(cpus, cpu);
420 if (s < 0)
421 return -1;
422
423 *skip = test_and_set_bit(s, mask) == 1;
424 return 0;
425}
426
427static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
428 struct perf_counts_values *count)
429{
430 struct perf_counts_values *aggr = &evsel->counts->aggr;
431 static struct perf_counts_values zero;
432 bool skip = false;
433
434 if (check_per_pkg(evsel, cpu, &skip)) {
435 pr_err("failed to read per-pkg counter\n");
436 return -1;
437 }
438
439 if (skip)
440 count = &zero;
441
442 switch (aggr_mode) {
443 case AGGR_CORE:
444 case AGGR_SOCKET:
445 case AGGR_NONE:
446 if (!evsel->snapshot)
447 perf_evsel__compute_deltas(evsel, cpu, count);
448 perf_counts_values__scale(count, scale, NULL);
449 evsel->counts->cpu[cpu] = *count;
450 update_shadow_stats(evsel, count->values);
451 break;
452 case AGGR_GLOBAL:
453 aggr->val += count->val;
454 if (scale) {
455 aggr->ena += count->ena;
456 aggr->run += count->run;
457 }
458 default:
459 break;
460 }
461
462 return 0;
463}
464
465static int read_counter(struct perf_evsel *counter);
466
390/* 467/*
391 * Read out the results of a single counter: 468 * Read out the results of a single counter:
392 * aggregate counts across CPUs in system-wide mode 469 * aggregate counts across CPUs in system-wide mode
393 */ 470 */
394static int read_counter_aggr(struct perf_evsel *counter) 471static int read_counter_aggr(struct perf_evsel *counter)
395{ 472{
473 struct perf_counts_values *aggr = &counter->counts->aggr;
396 struct perf_stat *ps = counter->priv; 474 struct perf_stat *ps = counter->priv;
397 u64 *count = counter->counts->aggr.values; 475 u64 *count = counter->counts->aggr.values;
398 int i; 476 int i;
399 477
400 if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter), 478 aggr->val = aggr->ena = aggr->run = 0;
401 thread_map__nr(evsel_list->threads), scale) < 0) 479
480 if (read_counter(counter))
402 return -1; 481 return -1;
403 482
483 if (!counter->snapshot)
484 perf_evsel__compute_deltas(counter, -1, aggr);
485 perf_counts_values__scale(aggr, scale, &counter->counts->scaled);
486
404 for (i = 0; i < 3; i++) 487 for (i = 0; i < 3; i++)
405 update_stats(&ps->res_stats[i], count[i]); 488 update_stats(&ps->res_stats[i], count[i]);
406 489
@@ -423,16 +506,21 @@ static int read_counter_aggr(struct perf_evsel *counter)
423 */ 506 */
424static int read_counter(struct perf_evsel *counter) 507static int read_counter(struct perf_evsel *counter)
425{ 508{
426 u64 *count; 509 int nthreads = thread_map__nr(evsel_list->threads);
427 int cpu; 510 int ncpus = perf_evsel__nr_cpus(counter);
511 int cpu, thread;
428 512
429 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 513 if (counter->system_wide)
430 if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0) 514 nthreads = 1;
431 return -1;
432 515
433 count = counter->counts->cpu[cpu].values; 516 if (counter->per_pkg)
517 zero_per_pkg(counter);
434 518
435 update_shadow_stats(counter, count); 519 for (thread = 0; thread < nthreads; thread++) {
520 for (cpu = 0; cpu < ncpus; cpu++) {
521 if (perf_evsel__read_cb(counter, cpu, thread, read_cb))
522 return -1;
523 }
436 } 524 }
437 525
438 return 0; 526 return 0;
@@ -593,7 +681,7 @@ static int __run_perf_stat(int argc, const char **argv)
593 681
594 if (perf_evlist__apply_filters(evsel_list)) { 682 if (perf_evlist__apply_filters(evsel_list)) {
595 error("failed to set filter with %d (%s)\n", errno, 683 error("failed to set filter with %d (%s)\n", errno,
596 strerror(errno)); 684 strerror_r(errno, msg, sizeof(msg)));
597 return -1; 685 return -1;
598 } 686 }
599 687
@@ -732,7 +820,7 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
732 } 820 }
733} 821}
734 822
735static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 823static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
736{ 824{
737 double msecs = avg / 1e6; 825 double msecs = avg / 1e6;
738 const char *fmt_v, *fmt_n; 826 const char *fmt_v, *fmt_n;
@@ -741,7 +829,7 @@ static void nsec_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
741 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s"; 829 fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
742 fmt_n = csv_output ? "%s" : "%-25s"; 830 fmt_n = csv_output ? "%s" : "%-25s";
743 831
744 aggr_printout(evsel, cpu, nr); 832 aggr_printout(evsel, id, nr);
745 833
746 scnprintf(name, sizeof(name), "%s%s", 834 scnprintf(name, sizeof(name), "%s%s",
747 perf_evsel__name(evsel), csv_output ? "" : " (msec)"); 835 perf_evsel__name(evsel), csv_output ? "" : " (msec)");
@@ -947,11 +1035,12 @@ static void print_ll_cache_misses(int cpu,
947 fprintf(output, " of all LL-cache hits "); 1035 fprintf(output, " of all LL-cache hits ");
948} 1036}
949 1037
950static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg) 1038static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
951{ 1039{
952 double total, ratio = 0.0, total2; 1040 double total, ratio = 0.0, total2;
953 double sc = evsel->scale; 1041 double sc = evsel->scale;
954 const char *fmt; 1042 const char *fmt;
1043 int cpu = cpu_map__id_to_cpu(id);
955 1044
956 if (csv_output) { 1045 if (csv_output) {
957 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 1046 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s";
@@ -962,7 +1051,7 @@ static void abs_printout(int cpu, int nr, struct perf_evsel *evsel, double avg)
962 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; 1051 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s";
963 } 1052 }
964 1053
965 aggr_printout(evsel, cpu, nr); 1054 aggr_printout(evsel, id, nr);
966 1055
967 if (aggr_mode == AGGR_GLOBAL) 1056 if (aggr_mode == AGGR_GLOBAL)
968 cpu = 0; 1057 cpu = 0;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 2f1a5220c090..f3bb1a4bf060 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -528,7 +528,7 @@ static const char *cat_backtrace(union perf_event *event,
528 } 528 }
529 529
530 tal.filtered = 0; 530 tal.filtered = 0;
531 thread__find_addr_location(al.thread, machine, cpumode, 531 thread__find_addr_location(al.thread, cpumode,
532 MAP__FUNCTION, ip, &tal); 532 MAP__FUNCTION, ip, &tal);
533 533
534 if (tal.sym) 534 if (tal.sym)
@@ -1605,7 +1605,9 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1605 int ret = -EINVAL; 1605 int ret = -EINVAL;
1606 1606
1607 if (session == NULL) 1607 if (session == NULL)
1608 return -ENOMEM; 1608 return -1;
1609
1610 symbol__init(&session->header.env);
1609 1611
1610 (void)perf_header__process_sections(&session->header, 1612 (void)perf_header__process_sections(&session->header,
1611 perf_data_file__fd(session->file), 1613 perf_data_file__fd(session->file),
@@ -1920,7 +1922,7 @@ int cmd_timechart(int argc, const char **argv,
1920 .fork = process_fork_event, 1922 .fork = process_fork_event,
1921 .exit = process_exit_event, 1923 .exit = process_exit_event,
1922 .sample = process_sample_event, 1924 .sample = process_sample_event,
1923 .ordered_samples = true, 1925 .ordered_events = true,
1924 }, 1926 },
1925 .proc_num = 15, 1927 .proc_num = 15,
1926 .min_time = 1000000, 1928 .min_time = 1000000,
@@ -1961,7 +1963,7 @@ int cmd_timechart(int argc, const char **argv,
1961 NULL 1963 NULL
1962 }; 1964 };
1963 1965
1964 const struct option record_options[] = { 1966 const struct option timechart_record_options[] = {
1965 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"), 1967 OPT_BOOLEAN('P', "power-only", &tchart.power_only, "output power data only"),
1966 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only, 1968 OPT_BOOLEAN('T', "tasks-only", &tchart.tasks_only,
1967 "output processes data only"), 1969 "output processes data only"),
@@ -1970,7 +1972,7 @@ int cmd_timechart(int argc, const char **argv,
1970 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"), 1972 OPT_BOOLEAN('g', "callchain", &tchart.with_backtrace, "record callchain"),
1971 OPT_END() 1973 OPT_END()
1972 }; 1974 };
1973 const char * const record_usage[] = { 1975 const char * const timechart_record_usage[] = {
1974 "perf timechart record [<options>]", 1976 "perf timechart record [<options>]",
1975 NULL 1977 NULL
1976 }; 1978 };
@@ -1982,10 +1984,9 @@ int cmd_timechart(int argc, const char **argv,
1982 return -1; 1984 return -1;
1983 } 1985 }
1984 1986
1985 symbol__init();
1986
1987 if (argc && !strncmp(argv[0], "rec", 3)) { 1987 if (argc && !strncmp(argv[0], "rec", 3)) {
1988 argc = parse_options(argc, argv, record_options, record_usage, 1988 argc = parse_options(argc, argv, timechart_record_options,
1989 timechart_record_usage,
1989 PARSE_OPT_STOP_AT_NON_OPTION); 1990 PARSE_OPT_STOP_AT_NON_OPTION);
1990 1991
1991 if (tchart.power_only && tchart.tasks_only) { 1992 if (tchart.power_only && tchart.tasks_only) {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 377971dc89a3..961cea183a83 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -59,7 +59,7 @@
59 59
60#include <sys/syscall.h> 60#include <sys/syscall.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/poll.h> 62#include <poll.h>
63#include <sys/prctl.h> 63#include <sys/prctl.h>
64#include <sys/wait.h> 64#include <sys/wait.h>
65#include <sys/uio.h> 65#include <sys/uio.h>
@@ -251,6 +251,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
251 char bf[160]; 251 char bf[160];
252 int printed = 0; 252 int printed = 0;
253 const int win_width = top->winsize.ws_col - 1; 253 const int win_width = top->winsize.ws_col - 1;
254 struct hists *hists = evsel__hists(top->sym_evsel);
254 255
255 puts(CONSOLE_CLEAR); 256 puts(CONSOLE_CLEAR);
256 257
@@ -261,13 +262,13 @@ static void perf_top__print_sym_table(struct perf_top *top)
261 262
262 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 263 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
263 264
264 if (top->sym_evsel->hists.stats.nr_lost_warned != 265 if (hists->stats.nr_lost_warned !=
265 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) { 266 hists->stats.nr_events[PERF_RECORD_LOST]) {
266 top->sym_evsel->hists.stats.nr_lost_warned = 267 hists->stats.nr_lost_warned =
267 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 268 hists->stats.nr_events[PERF_RECORD_LOST];
268 color_fprintf(stdout, PERF_COLOR_RED, 269 color_fprintf(stdout, PERF_COLOR_RED,
269 "WARNING: LOST %d chunks, Check IO/CPU overload", 270 "WARNING: LOST %d chunks, Check IO/CPU overload",
270 top->sym_evsel->hists.stats.nr_lost_warned); 271 hists->stats.nr_lost_warned);
271 ++printed; 272 ++printed;
272 } 273 }
273 274
@@ -276,16 +277,19 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 277 return;
277 } 278 }
278 279
279 hists__collapse_resort(&top->sym_evsel->hists, NULL); 280 if (top->zero) {
280 hists__output_resort(&top->sym_evsel->hists); 281 hists__delete_entries(hists);
281 hists__decay_entries(&top->sym_evsel->hists, 282 } else {
282 top->hide_user_symbols, 283 hists__decay_entries(hists, top->hide_user_symbols,
283 top->hide_kernel_symbols); 284 top->hide_kernel_symbols);
284 hists__output_recalc_col_len(&top->sym_evsel->hists, 285 }
285 top->print_entries - printed); 286
287 hists__collapse_resort(hists, NULL);
288 hists__output_resort(hists, NULL);
289
290 hists__output_recalc_col_len(hists, top->print_entries - printed);
286 putchar('\n'); 291 putchar('\n');
287 hists__fprintf(&top->sym_evsel->hists, false, 292 hists__fprintf(hists, false, top->print_entries - printed, win_width,
288 top->print_entries - printed, win_width,
289 top->min_percent, stdout); 293 top->min_percent, stdout);
290} 294}
291 295
@@ -328,6 +332,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
328{ 332{
329 char *buf = malloc(0), *p; 333 char *buf = malloc(0), *p;
330 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL; 334 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
335 struct hists *hists = evsel__hists(top->sym_evsel);
331 struct rb_node *next; 336 struct rb_node *next;
332 size_t dummy = 0; 337 size_t dummy = 0;
333 338
@@ -345,7 +350,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
345 if (p) 350 if (p)
346 *p = 0; 351 *p = 0;
347 352
348 next = rb_first(&top->sym_evsel->hists.entries); 353 next = rb_first(&hists->entries);
349 while (next) { 354 while (next) {
350 n = rb_entry(next, struct hist_entry, rb_node); 355 n = rb_entry(next, struct hist_entry, rb_node);
351 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) { 356 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
@@ -427,18 +432,13 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
427 432
428 if (!perf_top__key_mapped(top, c)) { 433 if (!perf_top__key_mapped(top, c)) {
429 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 434 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
430 struct termios tc, save; 435 struct termios save;
431 436
432 perf_top__print_mapped_keys(top); 437 perf_top__print_mapped_keys(top);
433 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 438 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
434 fflush(stdout); 439 fflush(stdout);
435 440
436 tcgetattr(0, &save); 441 set_term_quiet_input(&save);
437 tc = save;
438 tc.c_lflag &= ~(ICANON | ECHO);
439 tc.c_cc[VMIN] = 0;
440 tc.c_cc[VTIME] = 0;
441 tcsetattr(0, TCSANOW, &tc);
442 442
443 poll(&stdin_poll, 1, -1); 443 poll(&stdin_poll, 1, -1);
444 c = getc(stdin); 444 c = getc(stdin);
@@ -537,16 +537,24 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
537static void perf_top__sort_new_samples(void *arg) 537static void perf_top__sort_new_samples(void *arg)
538{ 538{
539 struct perf_top *t = arg; 539 struct perf_top *t = arg;
540 struct hists *hists;
541
540 perf_top__reset_sample_counters(t); 542 perf_top__reset_sample_counters(t);
541 543
542 if (t->evlist->selected != NULL) 544 if (t->evlist->selected != NULL)
543 t->sym_evsel = t->evlist->selected; 545 t->sym_evsel = t->evlist->selected;
544 546
545 hists__collapse_resort(&t->sym_evsel->hists, NULL); 547 hists = evsel__hists(t->sym_evsel);
546 hists__output_resort(&t->sym_evsel->hists); 548
547 hists__decay_entries(&t->sym_evsel->hists, 549 if (t->zero) {
548 t->hide_user_symbols, 550 hists__delete_entries(hists);
549 t->hide_kernel_symbols); 551 } else {
552 hists__decay_entries(hists, t->hide_user_symbols,
553 t->hide_kernel_symbols);
554 }
555
556 hists__collapse_resort(hists, NULL);
557 hists__output_resort(hists, NULL);
550} 558}
551 559
552static void *display_thread_tui(void *arg) 560static void *display_thread_tui(void *arg)
@@ -567,8 +575,10 @@ static void *display_thread_tui(void *arg)
567 * Zooming in/out UIDs. For now juse use whatever the user passed 575 * Zooming in/out UIDs. For now juse use whatever the user passed
568 * via --uid. 576 * via --uid.
569 */ 577 */
570 evlist__for_each(top->evlist, pos) 578 evlist__for_each(top->evlist, pos) {
571 pos->hists.uid_filter_str = top->record_opts.target.uid_str; 579 struct hists *hists = evsel__hists(pos);
580 hists->uid_filter_str = top->record_opts.target.uid_str;
581 }
572 582
573 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, 583 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
574 &top->session->header.env); 584 &top->session->header.env);
@@ -577,23 +587,32 @@ static void *display_thread_tui(void *arg)
577 return NULL; 587 return NULL;
578} 588}
579 589
590static void display_sig(int sig __maybe_unused)
591{
592 done = 1;
593}
594
595static void display_setup_sig(void)
596{
597 signal(SIGSEGV, display_sig);
598 signal(SIGFPE, display_sig);
599 signal(SIGINT, display_sig);
600 signal(SIGQUIT, display_sig);
601 signal(SIGTERM, display_sig);
602}
603
580static void *display_thread(void *arg) 604static void *display_thread(void *arg)
581{ 605{
582 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 606 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
583 struct termios tc, save; 607 struct termios save;
584 struct perf_top *top = arg; 608 struct perf_top *top = arg;
585 int delay_msecs, c; 609 int delay_msecs, c;
586 610
587 tcgetattr(0, &save); 611 display_setup_sig();
588 tc = save;
589 tc.c_lflag &= ~(ICANON | ECHO);
590 tc.c_cc[VMIN] = 0;
591 tc.c_cc[VTIME] = 0;
592
593 pthread__unblock_sigwinch(); 612 pthread__unblock_sigwinch();
594repeat: 613repeat:
595 delay_msecs = top->delay_secs * 1000; 614 delay_msecs = top->delay_secs * 1000;
596 tcsetattr(0, TCSANOW, &tc); 615 set_term_quiet_input(&save);
597 /* trash return*/ 616 /* trash return*/
598 getc(stdin); 617 getc(stdin);
599 618
@@ -620,13 +639,16 @@ repeat:
620 } 639 }
621 } 640 }
622 641
642 tcsetattr(0, TCSAFLUSH, &save);
623 return NULL; 643 return NULL;
624} 644}
625 645
626static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) 646static int symbol_filter(struct map *map, struct symbol *sym)
627{ 647{
628 const char *name = sym->name; 648 const char *name = sym->name;
629 649
650 if (!map->dso->kernel)
651 return 0;
630 /* 652 /*
631 * ppc64 uses function descriptors and appends a '.' to the 653 * ppc64 uses function descriptors and appends a '.' to the
632 * start of every instruction address. Remove it. 654 * start of every instruction address. Remove it.
@@ -750,6 +772,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
750 } 772 }
751 773
752 if (al.sym == NULL || !al.sym->ignore) { 774 if (al.sym == NULL || !al.sym->ignore) {
775 struct hists *hists = evsel__hists(evsel);
753 struct hist_entry_iter iter = { 776 struct hist_entry_iter iter = {
754 .add_entry_cb = hist_iter__top_callback, 777 .add_entry_cb = hist_iter__top_callback,
755 }; 778 };
@@ -759,14 +782,14 @@ static void perf_event__process_sample(struct perf_tool *tool,
759 else 782 else
760 iter.ops = &hist_iter_normal; 783 iter.ops = &hist_iter_normal;
761 784
762 pthread_mutex_lock(&evsel->hists.lock); 785 pthread_mutex_lock(&hists->lock);
763 786
764 err = hist_entry_iter__add(&iter, &al, evsel, sample, 787 err = hist_entry_iter__add(&iter, &al, evsel, sample,
765 top->max_stack, top); 788 top->max_stack, top);
766 if (err < 0) 789 if (err < 0)
767 pr_err("Problem incrementing symbol period, skipping event\n"); 790 pr_err("Problem incrementing symbol period, skipping event\n");
768 791
769 pthread_mutex_unlock(&evsel->hists.lock); 792 pthread_mutex_unlock(&hists->lock);
770 } 793 }
771 794
772 return; 795 return;
@@ -831,7 +854,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
831 perf_event__process_sample(&top->tool, event, evsel, 854 perf_event__process_sample(&top->tool, event, evsel,
832 &sample, machine); 855 &sample, machine);
833 } else if (event->header.type < PERF_RECORD_MAX) { 856 } else if (event->header.type < PERF_RECORD_MAX) {
834 hists__inc_nr_events(&evsel->hists, event->header.type); 857 hists__inc_nr_events(evsel__hists(evsel), event->header.type);
835 machine__process_event(machine, event, &sample); 858 machine__process_event(machine, event, &sample);
836 } else 859 } else
837 ++session->stats.nr_unknown_events; 860 ++session->stats.nr_unknown_events;
@@ -876,7 +899,7 @@ try_again:
876 899
877 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 900 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
878 ui__error("Failed to mmap with %d (%s)\n", 901 ui__error("Failed to mmap with %d (%s)\n",
879 errno, strerror(errno)); 902 errno, strerror_r(errno, msg, sizeof(msg)));
880 goto out_err; 903 goto out_err;
881 } 904 }
882 905
@@ -911,7 +934,7 @@ static int __cmd_top(struct perf_top *top)
911 934
912 top->session = perf_session__new(NULL, false, NULL); 935 top->session = perf_session__new(NULL, false, NULL);
913 if (top->session == NULL) 936 if (top->session == NULL)
914 return -ENOMEM; 937 return -1;
915 938
916 machines__set_symbol_filter(&top->session->machines, symbol_filter); 939 machines__set_symbol_filter(&top->session->machines, symbol_filter);
917 940
@@ -946,7 +969,7 @@ static int __cmd_top(struct perf_top *top)
946 perf_evlist__enable(top->evlist); 969 perf_evlist__enable(top->evlist);
947 970
948 /* Wait for a minimal set of events before starting the snapshot */ 971 /* Wait for a minimal set of events before starting the snapshot */
949 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 972 perf_evlist__poll(top->evlist, 100);
950 973
951 perf_top__mmap_read(top); 974 perf_top__mmap_read(top);
952 975
@@ -963,7 +986,7 @@ static int __cmd_top(struct perf_top *top)
963 param.sched_priority = top->realtime_prio; 986 param.sched_priority = top->realtime_prio;
964 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 987 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
965 ui__error("Could not set realtime priority.\n"); 988 ui__error("Could not set realtime priority.\n");
966 goto out_delete; 989 goto out_join;
967 } 990 }
968 } 991 }
969 992
@@ -973,10 +996,12 @@ static int __cmd_top(struct perf_top *top)
973 perf_top__mmap_read(top); 996 perf_top__mmap_read(top);
974 997
975 if (hits == top->samples) 998 if (hits == top->samples)
976 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 999 ret = perf_evlist__poll(top->evlist, 100);
977 } 1000 }
978 1001
979 ret = 0; 1002 ret = 0;
1003out_join:
1004 pthread_join(thread, NULL);
980out_delete: 1005out_delete:
981 perf_session__delete(top->session); 1006 perf_session__delete(top->session);
982 top->session = NULL; 1007 top->session = NULL;
@@ -1000,10 +1025,8 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1000 1025
1001static int perf_top_config(const char *var, const char *value, void *cb) 1026static int perf_top_config(const char *var, const char *value, void *cb)
1002{ 1027{
1003 struct perf_top *top = cb;
1004
1005 if (!strcmp(var, "top.call-graph")) 1028 if (!strcmp(var, "top.call-graph"))
1006 return record_parse_callchain(value, &top->record_opts); 1029 var = "call-graph.record-mode"; /* fall-through */
1007 if (!strcmp(var, "top.children")) { 1030 if (!strcmp(var, "top.children")) {
1008 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1031 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1009 return 0; 1032 return 0;
@@ -1024,7 +1047,6 @@ parse_percent_limit(const struct option *opt, const char *arg,
1024 1047
1025int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1048int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1026{ 1049{
1027 int status = -1;
1028 char errbuf[BUFSIZ]; 1050 char errbuf[BUFSIZ];
1029 struct perf_top top = { 1051 struct perf_top top = {
1030 .count_filter = 5, 1052 .count_filter = 5,
@@ -1122,6 +1144,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1122 "Interleave source code with assembly code (default)"), 1144 "Interleave source code with assembly code (default)"),
1123 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1145 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
1124 "Display raw encoding of assembly instructions (default)"), 1146 "Display raw encoding of assembly instructions (default)"),
1147 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1148 "Enable kernel symbol demangling"),
1125 OPT_STRING(0, "objdump", &objdump_path, "path", 1149 OPT_STRING(0, "objdump", &objdump_path, "path",
1126 "objdump binary to use for disassembly and annotations"), 1150 "objdump binary to use for disassembly and annotations"),
1127 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1151 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
@@ -1131,12 +1155,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1131 "Don't show entries under that percent", parse_percent_limit), 1155 "Don't show entries under that percent", parse_percent_limit),
1132 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1156 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1133 "How to display percentage of filtered entries", parse_filter_percentage), 1157 "How to display percentage of filtered entries", parse_filter_percentage),
1158 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1159 "width[,width...]",
1160 "don't try to adjust column width, use these fixed values"),
1134 OPT_END() 1161 OPT_END()
1135 }; 1162 };
1136 const char * const top_usage[] = { 1163 const char * const top_usage[] = {
1137 "perf top [<options>]", 1164 "perf top [<options>]",
1138 NULL 1165 NULL
1139 }; 1166 };
1167 int status = hists__init();
1168
1169 if (status < 0)
1170 return status;
1140 1171
1141 top.evlist = perf_evlist__new(); 1172 top.evlist = perf_evlist__new();
1142 if (top.evlist == NULL) 1173 if (top.evlist == NULL)
@@ -1217,7 +1248,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1217 symbol_conf.priv_size = sizeof(struct annotation); 1248 symbol_conf.priv_size = sizeof(struct annotation);
1218 1249
1219 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1250 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1220 if (symbol__init() < 0) 1251 if (symbol__init(NULL) < 0)
1221 return -1; 1252 return -1;
1222 1253
1223 sort__setup_elide(stdout); 1254 sort__setup_elide(stdout);
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index a6c375224f46..badfabc6a01f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -402,6 +402,31 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
402 402
403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags 403#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
404 404
405static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
406 struct syscall_arg *arg)
407{
408 int printed = 0, flags = arg->val;
409
410#define P_MREMAP_FLAG(n) \
411 if (flags & MREMAP_##n) { \
412 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
413 flags &= ~MREMAP_##n; \
414 }
415
416 P_MREMAP_FLAG(MAYMOVE);
417#ifdef MREMAP_FIXED
418 P_MREMAP_FLAG(FIXED);
419#endif
420#undef P_MREMAP_FLAG
421
422 if (flags)
423 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
424
425 return printed;
426}
427
428#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
429
405static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 430static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
406 struct syscall_arg *arg) 431 struct syscall_arg *arg)
407{ 432{
@@ -1004,6 +1029,7 @@ static struct syscall_fmt {
1004 [2] = SCA_MMAP_PROT, /* prot */ }, }, 1029 [2] = SCA_MMAP_PROT, /* prot */ }, },
1005 { .name = "mremap", .hexret = true, 1030 { .name = "mremap", .hexret = true,
1006 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 1031 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1032 [3] = SCA_MREMAP_FLAGS, /* flags */
1007 [4] = SCA_HEX, /* new_addr */ }, }, 1033 [4] = SCA_HEX, /* new_addr */ }, },
1008 { .name = "munlock", .errmsg = true, 1034 { .name = "munlock", .errmsg = true,
1009 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 1035 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
@@ -1163,13 +1189,13 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
1163 if (thread == NULL) 1189 if (thread == NULL)
1164 goto fail; 1190 goto fail;
1165 1191
1166 if (thread->priv == NULL) 1192 if (thread__priv(thread) == NULL)
1167 thread->priv = thread_trace__new(); 1193 thread__set_priv(thread, thread_trace__new());
1168 1194
1169 if (thread->priv == NULL) 1195 if (thread__priv(thread) == NULL)
1170 goto fail; 1196 goto fail;
1171 1197
1172 ttrace = thread->priv; 1198 ttrace = thread__priv(thread);
1173 ++ttrace->nr_events; 1199 ++ttrace->nr_events;
1174 1200
1175 return ttrace; 1201 return ttrace;
@@ -1222,7 +1248,7 @@ struct trace {
1222 1248
1223static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1249static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1224{ 1250{
1225 struct thread_trace *ttrace = thread->priv; 1251 struct thread_trace *ttrace = thread__priv(thread);
1226 1252
1227 if (fd > ttrace->paths.max) { 1253 if (fd > ttrace->paths.max) {
1228 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *)); 1254 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
@@ -1275,7 +1301,7 @@ static int thread__read_fd_path(struct thread *thread, int fd)
1275static const char *thread__fd_path(struct thread *thread, int fd, 1301static const char *thread__fd_path(struct thread *thread, int fd,
1276 struct trace *trace) 1302 struct trace *trace)
1277{ 1303{
1278 struct thread_trace *ttrace = thread->priv; 1304 struct thread_trace *ttrace = thread__priv(thread);
1279 1305
1280 if (ttrace == NULL) 1306 if (ttrace == NULL)
1281 return NULL; 1307 return NULL;
@@ -1312,7 +1338,7 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1312{ 1338{
1313 int fd = arg->val; 1339 int fd = arg->val;
1314 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1340 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1315 struct thread_trace *ttrace = arg->thread->priv; 1341 struct thread_trace *ttrace = thread__priv(arg->thread);
1316 1342
1317 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) 1343 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1318 zfree(&ttrace->paths.table[fd]); 1344 zfree(&ttrace->paths.table[fd]);
@@ -1385,7 +1411,7 @@ static int trace__tool_process(struct perf_tool *tool,
1385 1411
1386static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1412static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1387{ 1413{
1388 int err = symbol__init(); 1414 int err = symbol__init(NULL);
1389 1415
1390 if (err) 1416 if (err)
1391 return err; 1417 return err;
@@ -1669,7 +1695,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1669 union perf_event *event __maybe_unused, 1695 union perf_event *event __maybe_unused,
1670 struct perf_sample *sample) 1696 struct perf_sample *sample)
1671{ 1697{
1672 int ret; 1698 long ret;
1673 u64 duration = 0; 1699 u64 duration = 0;
1674 struct thread *thread; 1700 struct thread *thread;
1675 int id = perf_evsel__sc_tp_uint(evsel, id, sample); 1701 int id = perf_evsel__sc_tp_uint(evsel, id, sample);
@@ -1722,9 +1748,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
1722 1748
1723 if (sc->fmt == NULL) { 1749 if (sc->fmt == NULL) {
1724signed_print: 1750signed_print:
1725 fprintf(trace->output, ") = %d", ret); 1751 fprintf(trace->output, ") = %ld", ret);
1726 } else if (ret < 0 && sc->fmt->errmsg) { 1752 } else if (ret < 0 && sc->fmt->errmsg) {
1727 char bf[256]; 1753 char bf[STRERR_BUFSIZE];
1728 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1754 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
1729 *e = audit_errno_to_name(-ret); 1755 *e = audit_errno_to_name(-ret);
1730 1756
@@ -1732,7 +1758,7 @@ signed_print:
1732 } else if (ret == 0 && sc->fmt->timeout) 1758 } else if (ret == 0 && sc->fmt->timeout)
1733 fprintf(trace->output, ") = 0 Timeout"); 1759 fprintf(trace->output, ") = 0 Timeout");
1734 else if (sc->fmt->hexret) 1760 else if (sc->fmt->hexret)
1735 fprintf(trace->output, ") = %#x", ret); 1761 fprintf(trace->output, ") = %#lx", ret);
1736 else 1762 else
1737 goto signed_print; 1763 goto signed_print;
1738 1764
@@ -1820,7 +1846,7 @@ static int trace__pgfault(struct trace *trace,
1820 if (trace->summary_only) 1846 if (trace->summary_only)
1821 return 0; 1847 return 0;
1822 1848
1823 thread__find_addr_location(thread, trace->host, cpumode, MAP__FUNCTION, 1849 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1824 sample->ip, &al); 1850 sample->ip, &al);
1825 1851
1826 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); 1852 trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output);
@@ -1833,11 +1859,11 @@ static int trace__pgfault(struct trace *trace,
1833 1859
1834 fprintf(trace->output, "] => "); 1860 fprintf(trace->output, "] => ");
1835 1861
1836 thread__find_addr_location(thread, trace->host, cpumode, MAP__VARIABLE, 1862 thread__find_addr_location(thread, cpumode, MAP__VARIABLE,
1837 sample->addr, &al); 1863 sample->addr, &al);
1838 1864
1839 if (!al.map) { 1865 if (!al.map) {
1840 thread__find_addr_location(thread, trace->host, cpumode, 1866 thread__find_addr_location(thread, cpumode,
1841 MAP__FUNCTION, sample->addr, &al); 1867 MAP__FUNCTION, sample->addr, &al);
1842 1868
1843 if (al.map) 1869 if (al.map)
@@ -2018,6 +2044,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2018 int err = -1, i; 2044 int err = -1, i;
2019 unsigned long before; 2045 unsigned long before;
2020 const bool forks = argc > 0; 2046 const bool forks = argc > 0;
2047 bool draining = false;
2021 2048
2022 trace->live = true; 2049 trace->live = true;
2023 2050
@@ -2078,10 +2105,8 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2078 goto out_error_open; 2105 goto out_error_open;
2079 2106
2080 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); 2107 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
2081 if (err < 0) { 2108 if (err < 0)
2082 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); 2109 goto out_error_mmap;
2083 goto out_delete_evlist;
2084 }
2085 2110
2086 perf_evlist__enable(evlist); 2111 perf_evlist__enable(evlist);
2087 2112
@@ -2143,8 +2168,12 @@ next_event:
2143 if (trace->nr_events == before) { 2168 if (trace->nr_events == before) {
2144 int timeout = done ? 100 : -1; 2169 int timeout = done ? 100 : -1;
2145 2170
2146 if (poll(evlist->pollfd, evlist->nr_fds, timeout) > 0) 2171 if (!draining && perf_evlist__poll(evlist, timeout) > 0) {
2172 if (perf_evlist__filter_pollfd(evlist, POLLERR | POLLHUP) == 0)
2173 draining = true;
2174
2147 goto again; 2175 goto again;
2176 }
2148 } else { 2177 } else {
2149 goto again; 2178 goto again;
2150 } 2179 }
@@ -2177,6 +2206,10 @@ out_error_tp:
2177 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf)); 2206 perf_evlist__strerror_tp(evlist, errno, errbuf, sizeof(errbuf));
2178 goto out_error; 2207 goto out_error;
2179 2208
2209out_error_mmap:
2210 perf_evlist__strerror_mmap(evlist, errno, errbuf, sizeof(errbuf));
2211 goto out_error;
2212
2180out_error_open: 2213out_error_open:
2181 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf)); 2214 perf_evlist__strerror_open(evlist, errno, errbuf, sizeof(errbuf));
2182 2215
@@ -2209,18 +2242,18 @@ static int trace__replay(struct trace *trace)
2209 trace->tool.tracing_data = perf_event__process_tracing_data; 2242 trace->tool.tracing_data = perf_event__process_tracing_data;
2210 trace->tool.build_id = perf_event__process_build_id; 2243 trace->tool.build_id = perf_event__process_build_id;
2211 2244
2212 trace->tool.ordered_samples = true; 2245 trace->tool.ordered_events = true;
2213 trace->tool.ordering_requires_timestamps = true; 2246 trace->tool.ordering_requires_timestamps = true;
2214 2247
2215 /* add tid to output */ 2248 /* add tid to output */
2216 trace->multiple_threads = true; 2249 trace->multiple_threads = true;
2217 2250
2218 if (symbol__init() < 0)
2219 return -1;
2220
2221 session = perf_session__new(&file, false, &trace->tool); 2251 session = perf_session__new(&file, false, &trace->tool);
2222 if (session == NULL) 2252 if (session == NULL)
2223 return -ENOMEM; 2253 return -1;
2254
2255 if (symbol__init(&session->header.env) < 0)
2256 goto out;
2224 2257
2225 trace->host = &session->machines.host; 2258 trace->host = &session->machines.host;
2226 2259
@@ -2348,7 +2381,7 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2348 FILE *fp = data->fp; 2381 FILE *fp = data->fp;
2349 size_t printed = data->printed; 2382 size_t printed = data->printed;
2350 struct trace *trace = data->trace; 2383 struct trace *trace = data->trace;
2351 struct thread_trace *ttrace = thread->priv; 2384 struct thread_trace *ttrace = thread__priv(thread);
2352 double ratio; 2385 double ratio;
2353 2386
2354 if (ttrace == NULL) 2387 if (ttrace == NULL)
@@ -2452,7 +2485,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2452 .user_freq = UINT_MAX, 2485 .user_freq = UINT_MAX,
2453 .user_interval = ULLONG_MAX, 2486 .user_interval = ULLONG_MAX,
2454 .no_buffering = true, 2487 .no_buffering = true,
2455 .mmap_pages = 1024, 2488 .mmap_pages = UINT_MAX,
2456 }, 2489 },
2457 .output = stdout, 2490 .output = stdout,
2458 .show_comm = true, 2491 .show_comm = true,
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 1f67aa02d240..5d4b039fe1ed 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -48,10 +48,6 @@ ifneq ($(ARCH),$(filter $(ARCH),x86 arm))
48 NO_LIBDW_DWARF_UNWIND := 1 48 NO_LIBDW_DWARF_UNWIND := 1
49endif 49endif
50 50
51ifeq ($(ARCH),powerpc)
52 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
53endif
54
55ifeq ($(LIBUNWIND_LIBS),) 51ifeq ($(LIBUNWIND_LIBS),)
56 NO_LIBUNWIND := 1 52 NO_LIBUNWIND := 1
57else 53else
@@ -120,6 +116,29 @@ ifdef PARSER_DEBUG
120 CFLAGS += -DPARSER_DEBUG 116 CFLAGS += -DPARSER_DEBUG
121endif 117endif
122 118
119ifndef NO_LIBPYTHON
120 # Try different combinations to accommodate systems that only have
121 # python[2][-config] in weird combinations but always preferring
122 # python2 and python2-config as per pep-0394. If we catch a
123 # python[-config] in version 3, the version check will kill it.
124 PYTHON2 := $(if $(call get-executable,python2),python2,python)
125 override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
126 PYTHON2_CONFIG := \
127 $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
128 override PYTHON_CONFIG := \
129 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
130
131 PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
132
133 PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
134 PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
135
136 FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
137 FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
138 FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
139 FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
140endif
141
123CFLAGS += -fno-omit-frame-pointer 142CFLAGS += -fno-omit-frame-pointer
124CFLAGS += -ggdb3 143CFLAGS += -ggdb3
125CFLAGS += -funwind-tables 144CFLAGS += -funwind-tables
@@ -131,7 +150,7 @@ CFLAGS += -std=gnu99
131# adding assembler files missing the .GNU-stack linker note. 150# adding assembler files missing the .GNU-stack linker note.
132LDFLAGS += -Wl,-z,noexecstack 151LDFLAGS += -Wl,-z,noexecstack
133 152
134EXTLIBS = -lelf -lpthread -lrt -lm -ldl 153EXTLIBS = -lpthread -lrt -lm -ldl
135 154
136ifneq ($(OUTPUT),) 155ifneq ($(OUTPUT),)
137 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/ 156 OUTPUT_FEATURES = $(OUTPUT)config/feature-checks/
@@ -181,7 +200,8 @@ CORE_FEATURE_TESTS = \
181 libunwind \ 200 libunwind \
182 stackprotector-all \ 201 stackprotector-all \
183 timerfd \ 202 timerfd \
184 libdw-dwarf-unwind 203 libdw-dwarf-unwind \
204 zlib
185 205
186LIB_FEATURE_TESTS = \ 206LIB_FEATURE_TESTS = \
187 dwarf \ 207 dwarf \
@@ -195,7 +215,8 @@ LIB_FEATURE_TESTS = \
195 libpython \ 215 libpython \
196 libslang \ 216 libslang \
197 libunwind \ 217 libunwind \
198 libdw-dwarf-unwind 218 libdw-dwarf-unwind \
219 zlib
199 220
200VF_FEATURE_TESTS = \ 221VF_FEATURE_TESTS = \
201 backtrace \ 222 backtrace \
@@ -211,7 +232,9 @@ VF_FEATURE_TESTS = \
211 bionic \ 232 bionic \
212 liberty \ 233 liberty \
213 liberty-z \ 234 liberty-z \
214 cplus-demangle 235 cplus-demangle \
236 compile-32 \
237 compile-x32
215 238
216# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features. 239# Set FEATURE_CHECK_(C|LD)FLAGS-all for all CORE_FEATURE_TESTS features.
217# If in the future we need per-feature checks/flags for features not 240# If in the future we need per-feature checks/flags for features not
@@ -331,6 +354,7 @@ endif # NO_LIBELF
331 354
332ifndef NO_LIBELF 355ifndef NO_LIBELF
333 CFLAGS += -DHAVE_LIBELF_SUPPORT 356 CFLAGS += -DHAVE_LIBELF_SUPPORT
357 EXTLIBS += -lelf
334 358
335 ifeq ($(feature-libelf-mmap), 1) 359 ifeq ($(feature-libelf-mmap), 1)
336 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT 360 CFLAGS += -DHAVE_LIBELF_MMAP_SUPPORT
@@ -350,11 +374,17 @@ ifndef NO_LIBELF
350 else 374 else
351 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS) 375 CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
352 LDFLAGS += $(LIBDW_LDFLAGS) 376 LDFLAGS += $(LIBDW_LDFLAGS)
353 EXTLIBS += -lelf -ldw 377 EXTLIBS += -ldw
354 endif # PERF_HAVE_DWARF_REGS 378 endif # PERF_HAVE_DWARF_REGS
355 endif # NO_DWARF 379 endif # NO_DWARF
356endif # NO_LIBELF 380endif # NO_LIBELF
357 381
382ifeq ($(ARCH),powerpc)
383 ifndef NO_DWARF
384 CFLAGS += -DHAVE_SKIP_CALLCHAIN_IDX
385 endif
386endif
387
358ifndef NO_LIBUNWIND 388ifndef NO_LIBUNWIND
359 ifneq ($(feature-libunwind), 1) 389 ifneq ($(feature-libunwind), 1)
360 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); 390 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
@@ -482,21 +512,14 @@ define disable-python_code
482 NO_LIBPYTHON := 1 512 NO_LIBPYTHON := 1
483endef 513endef
484 514
485override PYTHON := \ 515ifdef NO_LIBPYTHON
486 $(call get-executable-or-default,PYTHON,python) 516 $(call disable-python)
487
488ifndef PYTHON
489 $(call disable-python,python interpreter)
490else 517else
491 518
492 PYTHON_WORD := $(call shell-wordify,$(PYTHON)) 519 ifndef PYTHON
493 520 $(call disable-python,python interpreter)
494 ifdef NO_LIBPYTHON
495 $(call disable-python)
496 else 521 else
497 522 PYTHON_WORD := $(call shell-wordify,$(PYTHON))
498 override PYTHON_CONFIG := \
499 $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON)-config)
500 523
501 ifndef PYTHON_CONFIG 524 ifndef PYTHON_CONFIG
502 $(call disable-python,python-config tool) 525 $(call disable-python,python-config tool)
@@ -584,6 +607,15 @@ ifneq ($(filter -lbfd,$(EXTLIBS)),)
584 CFLAGS += -DHAVE_LIBBFD_SUPPORT 607 CFLAGS += -DHAVE_LIBBFD_SUPPORT
585endif 608endif
586 609
610ifndef NO_ZLIB
611 ifeq ($(feature-zlib), 1)
612 CFLAGS += -DHAVE_ZLIB_SUPPORT
613 EXTLIBS += -lz
614 else
615 NO_ZLIB := 1
616 endif
617endif
618
587ifndef NO_BACKTRACE 619ifndef NO_BACKTRACE
588 ifeq ($(feature-backtrace), 1) 620 ifeq ($(feature-backtrace), 1)
589 CFLAGS += -DHAVE_BACKTRACE_SUPPORT 621 CFLAGS += -DHAVE_BACKTRACE_SUPPORT
@@ -604,6 +636,31 @@ ifdef HAVE_KVM_STAT_SUPPORT
604 CFLAGS += -DHAVE_KVM_STAT_SUPPORT 636 CFLAGS += -DHAVE_KVM_STAT_SUPPORT
605endif 637endif
606 638
639ifeq (${IS_64_BIT}, 1)
640 ifndef NO_PERF_READ_VDSO32
641 $(call feature_check,compile-32)
642 ifeq ($(feature-compile-32), 1)
643 CFLAGS += -DHAVE_PERF_READ_VDSO32
644 else
645 NO_PERF_READ_VDSO32 := 1
646 endif
647 endif
648 ifneq (${IS_X86_64}, 1)
649 NO_PERF_READ_VDSOX32 := 1
650 endif
651 ifndef NO_PERF_READ_VDSOX32
652 $(call feature_check,compile-x32)
653 ifeq ($(feature-compile-x32), 1)
654 CFLAGS += -DHAVE_PERF_READ_VDSOX32
655 else
656 NO_PERF_READ_VDSOX32 := 1
657 endif
658 endif
659else
660 NO_PERF_READ_VDSO32 := 1
661 NO_PERF_READ_VDSOX32 := 1
662endif
663
607# Among the variables below, these: 664# Among the variables below, these:
608# perfexecdir 665# perfexecdir
609# template_dir 666# template_dir
@@ -635,11 +692,13 @@ else
635sysconfdir = $(prefix)/etc 692sysconfdir = $(prefix)/etc
636ETC_PERFCONFIG = etc/perfconfig 693ETC_PERFCONFIG = etc/perfconfig
637endif 694endif
695ifndef lib
638ifeq ($(IS_X86_64),1) 696ifeq ($(IS_X86_64),1)
639lib = lib64 697lib = lib64
640else 698else
641lib = lib 699lib = lib
642endif 700endif
701endif # lib
643libdir = $(prefix)/$(lib) 702libdir = $(prefix)/$(lib)
644 703
645# Shell quote (do not use $(call) to accommodate ancient setups); 704# Shell quote (do not use $(call) to accommodate ancient setups);
diff --git a/tools/perf/config/Makefile.arch b/tools/perf/config/Makefile.arch
index 4b06719ee984..851cd0172a76 100644
--- a/tools/perf/config/Makefile.arch
+++ b/tools/perf/config/Makefile.arch
@@ -21,3 +21,11 @@ ifeq ($(ARCH),x86_64)
21 RAW_ARCH := x86_64 21 RAW_ARCH := x86_64
22 endif 22 endif
23endif 23endif
24
25ifeq (${IS_X86_64}, 1)
26 IS_64_BIT := 1
27else ifeq ($(ARCH),x86)
28 IS_64_BIT := 0
29else
30 IS_64_BIT := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
31endif
diff --git a/tools/perf/config/feature-checks/Makefile b/tools/perf/config/feature-checks/Makefile
index 6088f8d8a434..53f19b5dbc37 100644
--- a/tools/perf/config/feature-checks/Makefile
+++ b/tools/perf/config/feature-checks/Makefile
@@ -27,7 +27,10 @@ FILES= \
27 test-libunwind-debug-frame.bin \ 27 test-libunwind-debug-frame.bin \
28 test-stackprotector-all.bin \ 28 test-stackprotector-all.bin \
29 test-timerfd.bin \ 29 test-timerfd.bin \
30 test-libdw-dwarf-unwind.bin 30 test-libdw-dwarf-unwind.bin \
31 test-compile-32.bin \
32 test-compile-x32.bin \
33 test-zlib.bin
31 34
32CC := $(CROSS_COMPILE)gcc -MD 35CC := $(CROSS_COMPILE)gcc -MD
33PKG_CONFIG := $(CROSS_COMPILE)pkg-config 36PKG_CONFIG := $(CROSS_COMPILE)pkg-config
@@ -39,7 +42,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
39############################### 42###############################
40 43
41test-all.bin: 44test-all.bin:
42 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl 45 $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz
43 46
44test-hello.bin: 47test-hello.bin:
45 $(BUILD) 48 $(BUILD)
@@ -101,25 +104,11 @@ FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
101test-libperl.bin: 104test-libperl.bin:
102 $(BUILD) $(FLAGS_PERL_EMBED) 105 $(BUILD) $(FLAGS_PERL_EMBED)
103 106
104override PYTHON := python
105override PYTHON_CONFIG := python-config
106
107escape-for-shell-sq = $(subst ','\'',$(1))
108shell-sq = '$(escape-for-shell-sq)'
109
110PYTHON_CONFIG_SQ = $(call shell-sq,$(PYTHON_CONFIG))
111
112PYTHON_EMBED_LDOPTS = $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
113PYTHON_EMBED_LDFLAGS = $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
114PYTHON_EMBED_LIBADD = $(call grep-libs,$(PYTHON_EMBED_LDOPTS))
115PYTHON_EMBED_CCOPTS = $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
116FLAGS_PYTHON_EMBED = $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
117
118test-libpython.bin: 107test-libpython.bin:
119 $(BUILD) $(FLAGS_PYTHON_EMBED) 108 $(BUILD)
120 109
121test-libpython-version.bin: 110test-libpython-version.bin:
122 $(BUILD) $(FLAGS_PYTHON_EMBED) 111 $(BUILD)
123 112
124test-libbfd.bin: 113test-libbfd.bin:
125 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl 114 $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
@@ -145,6 +134,15 @@ test-libdw-dwarf-unwind.bin:
145test-sync-compare-and-swap.bin: 134test-sync-compare-and-swap.bin:
146 $(BUILD) -Werror 135 $(BUILD) -Werror
147 136
137test-compile-32.bin:
138 $(CC) -m32 -o $(OUTPUT)$@ test-compile.c
139
140test-compile-x32.bin:
141 $(CC) -mx32 -o $(OUTPUT)$@ test-compile.c
142
143test-zlib.bin:
144 $(BUILD) -lz
145
148-include *.d 146-include *.d
149 147
150############################### 148###############################
diff --git a/tools/perf/config/feature-checks/test-all.c b/tools/perf/config/feature-checks/test-all.c
index a7d022e161c0..652e0098eba6 100644
--- a/tools/perf/config/feature-checks/test-all.c
+++ b/tools/perf/config/feature-checks/test-all.c
@@ -93,6 +93,10 @@
93# include "test-sync-compare-and-swap.c" 93# include "test-sync-compare-and-swap.c"
94#undef main 94#undef main
95 95
96#define main main_test_zlib
97# include "test-zlib.c"
98#undef main
99
96int main(int argc, char *argv[]) 100int main(int argc, char *argv[])
97{ 101{
98 main_test_libpython(); 102 main_test_libpython();
@@ -116,6 +120,7 @@ int main(int argc, char *argv[])
116 main_test_stackprotector_all(); 120 main_test_stackprotector_all();
117 main_test_libdw_dwarf_unwind(); 121 main_test_libdw_dwarf_unwind();
118 main_test_sync_compare_and_swap(argc, argv); 122 main_test_sync_compare_and_swap(argc, argv);
123 main_test_zlib();
119 124
120 return 0; 125 return 0;
121} 126}
diff --git a/tools/perf/config/feature-checks/test-compile.c b/tools/perf/config/feature-checks/test-compile.c
new file mode 100644
index 000000000000..31dbf45bf99c
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-compile.c
@@ -0,0 +1,4 @@
1int main(void)
2{
3 return 0;
4}
diff --git a/tools/perf/config/feature-checks/test-zlib.c b/tools/perf/config/feature-checks/test-zlib.c
new file mode 100644
index 000000000000..e111fff6240e
--- /dev/null
+++ b/tools/perf/config/feature-checks/test-zlib.c
@@ -0,0 +1,9 @@
1#include <zlib.h>
2
3int main(void)
4{
5 z_stream zs;
6
7 inflateInit(&zs);
8 return 0;
9}
diff --git a/tools/perf/config/utilities.mak b/tools/perf/config/utilities.mak
index 4d985e0f03f5..7076a62d0ff7 100644
--- a/tools/perf/config/utilities.mak
+++ b/tools/perf/config/utilities.mak
@@ -132,7 +132,7 @@ endef
132# 132#
133# Usage: bool-value = $(call is-absolute,path) 133# Usage: bool-value = $(call is-absolute,path)
134# 134#
135is-absolute = $(shell echo $(shell-sq) | grep ^/ -q && echo y) 135is-absolute = $(shell echo $(shell-sq) | grep -q ^/ && echo y)
136 136
137# lookup 137# lookup
138# 138#
diff --git a/tools/perf/perf-read-vdso.c b/tools/perf/perf-read-vdso.c
new file mode 100644
index 000000000000..764e2547c25a
--- /dev/null
+++ b/tools/perf/perf-read-vdso.c
@@ -0,0 +1,34 @@
1#include <stdio.h>
2#include <string.h>
3
4#define VDSO__MAP_NAME "[vdso]"
5
6/*
7 * Include definition of find_vdso_map() also used in util/vdso.c for
8 * building perf.
9 */
10#include "util/find-vdso-map.c"
11
12int main(void)
13{
14 void *start, *end;
15 size_t size, written;
16
17 if (find_vdso_map(&start, &end))
18 return 1;
19
20 size = end - start;
21
22 while (size) {
23 written = fwrite(start, 1, size, stdout);
24 if (!written)
25 return 1;
26 start += written;
27 size -= written;
28 }
29
30 if (fflush(stdout))
31 return 1;
32
33 return 0;
34}
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 937e4324ad94..a3b13d7dc1d4 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -13,7 +13,7 @@
13#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 13#define wmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
14#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory") 14#define rmb() asm volatile("lock; addl $0,0(%%esp)" ::: "memory")
15#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 15#define cpu_relax() asm volatile("rep; nop" ::: "memory");
16#define CPUINFO_PROC "model name" 16#define CPUINFO_PROC {"model name"}
17#ifndef __NR_perf_event_open 17#ifndef __NR_perf_event_open
18# define __NR_perf_event_open 336 18# define __NR_perf_event_open 336
19#endif 19#endif
@@ -30,7 +30,7 @@
30#define wmb() asm volatile("sfence" ::: "memory") 30#define wmb() asm volatile("sfence" ::: "memory")
31#define rmb() asm volatile("lfence" ::: "memory") 31#define rmb() asm volatile("lfence" ::: "memory")
32#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 32#define cpu_relax() asm volatile("rep; nop" ::: "memory");
33#define CPUINFO_PROC "model name" 33#define CPUINFO_PROC {"model name"}
34#ifndef __NR_perf_event_open 34#ifndef __NR_perf_event_open
35# define __NR_perf_event_open 298 35# define __NR_perf_event_open 298
36#endif 36#endif
@@ -47,14 +47,14 @@
47#define mb() asm volatile ("sync" ::: "memory") 47#define mb() asm volatile ("sync" ::: "memory")
48#define wmb() asm volatile ("sync" ::: "memory") 48#define wmb() asm volatile ("sync" ::: "memory")
49#define rmb() asm volatile ("sync" ::: "memory") 49#define rmb() asm volatile ("sync" ::: "memory")
50#define CPUINFO_PROC "cpu" 50#define CPUINFO_PROC {"cpu"}
51#endif 51#endif
52 52
53#ifdef __s390__ 53#ifdef __s390__
54#define mb() asm volatile("bcr 15,0" ::: "memory") 54#define mb() asm volatile("bcr 15,0" ::: "memory")
55#define wmb() asm volatile("bcr 15,0" ::: "memory") 55#define wmb() asm volatile("bcr 15,0" ::: "memory")
56#define rmb() asm volatile("bcr 15,0" ::: "memory") 56#define rmb() asm volatile("bcr 15,0" ::: "memory")
57#define CPUINFO_PROC "vendor_id" 57#define CPUINFO_PROC {"vendor_id"}
58#endif 58#endif
59 59
60#ifdef __sh__ 60#ifdef __sh__
@@ -67,14 +67,14 @@
67# define wmb() asm volatile("" ::: "memory") 67# define wmb() asm volatile("" ::: "memory")
68# define rmb() asm volatile("" ::: "memory") 68# define rmb() asm volatile("" ::: "memory")
69#endif 69#endif
70#define CPUINFO_PROC "cpu type" 70#define CPUINFO_PROC {"cpu type"}
71#endif 71#endif
72 72
73#ifdef __hppa__ 73#ifdef __hppa__
74#define mb() asm volatile("" ::: "memory") 74#define mb() asm volatile("" ::: "memory")
75#define wmb() asm volatile("" ::: "memory") 75#define wmb() asm volatile("" ::: "memory")
76#define rmb() asm volatile("" ::: "memory") 76#define rmb() asm volatile("" ::: "memory")
77#define CPUINFO_PROC "cpu" 77#define CPUINFO_PROC {"cpu"}
78#endif 78#endif
79 79
80#ifdef __sparc__ 80#ifdef __sparc__
@@ -87,14 +87,14 @@
87#endif 87#endif
88#define wmb() asm volatile("":::"memory") 88#define wmb() asm volatile("":::"memory")
89#define rmb() asm volatile("":::"memory") 89#define rmb() asm volatile("":::"memory")
90#define CPUINFO_PROC "cpu" 90#define CPUINFO_PROC {"cpu"}
91#endif 91#endif
92 92
93#ifdef __alpha__ 93#ifdef __alpha__
94#define mb() asm volatile("mb" ::: "memory") 94#define mb() asm volatile("mb" ::: "memory")
95#define wmb() asm volatile("wmb" ::: "memory") 95#define wmb() asm volatile("wmb" ::: "memory")
96#define rmb() asm volatile("mb" ::: "memory") 96#define rmb() asm volatile("mb" ::: "memory")
97#define CPUINFO_PROC "cpu model" 97#define CPUINFO_PROC {"cpu model"}
98#endif 98#endif
99 99
100#ifdef __ia64__ 100#ifdef __ia64__
@@ -102,7 +102,7 @@
102#define wmb() asm volatile ("mf" ::: "memory") 102#define wmb() asm volatile ("mf" ::: "memory")
103#define rmb() asm volatile ("mf" ::: "memory") 103#define rmb() asm volatile ("mf" ::: "memory")
104#define cpu_relax() asm volatile ("hint @pause" ::: "memory") 104#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
105#define CPUINFO_PROC "model name" 105#define CPUINFO_PROC {"model name"}
106#endif 106#endif
107 107
108#ifdef __arm__ 108#ifdef __arm__
@@ -113,7 +113,7 @@
113#define mb() ((void(*)(void))0xffff0fa0)() 113#define mb() ((void(*)(void))0xffff0fa0)()
114#define wmb() ((void(*)(void))0xffff0fa0)() 114#define wmb() ((void(*)(void))0xffff0fa0)()
115#define rmb() ((void(*)(void))0xffff0fa0)() 115#define rmb() ((void(*)(void))0xffff0fa0)()
116#define CPUINFO_PROC "Processor" 116#define CPUINFO_PROC {"model name", "Processor"}
117#endif 117#endif
118 118
119#ifdef __aarch64__ 119#ifdef __aarch64__
@@ -133,28 +133,28 @@
133 : "memory") 133 : "memory")
134#define wmb() mb() 134#define wmb() mb()
135#define rmb() mb() 135#define rmb() mb()
136#define CPUINFO_PROC "cpu model" 136#define CPUINFO_PROC {"cpu model"}
137#endif 137#endif
138 138
139#ifdef __arc__ 139#ifdef __arc__
140#define mb() asm volatile("" ::: "memory") 140#define mb() asm volatile("" ::: "memory")
141#define wmb() asm volatile("" ::: "memory") 141#define wmb() asm volatile("" ::: "memory")
142#define rmb() asm volatile("" ::: "memory") 142#define rmb() asm volatile("" ::: "memory")
143#define CPUINFO_PROC "Processor" 143#define CPUINFO_PROC {"Processor"}
144#endif 144#endif
145 145
146#ifdef __metag__ 146#ifdef __metag__
147#define mb() asm volatile("" ::: "memory") 147#define mb() asm volatile("" ::: "memory")
148#define wmb() asm volatile("" ::: "memory") 148#define wmb() asm volatile("" ::: "memory")
149#define rmb() asm volatile("" ::: "memory") 149#define rmb() asm volatile("" ::: "memory")
150#define CPUINFO_PROC "CPU" 150#define CPUINFO_PROC {"CPU"}
151#endif 151#endif
152 152
153#ifdef __xtensa__ 153#ifdef __xtensa__
154#define mb() asm volatile("memw" ::: "memory") 154#define mb() asm volatile("memw" ::: "memory")
155#define wmb() asm volatile("memw" ::: "memory") 155#define wmb() asm volatile("memw" ::: "memory")
156#define rmb() asm volatile("" ::: "memory") 156#define rmb() asm volatile("" ::: "memory")
157#define CPUINFO_PROC "core ID" 157#define CPUINFO_PROC {"core ID"}
158#endif 158#endif
159 159
160#ifdef __tile__ 160#ifdef __tile__
@@ -162,7 +162,7 @@
162#define wmb() asm volatile ("mf" ::: "memory") 162#define wmb() asm volatile ("mf" ::: "memory")
163#define rmb() asm volatile ("mf" ::: "memory") 163#define rmb() asm volatile ("mf" ::: "memory")
164#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory") 164#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory")
165#define CPUINFO_PROC "model name" 165#define CPUINFO_PROC {"model name"}
166#endif 166#endif
167 167
168#define barrier() asm volatile ("" ::: "memory") 168#define barrier() asm volatile ("" ::: "memory")
diff --git a/tools/perf/perf-with-kcore.sh b/tools/perf/perf-with-kcore.sh
new file mode 100644
index 000000000000..c7ff90a90e4e
--- /dev/null
+++ b/tools/perf/perf-with-kcore.sh
@@ -0,0 +1,259 @@
1#!/bin/bash
2# perf-with-kcore: use perf with a copy of kcore
3# Copyright (c) 2014, Intel Corporation.
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms and conditions of the GNU General Public License,
7# version 2, as published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12# more details.
13
14set -e
15
16usage()
17{
18 echo "Usage: perf-with-kcore <perf sub-command> <perf.data directory> [<sub-command options> [ -- <workload>]]" >&2
19 echo " <perf sub-command> can be record, script, report or inject" >&2
20 echo " or: perf-with-kcore fix_buildid_cache_permissions" >&2
21 exit 1
22}
23
24find_perf()
25{
26 if [ -n "$PERF" ] ; then
27 return
28 fi
29 PERF=`which perf || true`
30 if [ -z "$PERF" ] ; then
31 echo "Failed to find perf" >&2
32 exit 1
33 fi
34 if [ ! -x "$PERF" ] ; then
35 echo "Failed to find perf" >&2
36 exit 1
37 fi
38 echo "Using $PERF"
39 "$PERF" version
40}
41
42copy_kcore()
43{
44 echo "Copying kcore"
45
46 if [ $EUID -eq 0 ] ; then
47 SUDO=""
48 else
49 SUDO="sudo"
50 fi
51
52 rm -f perf.data.junk
53 ("$PERF" record -o perf.data.junk $PERF_OPTIONS -- sleep 60) >/dev/null 2>/dev/null &
54 PERF_PID=$!
55
56 # Need to make sure that perf has started
57 sleep 1
58
59 KCORE=$(($SUDO "$PERF" buildid-cache -v -f -k /proc/kcore >/dev/null) 2>&1)
60 case "$KCORE" in
61 "kcore added to build-id cache directory "*)
62 KCORE_DIR=${KCORE#"kcore added to build-id cache directory "}
63 ;;
64 *)
65 kill $PERF_PID
66 wait >/dev/null 2>/dev/null || true
67 rm perf.data.junk
68 echo "$KCORE"
69 echo "Failed to find kcore" >&2
70 exit 1
71 ;;
72 esac
73
74 kill $PERF_PID
75 wait >/dev/null 2>/dev/null || true
76 rm perf.data.junk
77
78 $SUDO cp -a "$KCORE_DIR" "$(pwd)/$PERF_DATA_DIR"
79 $SUDO rm -f "$KCORE_DIR/kcore"
80 $SUDO rm -f "$KCORE_DIR/kallsyms"
81 $SUDO rm -f "$KCORE_DIR/modules"
82 $SUDO rmdir "$KCORE_DIR"
83
84 KCORE_DIR_BASENAME=$(basename "$KCORE_DIR")
85 KCORE_DIR="$(pwd)/$PERF_DATA_DIR/$KCORE_DIR_BASENAME"
86
87 $SUDO chown $UID "$KCORE_DIR"
88 $SUDO chown $UID "$KCORE_DIR/kcore"
89 $SUDO chown $UID "$KCORE_DIR/kallsyms"
90 $SUDO chown $UID "$KCORE_DIR/modules"
91
92 $SUDO chgrp $GROUPS "$KCORE_DIR"
93 $SUDO chgrp $GROUPS "$KCORE_DIR/kcore"
94 $SUDO chgrp $GROUPS "$KCORE_DIR/kallsyms"
95 $SUDO chgrp $GROUPS "$KCORE_DIR/modules"
96
97 ln -s "$KCORE_DIR_BASENAME" "$PERF_DATA_DIR/kcore_dir"
98}
99
100fix_buildid_cache_permissions()
101{
102 if [ $EUID -ne 0 ] ; then
103 echo "This script must be run as root via sudo " >&2
104 exit 1
105 fi
106
107 if [ -z "$SUDO_USER" ] ; then
108 echo "This script must be run via sudo" >&2
109 exit 1
110 fi
111
112 USER_HOME=$(bash <<< "echo ~$SUDO_USER")
113
114 if [ "$HOME" != "$USER_HOME" ] ; then
115 echo "Fix unnecessary because root has a home: $HOME" >&2
116 exit 1
117 fi
118
119 echo "Fixing buildid cache permissions"
120
121 find "$USER_HOME/.debug" -xdev -type d ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
122 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -user "$SUDO_USER" -ls -exec chown "$SUDO_USER" \{\} \;
123 find "$USER_HOME/.debug" -xdev -type l ! -user "$SUDO_USER" -ls -exec chown -h "$SUDO_USER" \{\} \;
124
125 if [ -n "$SUDO_GID" ] ; then
126 find "$USER_HOME/.debug" -xdev -type d ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
127 find "$USER_HOME/.debug" -xdev -type f -links 1 ! -group "$SUDO_GID" -ls -exec chgrp "$SUDO_GID" \{\} \;
128 find "$USER_HOME/.debug" -xdev -type l ! -group "$SUDO_GID" -ls -exec chgrp -h "$SUDO_GID" \{\} \;
129 fi
130
131 echo "Done"
132}
133
134check_buildid_cache_permissions()
135{
136 if [ $EUID -eq 0 ] ; then
137 return
138 fi
139
140 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -user "$USER" -print -quit)
141 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -user "$USER" -print -quit)
142 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -user "$USER" -print -quit)
143
144 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type d ! -group "$GROUPS" -print -quit)
145 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type f -links 1 ! -group "$GROUPS" -print -quit)
146 PERMISSIONS_OK+=$(find "$HOME/.debug" -xdev -type l ! -group "$GROUPS" -print -quit)
147
148 if [ -n "$PERMISSIONS_OK" ] ; then
149 echo "*** WARNING *** buildid cache permissions may need fixing" >&2
150 fi
151}
152
153record()
154{
155 echo "Recording"
156
157 if [ $EUID -ne 0 ] ; then
158
159 if [ "$(cat /proc/sys/kernel/kptr_restrict)" -ne 0 ] ; then
160 echo "*** WARNING *** /proc/sys/kernel/kptr_restrict prevents access to kernel addresses" >&2
161 fi
162
163 if echo "$PERF_OPTIONS" | grep -q ' -a \|^-a \| -a$\|^-a$\| --all-cpus \|^--all-cpus \| --all-cpus$\|^--all-cpus$' ; then
164 echo "*** WARNING *** system-wide tracing without root access will not be able to read all necessary information from /proc" >&2
165 fi
166
167 if echo "$PERF_OPTIONS" | grep -q 'intel_pt\|intel_bts\| -I\|^-I' ; then
168 if [ "$(cat /proc/sys/kernel/perf_event_paranoid)" -gt -1 ] ; then
169 echo "*** WARNING *** /proc/sys/kernel/perf_event_paranoid restricts buffer size and tracepoint (sched_switch) use" >&2
170 fi
171
172 if echo "$PERF_OPTIONS" | grep -q ' --per-thread \|^--per-thread \| --per-thread$\|^--per-thread$' ; then
173 true
174 elif echo "$PERF_OPTIONS" | grep -q ' -t \|^-t \| -t$\|^-t$' ; then
175 true
176 elif [ ! -r /sys/kernel/debug -o ! -x /sys/kernel/debug ] ; then
177 echo "*** WARNING *** /sys/kernel/debug permissions prevent tracepoint (sched_switch) use" >&2
178 fi
179 fi
180 fi
181
182 if [ -z "$1" ] ; then
183 echo "Workload is required for recording" >&2
184 usage
185 fi
186
187 if [ -e "$PERF_DATA_DIR" ] ; then
188 echo "'$PERF_DATA_DIR' exists" >&2
189 exit 1
190 fi
191
192 find_perf
193
194 mkdir "$PERF_DATA_DIR"
195
196 echo "$PERF record -o $PERF_DATA_DIR/perf.data $PERF_OPTIONS -- $*"
197 "$PERF" record -o "$PERF_DATA_DIR/perf.data" $PERF_OPTIONS -- $* || true
198
199 if rmdir "$PERF_DATA_DIR" > /dev/null 2>/dev/null ; then
200 exit 1
201 fi
202
203 copy_kcore
204
205 echo "Done"
206}
207
208subcommand()
209{
210 find_perf
211 check_buildid_cache_permissions
212 echo "$PERF $PERF_SUB_COMMAND -i $PERF_DATA_DIR/perf.data --kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms $*"
213 "$PERF" $PERF_SUB_COMMAND -i "$PERF_DATA_DIR/perf.data" "--kallsyms=$PERF_DATA_DIR/kcore_dir/kallsyms" $*
214}
215
216if [ "$1" = "fix_buildid_cache_permissions" ] ; then
217 fix_buildid_cache_permissions
218 exit 0
219fi
220
221PERF_SUB_COMMAND=$1
222PERF_DATA_DIR=$2
223shift || true
224shift || true
225
226if [ -z "$PERF_SUB_COMMAND" ] ; then
227 usage
228fi
229
230if [ -z "$PERF_DATA_DIR" ] ; then
231 usage
232fi
233
234case "$PERF_SUB_COMMAND" in
235"record")
236 while [ "$1" != "--" ] ; do
237 PERF_OPTIONS+="$1 "
238 shift || break
239 done
240 if [ "$1" != "--" ] ; then
241 echo "Options and workload are required for recording" >&2
242 usage
243 fi
244 shift
245 record $*
246;;
247"script")
248 subcommand $*
249;;
250"report")
251 subcommand $*
252;;
253"inject")
254 subcommand $*
255;;
256*)
257 usage
258;;
259esac
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 2282d41879a2..3700a7faca6c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -200,6 +200,16 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
200 *envchanged = 1; 200 *envchanged = 1;
201 (*argv)++; 201 (*argv)++;
202 (*argc)--; 202 (*argc)--;
203 } else if (!strcmp(cmd, "--buildid-dir")) {
204 if (*argc < 2) {
205 fprintf(stderr, "No directory given for --buildid-dir.\n");
206 usage(perf_usage_string);
207 }
208 set_buildid_dir((*argv)[1]);
209 if (envchanged)
210 *envchanged = 1;
211 (*argv)++;
212 (*argc)--;
203 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 213 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
204 perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR)); 214 perf_debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR));
205 fprintf(stderr, "dir: %s\n", debugfs_mountpoint); 215 fprintf(stderr, "dir: %s\n", debugfs_mountpoint);
@@ -313,6 +323,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
313 int status; 323 int status;
314 struct stat st; 324 struct stat st;
315 const char *prefix; 325 const char *prefix;
326 char sbuf[STRERR_BUFSIZE];
316 327
317 prefix = NULL; 328 prefix = NULL;
318 if (p->option & RUN_SETUP) 329 if (p->option & RUN_SETUP)
@@ -343,7 +354,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
343 status = 1; 354 status = 1;
344 /* Check for ENOSPC and EIO errors.. */ 355 /* Check for ENOSPC and EIO errors.. */
345 if (fflush(stdout)) { 356 if (fflush(stdout)) {
346 fprintf(stderr, "write failure on standard output: %s", strerror(errno)); 357 fprintf(stderr, "write failure on standard output: %s",
358 strerror_r(errno, sbuf, sizeof(sbuf)));
347 goto out; 359 goto out;
348 } 360 }
349 if (ferror(stdout)) { 361 if (ferror(stdout)) {
@@ -351,7 +363,8 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
351 goto out; 363 goto out;
352 } 364 }
353 if (fclose(stdout)) { 365 if (fclose(stdout)) {
354 fprintf(stderr, "close failed on standard output: %s", strerror(errno)); 366 fprintf(stderr, "close failed on standard output: %s",
367 strerror_r(errno, sbuf, sizeof(sbuf)));
355 goto out; 368 goto out;
356 } 369 }
357 status = 0; 370 status = 0;
@@ -466,6 +479,7 @@ void pthread__unblock_sigwinch(void)
466int main(int argc, const char **argv) 479int main(int argc, const char **argv)
467{ 480{
468 const char *cmd; 481 const char *cmd;
482 char sbuf[STRERR_BUFSIZE];
469 483
470 /* The page_size is placed in util object. */ 484 /* The page_size is placed in util object. */
471 page_size = sysconf(_SC_PAGE_SIZE); 485 page_size = sysconf(_SC_PAGE_SIZE);
@@ -495,7 +509,7 @@ int main(int argc, const char **argv)
495 } 509 }
496 if (!prefixcmp(cmd, "trace")) { 510 if (!prefixcmp(cmd, "trace")) {
497#ifdef HAVE_LIBAUDIT_SUPPORT 511#ifdef HAVE_LIBAUDIT_SUPPORT
498 set_buildid_dir(); 512 set_buildid_dir(NULL);
499 setup_path(); 513 setup_path();
500 argv[0] = "trace"; 514 argv[0] = "trace";
501 return cmd_trace(argc, argv, NULL); 515 return cmd_trace(argc, argv, NULL);
@@ -510,7 +524,7 @@ int main(int argc, const char **argv)
510 argc--; 524 argc--;
511 handle_options(&argv, &argc, NULL); 525 handle_options(&argv, &argc, NULL);
512 commit_pager_choice(); 526 commit_pager_choice();
513 set_buildid_dir(); 527 set_buildid_dir(NULL);
514 528
515 if (argc > 0) { 529 if (argc > 0) {
516 if (!prefixcmp(argv[0], "--")) 530 if (!prefixcmp(argv[0], "--"))
@@ -561,7 +575,7 @@ int main(int argc, const char **argv)
561 } 575 }
562 576
563 fprintf(stderr, "Failed to run command '%s': %s\n", 577 fprintf(stderr, "Failed to run command '%s': %s\n",
564 cmd, strerror(errno)); 578 cmd, strerror_r(errno, sbuf, sizeof(sbuf)));
565out: 579out:
566 return 1; 580 return 1;
567} 581}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 510c65f72858..1dabb8553499 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -41,8 +41,6 @@ void pthread__unblock_sigwinch(void);
41 41
42struct record_opts { 42struct record_opts {
43 struct target target; 43 struct target target;
44 int call_graph;
45 bool call_graph_enabled;
46 bool group; 44 bool group;
47 bool inherit_stat; 45 bool inherit_stat;
48 bool no_buffering; 46 bool no_buffering;
@@ -54,15 +52,18 @@ struct record_opts {
54 bool sample_weight; 52 bool sample_weight;
55 bool sample_time; 53 bool sample_time;
56 bool period; 54 bool period;
55 bool sample_intr_regs;
57 unsigned int freq; 56 unsigned int freq;
58 unsigned int mmap_pages; 57 unsigned int mmap_pages;
59 unsigned int user_freq; 58 unsigned int user_freq;
60 u64 branch_stack; 59 u64 branch_stack;
61 u64 default_interval; 60 u64 default_interval;
62 u64 user_interval; 61 u64 user_interval;
63 u16 stack_dump_size;
64 bool sample_transaction; 62 bool sample_transaction;
65 unsigned initial_delay; 63 unsigned initial_delay;
66}; 64};
67 65
66struct option;
67extern const char * const *record_usage;
68extern struct option *record_options;
68#endif 69#endif
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-record b/tools/perf/scripts/python/bin/export-to-postgresql-record
new file mode 100644
index 000000000000..221d66e05713
--- /dev/null
+++ b/tools/perf/scripts/python/bin/export-to-postgresql-record
@@ -0,0 +1,8 @@
1#!/bin/bash
2
3#
4# export perf data to a postgresql database. Can cover
5# perf ip samples (excluding the tracepoints). No special
6# record requirements, just record what you want to export.
7#
8perf record $@
diff --git a/tools/perf/scripts/python/bin/export-to-postgresql-report b/tools/perf/scripts/python/bin/export-to-postgresql-report
new file mode 100644
index 000000000000..cd335b6e2a01
--- /dev/null
+++ b/tools/perf/scripts/python/bin/export-to-postgresql-report
@@ -0,0 +1,29 @@
1#!/bin/bash
2# description: export perf data to a postgresql database
3# args: [database name] [columns] [calls]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 3 ] ; then
13 echo "usage: export-to-postgresql-report [database name] [columns] [calls]"
14 exit
15fi
16if [ "$n_args" -gt 2 ] ; then
17 dbname=$1
18 columns=$2
19 calls=$3
20 shift 3
21elif [ "$n_args" -gt 1 ] ; then
22 dbname=$1
23 columns=$2
24 shift 2
25elif [ "$n_args" -gt 0 ] ; then
26 dbname=$1
27 shift
28fi
29perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/export-to-postgresql.py $dbname $columns $calls
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
new file mode 100644
index 000000000000..4cdafd880074
--- /dev/null
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -0,0 +1,444 @@
1# export-to-postgresql.py: export perf data to a postgresql database
2# Copyright (c) 2014, Intel Corporation.
3#
4# This program is free software; you can redistribute it and/or modify it
5# under the terms and conditions of the GNU General Public License,
6# version 2, as published by the Free Software Foundation.
7#
8# This program is distributed in the hope it will be useful, but WITHOUT
9# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11# more details.
12
13import os
14import sys
15import struct
16import datetime
17
18from PySide.QtSql import *
19
20# Need to access PostgreSQL C library directly to use COPY FROM STDIN
21from ctypes import *
22libpq = CDLL("libpq.so.5")
23PQconnectdb = libpq.PQconnectdb
24PQconnectdb.restype = c_void_p
25PQfinish = libpq.PQfinish
26PQstatus = libpq.PQstatus
27PQexec = libpq.PQexec
28PQexec.restype = c_void_p
29PQresultStatus = libpq.PQresultStatus
30PQputCopyData = libpq.PQputCopyData
31PQputCopyData.argtypes = [ c_void_p, c_void_p, c_int ]
32PQputCopyEnd = libpq.PQputCopyEnd
33PQputCopyEnd.argtypes = [ c_void_p, c_void_p ]
34
35sys.path.append(os.environ['PERF_EXEC_PATH'] + \
36 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
37
38# These perf imports are not used at present
39#from perf_trace_context import *
40#from Core import *
41
42perf_db_export_mode = True
43perf_db_export_calls = False
44
45def usage():
46 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>]"
47 print >> sys.stderr, "where: columns 'all' or 'branches'"
48 print >> sys.stderr, " calls 'calls' => create calls table"
49 raise Exception("Too few arguments")
50
51if (len(sys.argv) < 2):
52 usage()
53
54dbname = sys.argv[1]
55
56if (len(sys.argv) >= 3):
57 columns = sys.argv[2]
58else:
59 columns = "all"
60
61if columns not in ("all", "branches"):
62 usage()
63
64branches = (columns == "branches")
65
66if (len(sys.argv) >= 4):
67 if (sys.argv[3] == "calls"):
68 perf_db_export_calls = True
69 else:
70 usage()
71
72output_dir_name = os.getcwd() + "/" + dbname + "-perf-data"
73os.mkdir(output_dir_name)
74
75def do_query(q, s):
76 if (q.exec_(s)):
77 return
78 raise Exception("Query failed: " + q.lastError().text())
79
80print datetime.datetime.today(), "Creating database..."
81
82db = QSqlDatabase.addDatabase('QPSQL')
83query = QSqlQuery(db)
84db.setDatabaseName('postgres')
85db.open()
86try:
87 do_query(query, 'CREATE DATABASE ' + dbname)
88except:
89 os.rmdir(output_dir_name)
90 raise
91query.finish()
92query.clear()
93db.close()
94
95db.setDatabaseName(dbname)
96db.open()
97
98query = QSqlQuery(db)
99do_query(query, 'SET client_min_messages TO WARNING')
100
101do_query(query, 'CREATE TABLE selected_events ('
102 'id bigint NOT NULL,'
103 'name varchar(80))')
104do_query(query, 'CREATE TABLE machines ('
105 'id bigint NOT NULL,'
106 'pid integer,'
107 'root_dir varchar(4096))')
108do_query(query, 'CREATE TABLE threads ('
109 'id bigint NOT NULL,'
110 'machine_id bigint,'
111 'process_id bigint,'
112 'pid integer,'
113 'tid integer)')
114do_query(query, 'CREATE TABLE comms ('
115 'id bigint NOT NULL,'
116 'comm varchar(16))')
117do_query(query, 'CREATE TABLE comm_threads ('
118 'id bigint NOT NULL,'
119 'comm_id bigint,'
120 'thread_id bigint)')
121do_query(query, 'CREATE TABLE dsos ('
122 'id bigint NOT NULL,'
123 'machine_id bigint,'
124 'short_name varchar(256),'
125 'long_name varchar(4096),'
126 'build_id varchar(64))')
127do_query(query, 'CREATE TABLE symbols ('
128 'id bigint NOT NULL,'
129 'dso_id bigint,'
130 'sym_start bigint,'
131 'sym_end bigint,'
132 'binding integer,'
133 'name varchar(2048))')
134do_query(query, 'CREATE TABLE branch_types ('
135 'id integer NOT NULL,'
136 'name varchar(80))')
137
138if branches:
139 do_query(query, 'CREATE TABLE samples ('
140 'id bigint NOT NULL,'
141 'evsel_id bigint,'
142 'machine_id bigint,'
143 'thread_id bigint,'
144 'comm_id bigint,'
145 'dso_id bigint,'
146 'symbol_id bigint,'
147 'sym_offset bigint,'
148 'ip bigint,'
149 'time bigint,'
150 'cpu integer,'
151 'to_dso_id bigint,'
152 'to_symbol_id bigint,'
153 'to_sym_offset bigint,'
154 'to_ip bigint,'
155 'branch_type integer,'
156 'in_tx boolean)')
157else:
158 do_query(query, 'CREATE TABLE samples ('
159 'id bigint NOT NULL,'
160 'evsel_id bigint,'
161 'machine_id bigint,'
162 'thread_id bigint,'
163 'comm_id bigint,'
164 'dso_id bigint,'
165 'symbol_id bigint,'
166 'sym_offset bigint,'
167 'ip bigint,'
168 'time bigint,'
169 'cpu integer,'
170 'to_dso_id bigint,'
171 'to_symbol_id bigint,'
172 'to_sym_offset bigint,'
173 'to_ip bigint,'
174 'period bigint,'
175 'weight bigint,'
176 'transaction bigint,'
177 'data_src bigint,'
178 'branch_type integer,'
179 'in_tx boolean)')
180
181if perf_db_export_calls:
182 do_query(query, 'CREATE TABLE call_paths ('
183 'id bigint NOT NULL,'
184 'parent_id bigint,'
185 'symbol_id bigint,'
186 'ip bigint)')
187 do_query(query, 'CREATE TABLE calls ('
188 'id bigint NOT NULL,'
189 'thread_id bigint,'
190 'comm_id bigint,'
191 'call_path_id bigint,'
192 'call_time bigint,'
193 'return_time bigint,'
194 'branch_count bigint,'
195 'call_id bigint,'
196 'return_id bigint,'
197 'parent_call_path_id bigint,'
198 'flags integer)')
199
200do_query(query, 'CREATE VIEW samples_view AS '
201 'SELECT '
202 'id,'
203 'time,'
204 'cpu,'
205 '(SELECT pid FROM threads WHERE id = thread_id) AS pid,'
206 '(SELECT tid FROM threads WHERE id = thread_id) AS tid,'
207 '(SELECT comm FROM comms WHERE id = comm_id) AS command,'
208 '(SELECT name FROM selected_events WHERE id = evsel_id) AS event,'
209 'to_hex(ip) AS ip_hex,'
210 '(SELECT name FROM symbols WHERE id = symbol_id) AS symbol,'
211 'sym_offset,'
212 '(SELECT short_name FROM dsos WHERE id = dso_id) AS dso_short_name,'
213 'to_hex(to_ip) AS to_ip_hex,'
214 '(SELECT name FROM symbols WHERE id = to_symbol_id) AS to_symbol,'
215 'to_sym_offset,'
216 '(SELECT short_name FROM dsos WHERE id = to_dso_id) AS to_dso_short_name,'
217 '(SELECT name FROM branch_types WHERE id = branch_type) AS branch_type_name,'
218 'in_tx'
219 ' FROM samples')
220
221
222file_header = struct.pack("!11sii", "PGCOPY\n\377\r\n\0", 0, 0)
223file_trailer = "\377\377"
224
225def open_output_file(file_name):
226 path_name = output_dir_name + "/" + file_name
227 file = open(path_name, "w+")
228 file.write(file_header)
229 return file
230
231def close_output_file(file):
232 file.write(file_trailer)
233 file.close()
234
235def copy_output_file_direct(file, table_name):
236 close_output_file(file)
237 sql = "COPY " + table_name + " FROM '" + file.name + "' (FORMAT 'binary')"
238 do_query(query, sql)
239
240# Use COPY FROM STDIN because security may prevent postgres from accessing the files directly
241def copy_output_file(file, table_name):
242 conn = PQconnectdb("dbname = " + dbname)
243 if (PQstatus(conn)):
244 raise Exception("COPY FROM STDIN PQconnectdb failed")
245 file.write(file_trailer)
246 file.seek(0)
247 sql = "COPY " + table_name + " FROM STDIN (FORMAT 'binary')"
248 res = PQexec(conn, sql)
249 if (PQresultStatus(res) != 4):
250 raise Exception("COPY FROM STDIN PQexec failed")
251 data = file.read(65536)
252 while (len(data)):
253 ret = PQputCopyData(conn, data, len(data))
254 if (ret != 1):
255 raise Exception("COPY FROM STDIN PQputCopyData failed, error " + str(ret))
256 data = file.read(65536)
257 ret = PQputCopyEnd(conn, None)
258 if (ret != 1):
259 raise Exception("COPY FROM STDIN PQputCopyEnd failed, error " + str(ret))
260 PQfinish(conn)
261
262def remove_output_file(file):
263 name = file.name
264 file.close()
265 os.unlink(name)
266
267evsel_file = open_output_file("evsel_table.bin")
268machine_file = open_output_file("machine_table.bin")
269thread_file = open_output_file("thread_table.bin")
270comm_file = open_output_file("comm_table.bin")
271comm_thread_file = open_output_file("comm_thread_table.bin")
272dso_file = open_output_file("dso_table.bin")
273symbol_file = open_output_file("symbol_table.bin")
274branch_type_file = open_output_file("branch_type_table.bin")
275sample_file = open_output_file("sample_table.bin")
276if perf_db_export_calls:
277 call_path_file = open_output_file("call_path_table.bin")
278 call_file = open_output_file("call_table.bin")
279
280def trace_begin():
281 print datetime.datetime.today(), "Writing to intermediate files..."
282 # id == 0 means unknown. It is easier to create records for them than replace the zeroes with NULLs
283 evsel_table(0, "unknown")
284 machine_table(0, 0, "unknown")
285 thread_table(0, 0, 0, -1, -1)
286 comm_table(0, "unknown")
287 dso_table(0, 0, "unknown", "unknown", "")
288 symbol_table(0, 0, 0, 0, 0, "unknown")
289 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
290 if perf_db_export_calls:
291 call_path_table(0, 0, 0, 0)
292
293unhandled_count = 0
294
295def trace_end():
296 print datetime.datetime.today(), "Copying to database..."
297 copy_output_file(evsel_file, "selected_events")
298 copy_output_file(machine_file, "machines")
299 copy_output_file(thread_file, "threads")
300 copy_output_file(comm_file, "comms")
301 copy_output_file(comm_thread_file, "comm_threads")
302 copy_output_file(dso_file, "dsos")
303 copy_output_file(symbol_file, "symbols")
304 copy_output_file(branch_type_file, "branch_types")
305 copy_output_file(sample_file, "samples")
306 if perf_db_export_calls:
307 copy_output_file(call_path_file, "call_paths")
308 copy_output_file(call_file, "calls")
309
310 print datetime.datetime.today(), "Removing intermediate files..."
311 remove_output_file(evsel_file)
312 remove_output_file(machine_file)
313 remove_output_file(thread_file)
314 remove_output_file(comm_file)
315 remove_output_file(comm_thread_file)
316 remove_output_file(dso_file)
317 remove_output_file(symbol_file)
318 remove_output_file(branch_type_file)
319 remove_output_file(sample_file)
320 if perf_db_export_calls:
321 remove_output_file(call_path_file)
322 remove_output_file(call_file)
323 os.rmdir(output_dir_name)
324 print datetime.datetime.today(), "Adding primary keys"
325 do_query(query, 'ALTER TABLE selected_events ADD PRIMARY KEY (id)')
326 do_query(query, 'ALTER TABLE machines ADD PRIMARY KEY (id)')
327 do_query(query, 'ALTER TABLE threads ADD PRIMARY KEY (id)')
328 do_query(query, 'ALTER TABLE comms ADD PRIMARY KEY (id)')
329 do_query(query, 'ALTER TABLE comm_threads ADD PRIMARY KEY (id)')
330 do_query(query, 'ALTER TABLE dsos ADD PRIMARY KEY (id)')
331 do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)')
332 do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)')
333 do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)')
334 if perf_db_export_calls:
335 do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)')
336 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
337
338 print datetime.datetime.today(), "Adding foreign keys"
339 do_query(query, 'ALTER TABLE threads '
340 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
341 'ADD CONSTRAINT processfk FOREIGN KEY (process_id) REFERENCES threads (id)')
342 do_query(query, 'ALTER TABLE comm_threads '
343 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
344 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id)')
345 do_query(query, 'ALTER TABLE dsos '
346 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id)')
347 do_query(query, 'ALTER TABLE symbols '
348 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id)')
349 do_query(query, 'ALTER TABLE samples '
350 'ADD CONSTRAINT evselfk FOREIGN KEY (evsel_id) REFERENCES selected_events (id),'
351 'ADD CONSTRAINT machinefk FOREIGN KEY (machine_id) REFERENCES machines (id),'
352 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
353 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
354 'ADD CONSTRAINT dsofk FOREIGN KEY (dso_id) REFERENCES dsos (id),'
355 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),'
356 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),'
357 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)')
358 if perf_db_export_calls:
359 do_query(query, 'ALTER TABLE call_paths '
360 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),'
361 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)')
362 do_query(query, 'ALTER TABLE calls '
363 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
364 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
365 'ADD CONSTRAINT call_pathfk FOREIGN KEY (call_path_id) REFERENCES call_paths (id),'
366 'ADD CONSTRAINT callfk FOREIGN KEY (call_id) REFERENCES samples (id),'
367 'ADD CONSTRAINT returnfk FOREIGN KEY (return_id) REFERENCES samples (id),'
368 'ADD CONSTRAINT parent_call_pathfk FOREIGN KEY (parent_call_path_id) REFERENCES call_paths (id)')
369 do_query(query, 'CREATE INDEX pcpid_idx ON calls (parent_call_path_id)')
370
371 if (unhandled_count):
372 print datetime.datetime.today(), "Warning: ", unhandled_count, " unhandled events"
373 print datetime.datetime.today(), "Done"
374
375def trace_unhandled(event_name, context, event_fields_dict):
376 global unhandled_count
377 unhandled_count += 1
378
379def sched__sched_switch(*x):
380 pass
381
382def evsel_table(evsel_id, evsel_name, *x):
383 n = len(evsel_name)
384 fmt = "!hiqi" + str(n) + "s"
385 value = struct.pack(fmt, 2, 8, evsel_id, n, evsel_name)
386 evsel_file.write(value)
387
388def machine_table(machine_id, pid, root_dir, *x):
389 n = len(root_dir)
390 fmt = "!hiqiii" + str(n) + "s"
391 value = struct.pack(fmt, 3, 8, machine_id, 4, pid, n, root_dir)
392 machine_file.write(value)
393
394def thread_table(thread_id, machine_id, process_id, pid, tid, *x):
395 value = struct.pack("!hiqiqiqiiii", 5, 8, thread_id, 8, machine_id, 8, process_id, 4, pid, 4, tid)
396 thread_file.write(value)
397
398def comm_table(comm_id, comm_str, *x):
399 n = len(comm_str)
400 fmt = "!hiqi" + str(n) + "s"
401 value = struct.pack(fmt, 2, 8, comm_id, n, comm_str)
402 comm_file.write(value)
403
404def comm_thread_table(comm_thread_id, comm_id, thread_id, *x):
405 fmt = "!hiqiqiq"
406 value = struct.pack(fmt, 3, 8, comm_thread_id, 8, comm_id, 8, thread_id)
407 comm_thread_file.write(value)
408
409def dso_table(dso_id, machine_id, short_name, long_name, build_id, *x):
410 n1 = len(short_name)
411 n2 = len(long_name)
412 n3 = len(build_id)
413 fmt = "!hiqiqi" + str(n1) + "si" + str(n2) + "si" + str(n3) + "s"
414 value = struct.pack(fmt, 5, 8, dso_id, 8, machine_id, n1, short_name, n2, long_name, n3, build_id)
415 dso_file.write(value)
416
417def symbol_table(symbol_id, dso_id, sym_start, sym_end, binding, symbol_name, *x):
418 n = len(symbol_name)
419 fmt = "!hiqiqiqiqiii" + str(n) + "s"
420 value = struct.pack(fmt, 6, 8, symbol_id, 8, dso_id, 8, sym_start, 8, sym_end, 4, binding, n, symbol_name)
421 symbol_file.write(value)
422
423def branch_type_table(branch_type, name, *x):
424 n = len(name)
425 fmt = "!hiii" + str(n) + "s"
426 value = struct.pack(fmt, 2, 4, branch_type, n, name)
427 branch_type_file.write(value)
428
429def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, *x):
430 if branches:
431 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiB", 17, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx)
432 else:
433 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiB", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx)
434 sample_file.write(value)
435
436def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
437 fmt = "!hiqiqiqiq"
438 value = struct.pack(fmt, 4, 8, cp_id, 8, parent_id, 8, symbol_id, 8, ip)
439 call_path_file.write(value)
440
441def call_return_table(cr_id, thread_id, comm_id, call_path_id, call_time, return_time, branch_count, call_id, return_id, parent_call_path_id, flags, *x):
442 fmt = "!hiqiqiqiqiqiqiqiqiqiqii"
443 value = struct.pack(fmt, 11, 8, cr_id, 8, thread_id, 8, comm_id, 8, call_path_id, 8, call_time, 8, return_time, 8, branch_count, 8, call_id, 8, return_id, 8, parent_call_path_id, 4, flags)
444 call_file.write(value)
diff --git a/tools/perf/tests/attr/base-record b/tools/perf/tests/attr/base-record
index f710b92ccff6..d3095dafed36 100644
--- a/tools/perf/tests/attr/base-record
+++ b/tools/perf/tests/attr/base-record
@@ -5,7 +5,7 @@ group_fd=-1
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0|1 7type=0|1
8size=96 8size=104
9config=0 9config=0
10sample_period=4000 10sample_period=4000
11sample_type=263 11sample_type=263
diff --git a/tools/perf/tests/attr/base-stat b/tools/perf/tests/attr/base-stat
index dc3ada2470c0..872ed7e24c7c 100644
--- a/tools/perf/tests/attr/base-stat
+++ b/tools/perf/tests/attr/base-stat
@@ -5,7 +5,7 @@ group_fd=-1
5flags=0|8 5flags=0|8
6cpu=* 6cpu=*
7type=0 7type=0
8size=96 8size=104
9config=0 9config=0
10sample_period=0 10sample_period=0
11sample_type=0 11sample_type=0
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 6f8b01bc6033..4b7d9ab0f049 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -6,6 +6,7 @@
6#include <unistd.h> 6#include <unistd.h>
7#include <string.h> 7#include <string.h>
8#include "builtin.h" 8#include "builtin.h"
9#include "hist.h"
9#include "intlist.h" 10#include "intlist.h"
10#include "tests.h" 11#include "tests.h"
11#include "debug.h" 12#include "debug.h"
@@ -84,7 +85,7 @@ static struct test {
84 .func = test__hists_link, 85 .func = test__hists_link,
85 }, 86 },
86 { 87 {
87 .desc = "Try 'use perf' in python, checking link problems", 88 .desc = "Try 'import perf' in python, checking link problems",
88 .func = test__python_use, 89 .func = test__python_use,
89 }, 90 },
90 { 91 {
@@ -154,6 +155,18 @@ static struct test {
154 .func = test__hists_cumulate, 155 .func = test__hists_cumulate,
155 }, 156 },
156 { 157 {
158 .desc = "Test tracking with sched_switch",
159 .func = test__switch_tracking,
160 },
161 {
162 .desc = "Filter fds with revents mask in a fdarray",
163 .func = test__fdarray__filter,
164 },
165 {
166 .desc = "Add fd to a fdarray, making it autogrow",
167 .func = test__fdarray__add,
168 },
169 {
157 .func = NULL, 170 .func = NULL,
158 }, 171 },
159}; 172};
@@ -185,9 +198,11 @@ static bool perf_test__matches(int curr, int argc, const char *argv[])
185static int run_test(struct test *test) 198static int run_test(struct test *test)
186{ 199{
187 int status, err = -1, child = fork(); 200 int status, err = -1, child = fork();
201 char sbuf[STRERR_BUFSIZE];
188 202
189 if (child < 0) { 203 if (child < 0) {
190 pr_err("failed to fork test: %s\n", strerror(errno)); 204 pr_err("failed to fork test: %s\n",
205 strerror_r(errno, sbuf, sizeof(sbuf)));
191 return -1; 206 return -1;
192 } 207 }
193 208
@@ -288,6 +303,10 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
288 OPT_END() 303 OPT_END()
289 }; 304 };
290 struct intlist *skiplist = NULL; 305 struct intlist *skiplist = NULL;
306 int ret = hists__init();
307
308 if (ret < 0)
309 return ret;
291 310
292 argc = parse_options(argc, argv, test_options, test_usage, 0); 311 argc = parse_options(argc, argv, test_options, test_usage, 0);
293 if (argc >= 1 && !strcmp(argv[0], "list")) 312 if (argc >= 1 && !strcmp(argv[0], "list"))
@@ -297,7 +316,7 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
297 symbol_conf.sort_by_name = true; 316 symbol_conf.sort_by_name = true;
298 symbol_conf.try_vmlinux_path = true; 317 symbol_conf.try_vmlinux_path = true;
299 318
300 if (symbol__init() < 0) 319 if (symbol__init(NULL) < 0)
301 return -1; 320 return -1;
302 321
303 if (skip != NULL) 322 if (skip != NULL)
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 67f2d6323558..f671ec37a7c4 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -133,8 +133,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
133} 133}
134 134
135static int read_object_code(u64 addr, size_t len, u8 cpumode, 135static int read_object_code(u64 addr, size_t len, u8 cpumode,
136 struct thread *thread, struct machine *machine, 136 struct thread *thread, struct state *state)
137 struct state *state)
138{ 137{
139 struct addr_location al; 138 struct addr_location al;
140 unsigned char buf1[BUFSZ]; 139 unsigned char buf1[BUFSZ];
@@ -145,8 +144,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
145 144
146 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr); 145 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
147 146
148 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr, 147 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, addr, &al);
149 &al);
150 if (!al.map || !al.map->dso) { 148 if (!al.map || !al.map->dso) {
151 pr_debug("thread__find_addr_map failed\n"); 149 pr_debug("thread__find_addr_map failed\n");
152 return -1; 150 return -1;
@@ -170,8 +168,8 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
170 len = al.map->end - addr; 168 len = al.map->end - addr;
171 169
172 /* Read the object code using perf */ 170 /* Read the object code using perf */
173 ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1, 171 ret_len = dso__data_read_offset(al.map->dso, thread->mg->machine,
174 len); 172 al.addr, buf1, len);
175 if (ret_len != len) { 173 if (ret_len != len) {
176 pr_debug("dso__data_read_offset failed\n"); 174 pr_debug("dso__data_read_offset failed\n");
177 return -1; 175 return -1;
@@ -264,8 +262,7 @@ static int process_sample_event(struct machine *machine,
264 262
265 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 263 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
266 264
267 return read_object_code(sample.ip, READLEN, cpumode, thread, machine, 265 return read_object_code(sample.ip, READLEN, cpumode, thread, state);
268 state);
269} 266}
270 267
271static int process_event(struct machine *machine, struct perf_evlist *evlist, 268static int process_event(struct machine *machine, struct perf_evlist *evlist,
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 96adb730b744..ab28cca2cb97 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -9,6 +9,7 @@
9#include "perf_regs.h" 9#include "perf_regs.h"
10#include "map.h" 10#include "map.h"
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h"
12 13
13static int mmap_handler(struct perf_tool *tool __maybe_unused, 14static int mmap_handler(struct perf_tool *tool __maybe_unused,
14 union perf_event *event, 15 union perf_event *event,
@@ -58,7 +59,7 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
58} 59}
59 60
60__attribute__ ((noinline)) 61__attribute__ ((noinline))
61static int unwind_thread(struct thread *thread, struct machine *machine) 62static int unwind_thread(struct thread *thread)
62{ 63{
63 struct perf_sample sample; 64 struct perf_sample sample;
64 unsigned long cnt = 0; 65 unsigned long cnt = 0;
@@ -71,7 +72,7 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
71 goto out; 72 goto out;
72 } 73 }
73 74
74 err = unwind__get_entries(unwind_entry, &cnt, machine, thread, 75 err = unwind__get_entries(unwind_entry, &cnt, thread,
75 &sample, MAX_STACK); 76 &sample, MAX_STACK);
76 if (err) 77 if (err)
77 pr_debug("unwind failed\n"); 78 pr_debug("unwind failed\n");
@@ -88,21 +89,21 @@ static int unwind_thread(struct thread *thread, struct machine *machine)
88} 89}
89 90
90__attribute__ ((noinline)) 91__attribute__ ((noinline))
91static int krava_3(struct thread *thread, struct machine *machine) 92static int krava_3(struct thread *thread)
92{ 93{
93 return unwind_thread(thread, machine); 94 return unwind_thread(thread);
94} 95}
95 96
96__attribute__ ((noinline)) 97__attribute__ ((noinline))
97static int krava_2(struct thread *thread, struct machine *machine) 98static int krava_2(struct thread *thread)
98{ 99{
99 return krava_3(thread, machine); 100 return krava_3(thread);
100} 101}
101 102
102__attribute__ ((noinline)) 103__attribute__ ((noinline))
103static int krava_1(struct thread *thread, struct machine *machine) 104static int krava_1(struct thread *thread)
104{ 105{
105 return krava_2(thread, machine); 106 return krava_2(thread);
106} 107}
107 108
108int test__dwarf_unwind(void) 109int test__dwarf_unwind(void)
@@ -120,6 +121,8 @@ int test__dwarf_unwind(void)
120 return -1; 121 return -1;
121 } 122 }
122 123
124 callchain_param.record_mode = CALLCHAIN_DWARF;
125
123 if (init_live_machine(machine)) { 126 if (init_live_machine(machine)) {
124 pr_err("Could not init machine\n"); 127 pr_err("Could not init machine\n");
125 goto out; 128 goto out;
@@ -134,7 +137,7 @@ int test__dwarf_unwind(void)
134 goto out; 137 goto out;
135 } 138 }
136 139
137 err = krava_1(thread, machine); 140 err = krava_1(thread);
138 141
139 out: 142 out:
140 machine__delete_threads(machine); 143 machine__delete_threads(machine);
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
new file mode 100644
index 000000000000..d24b837951d4
--- /dev/null
+++ b/tools/perf/tests/fdarray.c
@@ -0,0 +1,174 @@
1#include <api/fd/array.h>
2#include "util/debug.h"
3#include "tests/tests.h"
4
5static void fdarray__init_revents(struct fdarray *fda, short revents)
6{
7 int fd;
8
9 fda->nr = fda->nr_alloc;
10
11 for (fd = 0; fd < fda->nr; ++fd) {
12 fda->entries[fd].fd = fda->nr - fd;
13 fda->entries[fd].revents = revents;
14 }
15}
16
17static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp)
18{
19 int printed = 0;
20
21 if (!verbose)
22 return 0;
23
24 printed += fprintf(fp, "\n%s: ", prefix);
25 return printed + fdarray__fprintf(fda, fp);
26}
27
28int test__fdarray__filter(void)
29{
30 int nr_fds, expected_fd[2], fd, err = TEST_FAIL;
31 struct fdarray *fda = fdarray__new(5, 5);
32
33 if (fda == NULL) {
34 pr_debug("\nfdarray__new() failed!");
35 goto out;
36 }
37
38 fdarray__init_revents(fda, POLLIN);
39 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
40 if (nr_fds != fda->nr_alloc) {
41 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything",
42 nr_fds, fda->nr_alloc);
43 goto out_delete;
44 }
45
46 fdarray__init_revents(fda, POLLHUP);
47 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
48 if (nr_fds != 0) {
49 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds",
50 nr_fds, fda->nr_alloc);
51 goto out_delete;
52 }
53
54 fdarray__init_revents(fda, POLLHUP);
55 fda->entries[2].revents = POLLIN;
56 expected_fd[0] = fda->entries[2].fd;
57
58 pr_debug("\nfiltering all but fda->entries[2]:");
59 fdarray__fprintf_prefix(fda, "before", stderr);
60 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
61 fdarray__fprintf_prefix(fda, " after", stderr);
62 if (nr_fds != 1) {
63 pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds);
64 goto out_delete;
65 }
66
67 if (fda->entries[0].fd != expected_fd[0]) {
68 pr_debug("\nfda->entries[0].fd=%d != %d\n",
69 fda->entries[0].fd, expected_fd[0]);
70 goto out_delete;
71 }
72
73 fdarray__init_revents(fda, POLLHUP);
74 fda->entries[0].revents = POLLIN;
75 expected_fd[0] = fda->entries[0].fd;
76 fda->entries[3].revents = POLLIN;
77 expected_fd[1] = fda->entries[3].fd;
78
79 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):");
80 fdarray__fprintf_prefix(fda, "before", stderr);
81 nr_fds = fdarray__filter(fda, POLLHUP, NULL);
82 fdarray__fprintf_prefix(fda, " after", stderr);
83 if (nr_fds != 2) {
84 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events",
85 nr_fds);
86 goto out_delete;
87 }
88
89 for (fd = 0; fd < 2; ++fd) {
90 if (fda->entries[fd].fd != expected_fd[fd]) {
91 pr_debug("\nfda->entries[%d].fd=%d != %d\n", fd,
92 fda->entries[fd].fd, expected_fd[fd]);
93 goto out_delete;
94 }
95 }
96
97 pr_debug("\n");
98
99 err = 0;
100out_delete:
101 fdarray__delete(fda);
102out:
103 return err;
104}
105
106int test__fdarray__add(void)
107{
108 int err = TEST_FAIL;
109 struct fdarray *fda = fdarray__new(2, 2);
110
111 if (fda == NULL) {
112 pr_debug("\nfdarray__new() failed!");
113 goto out;
114 }
115
116#define FDA_CHECK(_idx, _fd, _revents) \
117 if (fda->entries[_idx].fd != _fd) { \
118 pr_debug("\n%d: fda->entries[%d](%d) != %d!", \
119 __LINE__, _idx, fda->entries[1].fd, _fd); \
120 goto out_delete; \
121 } \
122 if (fda->entries[_idx].events != (_revents)) { \
123 pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \
124 __LINE__, _idx, fda->entries[_idx].fd, _revents); \
125 goto out_delete; \
126 }
127
128#define FDA_ADD(_idx, _fd, _revents, _nr) \
129 if (fdarray__add(fda, _fd, _revents) < 0) { \
130 pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \
131 __LINE__,_fd, _revents); \
132 goto out_delete; \
133 } \
134 if (fda->nr != _nr) { \
135 pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \
136 __LINE__,_fd, _revents, fda->nr, _nr); \
137 goto out_delete; \
138 } \
139 FDA_CHECK(_idx, _fd, _revents)
140
141 FDA_ADD(0, 1, POLLIN, 1);
142 FDA_ADD(1, 2, POLLERR, 2);
143
144 fdarray__fprintf_prefix(fda, "before growing array", stderr);
145
146 FDA_ADD(2, 35, POLLHUP, 3);
147
148 if (fda->entries == NULL) {
149 pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!");
150 goto out_delete;
151 }
152
153 fdarray__fprintf_prefix(fda, "after 3rd add", stderr);
154
155 FDA_ADD(3, 88, POLLIN | POLLOUT, 4);
156
157 fdarray__fprintf_prefix(fda, "after 4th add", stderr);
158
159 FDA_CHECK(0, 1, POLLIN);
160 FDA_CHECK(1, 2, POLLERR);
161 FDA_CHECK(2, 35, POLLHUP);
162 FDA_CHECK(3, 88, POLLIN | POLLOUT);
163
164#undef FDA_ADD
165#undef FDA_CHECK
166
167 pr_debug("\n");
168
169 err = 0;
170out_delete:
171 fdarray__delete(fda);
172out:
173 return err;
174}
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 0ac240db2e24..8d110dec393e 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -187,7 +187,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
187 * function since TEST_ASSERT_VAL() returns in case of failure. 187 * function since TEST_ASSERT_VAL() returns in case of failure.
188 */ 188 */
189 hists__collapse_resort(hists, NULL); 189 hists__collapse_resort(hists, NULL);
190 hists__output_resort(hists); 190 hists__output_resort(hists, NULL);
191 191
192 if (verbose > 2) { 192 if (verbose > 2) {
193 pr_info("use callchain: %d, cumulate callchain: %d\n", 193 pr_info("use callchain: %d, cumulate callchain: %d\n",
@@ -245,7 +245,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
245static int test1(struct perf_evsel *evsel, struct machine *machine) 245static int test1(struct perf_evsel *evsel, struct machine *machine)
246{ 246{
247 int err; 247 int err;
248 struct hists *hists = &evsel->hists; 248 struct hists *hists = evsel__hists(evsel);
249 /* 249 /*
250 * expected output: 250 * expected output:
251 * 251 *
@@ -295,7 +295,7 @@ out:
295static int test2(struct perf_evsel *evsel, struct machine *machine) 295static int test2(struct perf_evsel *evsel, struct machine *machine)
296{ 296{
297 int err; 297 int err;
298 struct hists *hists = &evsel->hists; 298 struct hists *hists = evsel__hists(evsel);
299 /* 299 /*
300 * expected output: 300 * expected output:
301 * 301 *
@@ -442,7 +442,7 @@ out:
442static int test3(struct perf_evsel *evsel, struct machine *machine) 442static int test3(struct perf_evsel *evsel, struct machine *machine)
443{ 443{
444 int err; 444 int err;
445 struct hists *hists = &evsel->hists; 445 struct hists *hists = evsel__hists(evsel);
446 /* 446 /*
447 * expected output: 447 * expected output:
448 * 448 *
@@ -454,12 +454,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
454 * 30.00% 10.00% perf perf [.] cmd_record 454 * 30.00% 10.00% perf perf [.] cmd_record
455 * 20.00% 0.00% bash libc [.] malloc 455 * 20.00% 0.00% bash libc [.] malloc
456 * 10.00% 10.00% bash [kernel] [k] page_fault 456 * 10.00% 10.00% bash [kernel] [k] page_fault
457 * 10.00% 10.00% perf [kernel] [k] schedule 457 * 10.00% 10.00% bash bash [.] xmalloc
458 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
459 * 10.00% 10.00% perf [kernel] [k] page_fault 458 * 10.00% 10.00% perf [kernel] [k] page_fault
460 * 10.00% 10.00% perf libc [.] free
461 * 10.00% 10.00% perf libc [.] malloc 459 * 10.00% 10.00% perf libc [.] malloc
462 * 10.00% 10.00% bash bash [.] xmalloc 460 * 10.00% 10.00% perf [kernel] [k] schedule
461 * 10.00% 10.00% perf libc [.] free
462 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
463 */ 463 */
464 struct result expected[] = { 464 struct result expected[] = {
465 { 7000, 2000, "perf", "perf", "main" }, 465 { 7000, 2000, "perf", "perf", "main" },
@@ -468,12 +468,12 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
468 { 3000, 1000, "perf", "perf", "cmd_record" }, 468 { 3000, 1000, "perf", "perf", "cmd_record" },
469 { 2000, 0, "bash", "libc", "malloc" }, 469 { 2000, 0, "bash", "libc", "malloc" },
470 { 1000, 1000, "bash", "[kernel]", "page_fault" }, 470 { 1000, 1000, "bash", "[kernel]", "page_fault" },
471 { 1000, 1000, "perf", "[kernel]", "schedule" }, 471 { 1000, 1000, "bash", "bash", "xmalloc" },
472 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
473 { 1000, 1000, "perf", "[kernel]", "page_fault" }, 472 { 1000, 1000, "perf", "[kernel]", "page_fault" },
473 { 1000, 1000, "perf", "[kernel]", "schedule" },
474 { 1000, 1000, "perf", "libc", "free" }, 474 { 1000, 1000, "perf", "libc", "free" },
475 { 1000, 1000, "perf", "libc", "malloc" }, 475 { 1000, 1000, "perf", "libc", "malloc" },
476 { 1000, 1000, "bash", "bash", "xmalloc" }, 476 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
477 }; 477 };
478 478
479 symbol_conf.use_callchain = false; 479 symbol_conf.use_callchain = false;
@@ -498,7 +498,7 @@ out:
498static int test4(struct perf_evsel *evsel, struct machine *machine) 498static int test4(struct perf_evsel *evsel, struct machine *machine)
499{ 499{
500 int err; 500 int err;
501 struct hists *hists = &evsel->hists; 501 struct hists *hists = evsel__hists(evsel);
502 /* 502 /*
503 * expected output: 503 * expected output:
504 * 504 *
@@ -537,10 +537,13 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
537 * malloc 537 * malloc
538 * main 538 * main
539 * 539 *
540 * 10.00% 10.00% perf [kernel] [k] schedule 540 * 10.00% 10.00% bash bash [.] xmalloc
541 * | 541 * |
542 * --- schedule 542 * --- xmalloc
543 * run_command 543 * malloc
544 * xmalloc <--- NOTE: there's a cycle
545 * malloc
546 * xmalloc
544 * main 547 * main
545 * 548 *
546 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open 549 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
@@ -556,6 +559,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
556 * run_command 559 * run_command
557 * main 560 * main
558 * 561 *
562 * 10.00% 10.00% perf [kernel] [k] schedule
563 * |
564 * --- schedule
565 * run_command
566 * main
567 *
559 * 10.00% 10.00% perf libc [.] free 568 * 10.00% 10.00% perf libc [.] free
560 * | 569 * |
561 * --- free 570 * --- free
@@ -570,15 +579,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
570 * run_command 579 * run_command
571 * main 580 * main
572 * 581 *
573 * 10.00% 10.00% bash bash [.] xmalloc
574 * |
575 * --- xmalloc
576 * malloc
577 * xmalloc <--- NOTE: there's a cycle
578 * malloc
579 * xmalloc
580 * main
581 *
582 */ 582 */
583 struct result expected[] = { 583 struct result expected[] = {
584 { 7000, 2000, "perf", "perf", "main" }, 584 { 7000, 2000, "perf", "perf", "main" },
@@ -587,12 +587,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
587 { 3000, 1000, "perf", "perf", "cmd_record" }, 587 { 3000, 1000, "perf", "perf", "cmd_record" },
588 { 2000, 0, "bash", "libc", "malloc" }, 588 { 2000, 0, "bash", "libc", "malloc" },
589 { 1000, 1000, "bash", "[kernel]", "page_fault" }, 589 { 1000, 1000, "bash", "[kernel]", "page_fault" },
590 { 1000, 1000, "perf", "[kernel]", "schedule" }, 590 { 1000, 1000, "bash", "bash", "xmalloc" },
591 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" }, 591 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
592 { 1000, 1000, "perf", "[kernel]", "page_fault" }, 592 { 1000, 1000, "perf", "[kernel]", "page_fault" },
593 { 1000, 1000, "perf", "[kernel]", "schedule" },
593 { 1000, 1000, "perf", "libc", "free" }, 594 { 1000, 1000, "perf", "libc", "free" },
594 { 1000, 1000, "perf", "libc", "malloc" }, 595 { 1000, 1000, "perf", "libc", "malloc" },
595 { 1000, 1000, "bash", "bash", "xmalloc" },
596 }; 596 };
597 struct callchain_result expected_callchain[] = { 597 struct callchain_result expected_callchain[] = {
598 { 598 {
@@ -622,9 +622,12 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
622 { "bash", "main" }, }, 622 { "bash", "main" }, },
623 }, 623 },
624 { 624 {
625 3, { { "[kernel]", "schedule" }, 625 6, { { "bash", "xmalloc" },
626 { "perf", "run_command" }, 626 { "libc", "malloc" },
627 { "perf", "main" }, }, 627 { "bash", "xmalloc" },
628 { "libc", "malloc" },
629 { "bash", "xmalloc" },
630 { "bash", "main" }, },
628 }, 631 },
629 { 632 {
630 3, { { "[kernel]", "sys_perf_event_open" }, 633 3, { { "[kernel]", "sys_perf_event_open" },
@@ -638,6 +641,11 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
638 { "perf", "main" }, }, 641 { "perf", "main" }, },
639 }, 642 },
640 { 643 {
644 3, { { "[kernel]", "schedule" },
645 { "perf", "run_command" },
646 { "perf", "main" }, },
647 },
648 {
641 4, { { "libc", "free" }, 649 4, { { "libc", "free" },
642 { "perf", "cmd_record" }, 650 { "perf", "cmd_record" },
643 { "perf", "run_command" }, 651 { "perf", "run_command" },
@@ -649,14 +657,6 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
649 { "perf", "run_command" }, 657 { "perf", "run_command" },
650 { "perf", "main" }, }, 658 { "perf", "main" }, },
651 }, 659 },
652 {
653 6, { { "bash", "xmalloc" },
654 { "libc", "malloc" },
655 { "bash", "xmalloc" },
656 { "libc", "malloc" },
657 { "bash", "xmalloc" },
658 { "bash", "main" }, },
659 },
660 }; 660 };
661 661
662 symbol_conf.use_callchain = true; 662 symbol_conf.use_callchain = true;
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 821f581fd930..59e53db7914c 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -43,7 +43,7 @@ static struct sample fake_samples[] = {
43}; 43};
44 44
45static int add_hist_entries(struct perf_evlist *evlist, 45static int add_hist_entries(struct perf_evlist *evlist,
46 struct machine *machine __maybe_unused) 46 struct machine *machine)
47{ 47{
48 struct perf_evsel *evsel; 48 struct perf_evsel *evsel;
49 struct addr_location al; 49 struct addr_location al;
@@ -66,11 +66,12 @@ static int add_hist_entries(struct perf_evlist *evlist,
66 .ops = &hist_iter_normal, 66 .ops = &hist_iter_normal,
67 .hide_unresolved = false, 67 .hide_unresolved = false,
68 }; 68 };
69 struct hists *hists = evsel__hists(evsel);
69 70
70 /* make sure it has no filter at first */ 71 /* make sure it has no filter at first */
71 evsel->hists.thread_filter = NULL; 72 hists->thread_filter = NULL;
72 evsel->hists.dso_filter = NULL; 73 hists->dso_filter = NULL;
73 evsel->hists.symbol_filter_str = NULL; 74 hists->symbol_filter_str = NULL;
74 75
75 sample.pid = fake_samples[i].pid; 76 sample.pid = fake_samples[i].pid;
76 sample.tid = fake_samples[i].pid; 77 sample.tid = fake_samples[i].pid;
@@ -134,10 +135,10 @@ int test__hists_filter(void)
134 goto out; 135 goto out;
135 136
136 evlist__for_each(evlist, evsel) { 137 evlist__for_each(evlist, evsel) {
137 struct hists *hists = &evsel->hists; 138 struct hists *hists = evsel__hists(evsel);
138 139
139 hists__collapse_resort(hists, NULL); 140 hists__collapse_resort(hists, NULL);
140 hists__output_resort(hists); 141 hists__output_resort(hists, NULL);
141 142
142 if (verbose > 2) { 143 if (verbose > 2) {
143 pr_info("Normal histogram\n"); 144 pr_info("Normal histogram\n");
@@ -160,7 +161,7 @@ int test__hists_filter(void)
160 hists->stats.total_non_filtered_period); 161 hists->stats.total_non_filtered_period);
161 162
162 /* now applying thread filter for 'bash' */ 163 /* now applying thread filter for 'bash' */
163 evsel->hists.thread_filter = fake_samples[9].thread; 164 hists->thread_filter = fake_samples[9].thread;
164 hists__filter_by_thread(hists); 165 hists__filter_by_thread(hists);
165 166
166 if (verbose > 2) { 167 if (verbose > 2) {
@@ -185,11 +186,11 @@ int test__hists_filter(void)
185 hists->stats.total_non_filtered_period == 400); 186 hists->stats.total_non_filtered_period == 400);
186 187
187 /* remove thread filter first */ 188 /* remove thread filter first */
188 evsel->hists.thread_filter = NULL; 189 hists->thread_filter = NULL;
189 hists__filter_by_thread(hists); 190 hists__filter_by_thread(hists);
190 191
191 /* now applying dso filter for 'kernel' */ 192 /* now applying dso filter for 'kernel' */
192 evsel->hists.dso_filter = fake_samples[0].map->dso; 193 hists->dso_filter = fake_samples[0].map->dso;
193 hists__filter_by_dso(hists); 194 hists__filter_by_dso(hists);
194 195
195 if (verbose > 2) { 196 if (verbose > 2) {
@@ -214,7 +215,7 @@ int test__hists_filter(void)
214 hists->stats.total_non_filtered_period == 300); 215 hists->stats.total_non_filtered_period == 300);
215 216
216 /* remove dso filter first */ 217 /* remove dso filter first */
217 evsel->hists.dso_filter = NULL; 218 hists->dso_filter = NULL;
218 hists__filter_by_dso(hists); 219 hists__filter_by_dso(hists);
219 220
220 /* 221 /*
@@ -224,7 +225,7 @@ int test__hists_filter(void)
224 * be counted as a separate entry but the sample count and 225 * be counted as a separate entry but the sample count and
225 * total period will be remained. 226 * total period will be remained.
226 */ 227 */
227 evsel->hists.symbol_filter_str = "main"; 228 hists->symbol_filter_str = "main";
228 hists__filter_by_symbol(hists); 229 hists__filter_by_symbol(hists);
229 230
230 if (verbose > 2) { 231 if (verbose > 2) {
@@ -249,8 +250,8 @@ int test__hists_filter(void)
249 hists->stats.total_non_filtered_period == 300); 250 hists->stats.total_non_filtered_period == 300);
250 251
251 /* now applying all filters at once. */ 252 /* now applying all filters at once. */
252 evsel->hists.thread_filter = fake_samples[1].thread; 253 hists->thread_filter = fake_samples[1].thread;
253 evsel->hists.dso_filter = fake_samples[1].map->dso; 254 hists->dso_filter = fake_samples[1].map->dso;
254 hists__filter_by_thread(hists); 255 hists__filter_by_thread(hists);
255 hists__filter_by_dso(hists); 256 hists__filter_by_dso(hists);
256 257
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index d4b34b0f50a2..278ba8344c23 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -73,6 +73,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
73 * "bash [libc] malloc" so total 9 entries will be in the tree. 73 * "bash [libc] malloc" so total 9 entries will be in the tree.
74 */ 74 */
75 evlist__for_each(evlist, evsel) { 75 evlist__for_each(evlist, evsel) {
76 struct hists *hists = evsel__hists(evsel);
77
76 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { 78 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
77 const union perf_event event = { 79 const union perf_event event = {
78 .header = { 80 .header = {
@@ -87,7 +89,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
87 &sample) < 0) 89 &sample) < 0)
88 goto out; 90 goto out;
89 91
90 he = __hists__add_entry(&evsel->hists, &al, NULL, 92 he = __hists__add_entry(hists, &al, NULL,
91 NULL, NULL, 1, 1, 0, true); 93 NULL, NULL, 1, 1, 0, true);
92 if (he == NULL) 94 if (he == NULL)
93 goto out; 95 goto out;
@@ -111,7 +113,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
111 &sample) < 0) 113 &sample) < 0)
112 goto out; 114 goto out;
113 115
114 he = __hists__add_entry(&evsel->hists, &al, NULL, 116 he = __hists__add_entry(hists, &al, NULL,
115 NULL, NULL, 1, 1, 0, true); 117 NULL, NULL, 1, 1, 0, true);
116 if (he == NULL) 118 if (he == NULL)
117 goto out; 119 goto out;
@@ -271,6 +273,7 @@ static int validate_link(struct hists *leader, struct hists *other)
271int test__hists_link(void) 273int test__hists_link(void)
272{ 274{
273 int err = -1; 275 int err = -1;
276 struct hists *hists, *first_hists;
274 struct machines machines; 277 struct machines machines;
275 struct machine *machine = NULL; 278 struct machine *machine = NULL;
276 struct perf_evsel *evsel, *first; 279 struct perf_evsel *evsel, *first;
@@ -306,24 +309,28 @@ int test__hists_link(void)
306 goto out; 309 goto out;
307 310
308 evlist__for_each(evlist, evsel) { 311 evlist__for_each(evlist, evsel) {
309 hists__collapse_resort(&evsel->hists, NULL); 312 hists = evsel__hists(evsel);
313 hists__collapse_resort(hists, NULL);
310 314
311 if (verbose > 2) 315 if (verbose > 2)
312 print_hists_in(&evsel->hists); 316 print_hists_in(hists);
313 } 317 }
314 318
315 first = perf_evlist__first(evlist); 319 first = perf_evlist__first(evlist);
316 evsel = perf_evlist__last(evlist); 320 evsel = perf_evlist__last(evlist);
317 321
322 first_hists = evsel__hists(first);
323 hists = evsel__hists(evsel);
324
318 /* match common entries */ 325 /* match common entries */
319 hists__match(&first->hists, &evsel->hists); 326 hists__match(first_hists, hists);
320 err = validate_match(&first->hists, &evsel->hists); 327 err = validate_match(first_hists, hists);
321 if (err) 328 if (err)
322 goto out; 329 goto out;
323 330
324 /* link common and/or dummy entries */ 331 /* link common and/or dummy entries */
325 hists__link(&first->hists, &evsel->hists); 332 hists__link(first_hists, hists);
326 err = validate_link(&first->hists, &evsel->hists); 333 err = validate_link(first_hists, hists);
327 if (err) 334 if (err)
328 goto out; 335 goto out;
329 336
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index e3bbd6c54c1b..f5547610da02 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -122,7 +122,7 @@ typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
122static int test1(struct perf_evsel *evsel, struct machine *machine) 122static int test1(struct perf_evsel *evsel, struct machine *machine)
123{ 123{
124 int err; 124 int err;
125 struct hists *hists = &evsel->hists; 125 struct hists *hists = evsel__hists(evsel);
126 struct hist_entry *he; 126 struct hist_entry *he;
127 struct rb_root *root; 127 struct rb_root *root;
128 struct rb_node *node; 128 struct rb_node *node;
@@ -152,14 +152,14 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
152 goto out; 152 goto out;
153 153
154 hists__collapse_resort(hists, NULL); 154 hists__collapse_resort(hists, NULL);
155 hists__output_resort(hists); 155 hists__output_resort(hists, NULL);
156 156
157 if (verbose > 2) { 157 if (verbose > 2) {
158 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 158 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
159 print_hists_out(hists); 159 print_hists_out(hists);
160 } 160 }
161 161
162 root = &evsel->hists.entries; 162 root = &hists->entries;
163 node = rb_first(root); 163 node = rb_first(root);
164 he = rb_entry(node, struct hist_entry, rb_node); 164 he = rb_entry(node, struct hist_entry, rb_node);
165 TEST_ASSERT_VAL("Invalid hist entry", 165 TEST_ASSERT_VAL("Invalid hist entry",
@@ -224,7 +224,7 @@ out:
224static int test2(struct perf_evsel *evsel, struct machine *machine) 224static int test2(struct perf_evsel *evsel, struct machine *machine)
225{ 225{
226 int err; 226 int err;
227 struct hists *hists = &evsel->hists; 227 struct hists *hists = evsel__hists(evsel);
228 struct hist_entry *he; 228 struct hist_entry *he;
229 struct rb_root *root; 229 struct rb_root *root;
230 struct rb_node *node; 230 struct rb_node *node;
@@ -252,14 +252,14 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
252 goto out; 252 goto out;
253 253
254 hists__collapse_resort(hists, NULL); 254 hists__collapse_resort(hists, NULL);
255 hists__output_resort(hists); 255 hists__output_resort(hists, NULL);
256 256
257 if (verbose > 2) { 257 if (verbose > 2) {
258 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 258 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
259 print_hists_out(hists); 259 print_hists_out(hists);
260 } 260 }
261 261
262 root = &evsel->hists.entries; 262 root = &hists->entries;
263 node = rb_first(root); 263 node = rb_first(root);
264 he = rb_entry(node, struct hist_entry, rb_node); 264 he = rb_entry(node, struct hist_entry, rb_node);
265 TEST_ASSERT_VAL("Invalid hist entry", 265 TEST_ASSERT_VAL("Invalid hist entry",
@@ -280,7 +280,7 @@ out:
280static int test3(struct perf_evsel *evsel, struct machine *machine) 280static int test3(struct perf_evsel *evsel, struct machine *machine)
281{ 281{
282 int err; 282 int err;
283 struct hists *hists = &evsel->hists; 283 struct hists *hists = evsel__hists(evsel);
284 struct hist_entry *he; 284 struct hist_entry *he;
285 struct rb_root *root; 285 struct rb_root *root;
286 struct rb_node *node; 286 struct rb_node *node;
@@ -306,14 +306,14 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
306 goto out; 306 goto out;
307 307
308 hists__collapse_resort(hists, NULL); 308 hists__collapse_resort(hists, NULL);
309 hists__output_resort(hists); 309 hists__output_resort(hists, NULL);
310 310
311 if (verbose > 2) { 311 if (verbose > 2) {
312 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 312 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
313 print_hists_out(hists); 313 print_hists_out(hists);
314 } 314 }
315 315
316 root = &evsel->hists.entries; 316 root = &hists->entries;
317 node = rb_first(root); 317 node = rb_first(root);
318 he = rb_entry(node, struct hist_entry, rb_node); 318 he = rb_entry(node, struct hist_entry, rb_node);
319 TEST_ASSERT_VAL("Invalid hist entry", 319 TEST_ASSERT_VAL("Invalid hist entry",
@@ -354,7 +354,7 @@ out:
354static int test4(struct perf_evsel *evsel, struct machine *machine) 354static int test4(struct perf_evsel *evsel, struct machine *machine)
355{ 355{
356 int err; 356 int err;
357 struct hists *hists = &evsel->hists; 357 struct hists *hists = evsel__hists(evsel);
358 struct hist_entry *he; 358 struct hist_entry *he;
359 struct rb_root *root; 359 struct rb_root *root;
360 struct rb_node *node; 360 struct rb_node *node;
@@ -384,14 +384,14 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
384 goto out; 384 goto out;
385 385
386 hists__collapse_resort(hists, NULL); 386 hists__collapse_resort(hists, NULL);
387 hists__output_resort(hists); 387 hists__output_resort(hists, NULL);
388 388
389 if (verbose > 2) { 389 if (verbose > 2) {
390 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 390 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
391 print_hists_out(hists); 391 print_hists_out(hists);
392 } 392 }
393 393
394 root = &evsel->hists.entries; 394 root = &hists->entries;
395 node = rb_first(root); 395 node = rb_first(root);
396 he = rb_entry(node, struct hist_entry, rb_node); 396 he = rb_entry(node, struct hist_entry, rb_node);
397 TEST_ASSERT_VAL("Invalid hist entry", 397 TEST_ASSERT_VAL("Invalid hist entry",
@@ -456,7 +456,7 @@ out:
456static int test5(struct perf_evsel *evsel, struct machine *machine) 456static int test5(struct perf_evsel *evsel, struct machine *machine)
457{ 457{
458 int err; 458 int err;
459 struct hists *hists = &evsel->hists; 459 struct hists *hists = evsel__hists(evsel);
460 struct hist_entry *he; 460 struct hist_entry *he;
461 struct rb_root *root; 461 struct rb_root *root;
462 struct rb_node *node; 462 struct rb_node *node;
@@ -487,14 +487,14 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
487 goto out; 487 goto out;
488 488
489 hists__collapse_resort(hists, NULL); 489 hists__collapse_resort(hists, NULL);
490 hists__output_resort(hists); 490 hists__output_resort(hists, NULL);
491 491
492 if (verbose > 2) { 492 if (verbose > 2) {
493 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); 493 pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
494 print_hists_out(hists); 494 print_hists_out(hists);
495 } 495 }
496 496
497 root = &evsel->hists.entries; 497 root = &hists->entries;
498 node = rb_first(root); 498 node = rb_first(root);
499 he = rb_entry(node, struct hist_entry, rb_node); 499 he = rb_entry(node, struct hist_entry, rb_node);
500 500
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 142263492f6f..9b9622a33932 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -31,6 +31,7 @@ int test__basic_mmap(void)
31 unsigned int nr_events[nsyscalls], 31 unsigned int nr_events[nsyscalls],
32 expected_nr_events[nsyscalls], i, j; 32 expected_nr_events[nsyscalls], i, j;
33 struct perf_evsel *evsels[nsyscalls], *evsel; 33 struct perf_evsel *evsels[nsyscalls], *evsel;
34 char sbuf[STRERR_BUFSIZE];
34 35
35 threads = thread_map__new(-1, getpid(), UINT_MAX); 36 threads = thread_map__new(-1, getpid(), UINT_MAX);
36 if (threads == NULL) { 37 if (threads == NULL) {
@@ -49,7 +50,7 @@ int test__basic_mmap(void)
49 sched_setaffinity(0, sizeof(cpu_set), &cpu_set); 50 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
50 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 51 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
51 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 52 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
52 cpus->map[0], strerror(errno)); 53 cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf)));
53 goto out_free_cpus; 54 goto out_free_cpus;
54 } 55 }
55 56
@@ -79,7 +80,7 @@ int test__basic_mmap(void)
79 if (perf_evsel__open(evsels[i], cpus, threads) < 0) { 80 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
80 pr_debug("failed to open counter: %s, " 81 pr_debug("failed to open counter: %s, "
81 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 82 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
82 strerror(errno)); 83 strerror_r(errno, sbuf, sizeof(sbuf)));
83 goto out_delete_evlist; 84 goto out_delete_evlist;
84 } 85 }
85 86
@@ -89,7 +90,7 @@ int test__basic_mmap(void)
89 90
90 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
91 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
92 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
93 goto out_delete_evlist; 94 goto out_delete_evlist;
94 } 95 }
95 96
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 4a456fef66ca..2113f1c8611f 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -187,7 +187,7 @@ static int mmap_events(synth_cb synth)
187 187
188 pr_debug("looking for map %p\n", td->map); 188 pr_debug("looking for map %p\n", td->map);
189 189
190 thread__find_addr_map(thread, machine, 190 thread__find_addr_map(thread,
191 PERF_RECORD_MISC_USER, MAP__FUNCTION, 191 PERF_RECORD_MISC_USER, MAP__FUNCTION,
192 (unsigned long) (td->map + 1), &al); 192 (unsigned long) (td->map + 1), &al);
193 193
diff --git a/tools/perf/tests/open-syscall-all-cpus.c b/tools/perf/tests/open-syscall-all-cpus.c
index 5fecdbd2f5f7..8fa82d1700c7 100644
--- a/tools/perf/tests/open-syscall-all-cpus.c
+++ b/tools/perf/tests/open-syscall-all-cpus.c
@@ -12,6 +12,7 @@ int test__open_syscall_event_on_all_cpus(void)
12 unsigned int nr_open_calls = 111, i; 12 unsigned int nr_open_calls = 111, i;
13 cpu_set_t cpu_set; 13 cpu_set_t cpu_set;
14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 14 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
15 char sbuf[STRERR_BUFSIZE];
15 16
16 if (threads == NULL) { 17 if (threads == NULL) {
17 pr_debug("thread_map__new\n"); 18 pr_debug("thread_map__new\n");
@@ -35,7 +36,7 @@ int test__open_syscall_event_on_all_cpus(void)
35 if (perf_evsel__open(evsel, cpus, threads) < 0) { 36 if (perf_evsel__open(evsel, cpus, threads) < 0) {
36 pr_debug("failed to open counter: %s, " 37 pr_debug("failed to open counter: %s, "
37 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 38 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
38 strerror(errno)); 39 strerror_r(errno, sbuf, sizeof(sbuf)));
39 goto out_evsel_delete; 40 goto out_evsel_delete;
40 } 41 }
41 42
@@ -56,7 +57,7 @@ int test__open_syscall_event_on_all_cpus(void)
56 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 57 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
57 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 58 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
58 cpus->map[cpu], 59 cpus->map[cpu],
59 strerror(errno)); 60 strerror_r(errno, sbuf, sizeof(sbuf)));
60 goto out_close_fd; 61 goto out_close_fd;
61 } 62 }
62 for (i = 0; i < ncalls; ++i) { 63 for (i = 0; i < ncalls; ++i) {
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c
index 0785b64ffd6c..127dcae0b760 100644
--- a/tools/perf/tests/open-syscall-tp-fields.c
+++ b/tools/perf/tests/open-syscall-tp-fields.c
@@ -22,6 +22,7 @@ int test__syscall_open_tp_fields(void)
22 struct perf_evlist *evlist = perf_evlist__new(); 22 struct perf_evlist *evlist = perf_evlist__new();
23 struct perf_evsel *evsel; 23 struct perf_evsel *evsel;
24 int err = -1, i, nr_events = 0, nr_polls = 0; 24 int err = -1, i, nr_events = 0, nr_polls = 0;
25 char sbuf[STRERR_BUFSIZE];
25 26
26 if (evlist == NULL) { 27 if (evlist == NULL) {
27 pr_debug("%s: perf_evlist__new\n", __func__); 28 pr_debug("%s: perf_evlist__new\n", __func__);
@@ -48,13 +49,15 @@ int test__syscall_open_tp_fields(void)
48 49
49 err = perf_evlist__open(evlist); 50 err = perf_evlist__open(evlist);
50 if (err < 0) { 51 if (err < 0) {
51 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 52 pr_debug("perf_evlist__open: %s\n",
53 strerror_r(errno, sbuf, sizeof(sbuf)));
52 goto out_delete_evlist; 54 goto out_delete_evlist;
53 } 55 }
54 56
55 err = perf_evlist__mmap(evlist, UINT_MAX, false); 57 err = perf_evlist__mmap(evlist, UINT_MAX, false);
56 if (err < 0) { 58 if (err < 0) {
57 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 59 pr_debug("perf_evlist__mmap: %s\n",
60 strerror_r(errno, sbuf, sizeof(sbuf)));
58 goto out_delete_evlist; 61 goto out_delete_evlist;
59 } 62 }
60 63
@@ -102,7 +105,7 @@ int test__syscall_open_tp_fields(void)
102 } 105 }
103 106
104 if (nr_events == before) 107 if (nr_events == before)
105 poll(evlist->pollfd, evlist->nr_fds, 10); 108 perf_evlist__poll(evlist, 10);
106 109
107 if (++nr_polls > 5) { 110 if (++nr_polls > 5) {
108 pr_debug("%s: no events!\n", __func__); 111 pr_debug("%s: no events!\n", __func__);
diff --git a/tools/perf/tests/open-syscall.c b/tools/perf/tests/open-syscall.c
index c1dc7d25f38c..a33b2daae40f 100644
--- a/tools/perf/tests/open-syscall.c
+++ b/tools/perf/tests/open-syscall.c
@@ -9,6 +9,7 @@ int test__open_syscall_event(void)
9 struct perf_evsel *evsel; 9 struct perf_evsel *evsel;
10 unsigned int nr_open_calls = 111, i; 10 unsigned int nr_open_calls = 111, i;
11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX); 11 struct thread_map *threads = thread_map__new(-1, getpid(), UINT_MAX);
12 char sbuf[STRERR_BUFSIZE];
12 13
13 if (threads == NULL) { 14 if (threads == NULL) {
14 pr_debug("thread_map__new\n"); 15 pr_debug("thread_map__new\n");
@@ -24,7 +25,7 @@ int test__open_syscall_event(void)
24 if (perf_evsel__open_per_thread(evsel, threads) < 0) { 25 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
25 pr_debug("failed to open counter: %s, " 26 pr_debug("failed to open counter: %s, "
26 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 27 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
27 strerror(errno)); 28 strerror_r(errno, sbuf, sizeof(sbuf)));
28 goto out_evsel_delete; 29 goto out_evsel_delete;
29 } 30 }
30 31
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 5941927a4b7f..7f2f51f93619 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -457,6 +457,36 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist)
457 return 0; 457 return 0;
458} 458}
459 459
460
461static int test__checkevent_pmu_events_mix(struct perf_evlist *evlist)
462{
463 struct perf_evsel *evsel = perf_evlist__first(evlist);
464
465 /* pmu-event:u */
466 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
467 TEST_ASSERT_VAL("wrong exclude_user",
468 !evsel->attr.exclude_user);
469 TEST_ASSERT_VAL("wrong exclude_kernel",
470 evsel->attr.exclude_kernel);
471 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
472 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
473 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
474
475 /* cpu/pmu-event/u*/
476 evsel = perf_evsel__next(evsel);
477 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
478 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
479 TEST_ASSERT_VAL("wrong exclude_user",
480 !evsel->attr.exclude_user);
481 TEST_ASSERT_VAL("wrong exclude_kernel",
482 evsel->attr.exclude_kernel);
483 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
484 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
485 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
486
487 return 0;
488}
489
460static int test__checkterms_simple(struct list_head *terms) 490static int test__checkterms_simple(struct list_head *terms)
461{ 491{
462 struct parse_events_term *term; 492 struct parse_events_term *term;
@@ -1554,6 +1584,12 @@ static int test_pmu_events(void)
1554 e.check = test__checkevent_pmu_events; 1584 e.check = test__checkevent_pmu_events;
1555 1585
1556 ret = test_event(&e); 1586 ret = test_event(&e);
1587 if (ret)
1588 break;
1589 snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
1590 e.name = name;
1591 e.check = test__checkevent_pmu_events_mix;
1592 ret = test_event(&e);
1557#undef MAX_NAME 1593#undef MAX_NAME
1558 } 1594 }
1559 1595
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index aca1a83dd13a..7a228a2a070b 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -59,6 +59,7 @@ int test__PERF_RECORD(void)
59 int err = -1, errs = 0, i, wakeups = 0; 59 int err = -1, errs = 0, i, wakeups = 0;
60 u32 cpu; 60 u32 cpu;
61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, }; 61 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
62 char sbuf[STRERR_BUFSIZE];
62 63
63 if (evlist == NULL || argv == NULL) { 64 if (evlist == NULL || argv == NULL) {
64 pr_debug("Not enough memory to create evlist\n"); 65 pr_debug("Not enough memory to create evlist\n");
@@ -100,7 +101,8 @@ int test__PERF_RECORD(void)
100 101
101 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 102 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
102 if (err < 0) { 103 if (err < 0) {
103 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); 104 pr_debug("sched__get_first_possible_cpu: %s\n",
105 strerror_r(errno, sbuf, sizeof(sbuf)));
104 goto out_delete_evlist; 106 goto out_delete_evlist;
105 } 107 }
106 108
@@ -110,7 +112,8 @@ int test__PERF_RECORD(void)
110 * So that we can check perf_sample.cpu on all the samples. 112 * So that we can check perf_sample.cpu on all the samples.
111 */ 113 */
112 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { 114 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
113 pr_debug("sched_setaffinity: %s\n", strerror(errno)); 115 pr_debug("sched_setaffinity: %s\n",
116 strerror_r(errno, sbuf, sizeof(sbuf)));
114 goto out_delete_evlist; 117 goto out_delete_evlist;
115 } 118 }
116 119
@@ -120,7 +123,8 @@ int test__PERF_RECORD(void)
120 */ 123 */
121 err = perf_evlist__open(evlist); 124 err = perf_evlist__open(evlist);
122 if (err < 0) { 125 if (err < 0) {
123 pr_debug("perf_evlist__open: %s\n", strerror(errno)); 126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf)));
124 goto out_delete_evlist; 128 goto out_delete_evlist;
125 } 129 }
126 130
@@ -131,7 +135,8 @@ int test__PERF_RECORD(void)
131 */ 135 */
132 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 136 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
133 if (err < 0) { 137 if (err < 0) {
134 pr_debug("perf_evlist__mmap: %s\n", strerror(errno)); 138 pr_debug("perf_evlist__mmap: %s\n",
139 strerror_r(errno, sbuf, sizeof(sbuf)));
135 goto out_delete_evlist; 140 goto out_delete_evlist;
136 } 141 }
137 142
@@ -263,7 +268,7 @@ int test__PERF_RECORD(void)
263 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does. 268 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
264 */ 269 */
265 if (total_events == before && false) 270 if (total_events == before && false)
266 poll(evlist->pollfd, evlist->nr_fds, -1); 271 perf_evlist__poll(evlist, -1);
267 272
268 sleep(1); 273 sleep(1);
269 if (++wakeups > 5) { 274 if (++wakeups > 5) {
diff --git a/tools/perf/tests/pmu.c b/tools/perf/tests/pmu.c
index 12b322fa3475..eeb68bb1972d 100644
--- a/tools/perf/tests/pmu.c
+++ b/tools/perf/tests/pmu.c
@@ -152,7 +152,7 @@ int test__pmu(void)
152 if (ret) 152 if (ret)
153 break; 153 break;
154 154
155 ret = perf_pmu__config_terms(&formats, &attr, terms); 155 ret = perf_pmu__config_terms(&formats, &attr, terms, false);
156 if (ret) 156 if (ret)
157 break; 157 break;
158 158
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c
index c04d1f268576..d31f2c4d9f64 100644
--- a/tools/perf/tests/rdpmc.c
+++ b/tools/perf/tests/rdpmc.c
@@ -100,6 +100,7 @@ static int __test__rdpmc(void)
100 }; 100 };
101 u64 delta_sum = 0; 101 u64 delta_sum = 0;
102 struct sigaction sa; 102 struct sigaction sa;
103 char sbuf[STRERR_BUFSIZE];
103 104
104 sigfillset(&sa.sa_mask); 105 sigfillset(&sa.sa_mask);
105 sa.sa_sigaction = segfault_handler; 106 sa.sa_sigaction = segfault_handler;
@@ -109,14 +110,15 @@ static int __test__rdpmc(void)
109 perf_event_open_cloexec_flag()); 110 perf_event_open_cloexec_flag());
110 if (fd < 0) { 111 if (fd < 0) {
111 pr_err("Error: sys_perf_event_open() syscall returned " 112 pr_err("Error: sys_perf_event_open() syscall returned "
112 "with %d (%s)\n", fd, strerror(errno)); 113 "with %d (%s)\n", fd,
114 strerror_r(errno, sbuf, sizeof(sbuf)));
113 return -1; 115 return -1;
114 } 116 }
115 117
116 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 118 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
117 if (addr == (void *)(-1)) { 119 if (addr == (void *)(-1)) {
118 pr_err("Error: mmap() syscall returned with (%s)\n", 120 pr_err("Error: mmap() syscall returned with (%s)\n",
119 strerror(errno)); 121 strerror_r(errno, sbuf, sizeof(sbuf)));
120 goto out_close; 122 goto out_close;
121 } 123 }
122 124
diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c
index ca292f9a4ae2..4908c648a597 100644
--- a/tools/perf/tests/sample-parsing.c
+++ b/tools/perf/tests/sample-parsing.c
@@ -126,16 +126,28 @@ static bool samples_same(const struct perf_sample *s1,
126 if (type & PERF_SAMPLE_TRANSACTION) 126 if (type & PERF_SAMPLE_TRANSACTION)
127 COMP(transaction); 127 COMP(transaction);
128 128
129 if (type & PERF_SAMPLE_REGS_INTR) {
130 size_t sz = hweight_long(s1->intr_regs.mask) * sizeof(u64);
131
132 COMP(intr_regs.mask);
133 COMP(intr_regs.abi);
134 if (s1->intr_regs.abi &&
135 (!s1->intr_regs.regs || !s2->intr_regs.regs ||
136 memcmp(s1->intr_regs.regs, s2->intr_regs.regs, sz))) {
137 pr_debug("Samples differ at 'intr_regs'\n");
138 return false;
139 }
140 }
141
129 return true; 142 return true;
130} 143}
131 144
132static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format) 145static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
133{ 146{
134 struct perf_evsel evsel = { 147 struct perf_evsel evsel = {
135 .needs_swap = false, 148 .needs_swap = false,
136 .attr = { 149 .attr = {
137 .sample_type = sample_type, 150 .sample_type = sample_type,
138 .sample_regs_user = sample_regs_user,
139 .read_format = read_format, 151 .read_format = read_format,
140 }, 152 },
141 }; 153 };
@@ -154,7 +166,7 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
154 /* 1 branch_entry */ 166 /* 1 branch_entry */
155 .data = {1, 211, 212, 213}, 167 .data = {1, 211, 212, 213},
156 }; 168 };
157 u64 user_regs[64]; 169 u64 regs[64];
158 const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; 170 const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL};
159 const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; 171 const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL};
160 struct perf_sample sample = { 172 struct perf_sample sample = {
@@ -176,8 +188,8 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
176 .branch_stack = &branch_stack.branch_stack, 188 .branch_stack = &branch_stack.branch_stack,
177 .user_regs = { 189 .user_regs = {
178 .abi = PERF_SAMPLE_REGS_ABI_64, 190 .abi = PERF_SAMPLE_REGS_ABI_64,
179 .mask = sample_regs_user, 191 .mask = sample_regs,
180 .regs = user_regs, 192 .regs = regs,
181 }, 193 },
182 .user_stack = { 194 .user_stack = {
183 .size = sizeof(data), 195 .size = sizeof(data),
@@ -187,14 +199,25 @@ static int do_test(u64 sample_type, u64 sample_regs_user, u64 read_format)
187 .time_enabled = 0x030a59d664fca7deULL, 199 .time_enabled = 0x030a59d664fca7deULL,
188 .time_running = 0x011b6ae553eb98edULL, 200 .time_running = 0x011b6ae553eb98edULL,
189 }, 201 },
202 .intr_regs = {
203 .abi = PERF_SAMPLE_REGS_ABI_64,
204 .mask = sample_regs,
205 .regs = regs,
206 },
190 }; 207 };
191 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; 208 struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},};
192 struct perf_sample sample_out; 209 struct perf_sample sample_out;
193 size_t i, sz, bufsz; 210 size_t i, sz, bufsz;
194 int err, ret = -1; 211 int err, ret = -1;
195 212
196 for (i = 0; i < sizeof(user_regs); i++) 213 if (sample_type & PERF_SAMPLE_REGS_USER)
197 *(i + (u8 *)user_regs) = i & 0xfe; 214 evsel.attr.sample_regs_user = sample_regs;
215
216 if (sample_type & PERF_SAMPLE_REGS_INTR)
217 evsel.attr.sample_regs_intr = sample_regs;
218
219 for (i = 0; i < sizeof(regs); i++)
220 *(i + (u8 *)regs) = i & 0xfe;
198 221
199 if (read_format & PERF_FORMAT_GROUP) { 222 if (read_format & PERF_FORMAT_GROUP) {
200 sample.read.group.nr = 4; 223 sample.read.group.nr = 4;
@@ -271,7 +294,7 @@ int test__sample_parsing(void)
271{ 294{
272 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; 295 const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15};
273 u64 sample_type; 296 u64 sample_type;
274 u64 sample_regs_user; 297 u64 sample_regs;
275 size_t i; 298 size_t i;
276 int err; 299 int err;
277 300
@@ -280,7 +303,7 @@ int test__sample_parsing(void)
280 * were added. Please actually update the test rather than just change 303 * were added. Please actually update the test rather than just change
281 * the condition below. 304 * the condition below.
282 */ 305 */
283 if (PERF_SAMPLE_MAX > PERF_SAMPLE_TRANSACTION << 1) { 306 if (PERF_SAMPLE_MAX > PERF_SAMPLE_REGS_INTR << 1) {
284 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n"); 307 pr_debug("sample format has changed, some new PERF_SAMPLE_ bit was introduced - test needs updating\n");
285 return -1; 308 return -1;
286 } 309 }
@@ -297,22 +320,24 @@ int test__sample_parsing(void)
297 } 320 }
298 continue; 321 continue;
299 } 322 }
323 sample_regs = 0;
300 324
301 if (sample_type == PERF_SAMPLE_REGS_USER) 325 if (sample_type == PERF_SAMPLE_REGS_USER)
302 sample_regs_user = 0x3fff; 326 sample_regs = 0x3fff;
303 else 327
304 sample_regs_user = 0; 328 if (sample_type == PERF_SAMPLE_REGS_INTR)
329 sample_regs = 0xff0fff;
305 330
306 err = do_test(sample_type, sample_regs_user, 0); 331 err = do_test(sample_type, sample_regs, 0);
307 if (err) 332 if (err)
308 return err; 333 return err;
309 } 334 }
310 335
311 /* Test all sample format bits together */ 336 /* Test all sample format bits together */
312 sample_type = PERF_SAMPLE_MAX - 1; 337 sample_type = PERF_SAMPLE_MAX - 1;
313 sample_regs_user = 0x3fff; 338 sample_regs = 0x3fff; /* shared yb intr and user regs */
314 for (i = 0; i < ARRAY_SIZE(rf); i++) { 339 for (i = 0; i < ARRAY_SIZE(rf); i++) {
315 err = do_test(sample_type, sample_regs_user, rf[i]); 340 err = do_test(sample_type, sample_regs, rf[i]);
316 if (err) 341 if (err)
317 return err; 342 return err;
318 } 343 }
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 983d6b8562a8..1aa21c90731b 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -22,6 +22,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
22 volatile int tmp = 0; 22 volatile int tmp = 0;
23 u64 total_periods = 0; 23 u64 total_periods = 0;
24 int nr_samples = 0; 24 int nr_samples = 0;
25 char sbuf[STRERR_BUFSIZE];
25 union perf_event *event; 26 union perf_event *event;
26 struct perf_evsel *evsel; 27 struct perf_evsel *evsel;
27 struct perf_evlist *evlist; 28 struct perf_evlist *evlist;
@@ -62,14 +63,15 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
62 63
63 err = -errno; 64 err = -errno;
64 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", 65 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
65 strerror(errno), knob, (u64)attr.sample_freq); 66 strerror_r(errno, sbuf, sizeof(sbuf)),
67 knob, (u64)attr.sample_freq);
66 goto out_delete_evlist; 68 goto out_delete_evlist;
67 } 69 }
68 70
69 err = perf_evlist__mmap(evlist, 128, true); 71 err = perf_evlist__mmap(evlist, 128, true);
70 if (err < 0) { 72 if (err < 0) {
71 pr_debug("failed to mmap event: %d (%s)\n", errno, 73 pr_debug("failed to mmap event: %d (%s)\n", errno,
72 strerror(errno)); 74 strerror_r(errno, sbuf, sizeof(sbuf)));
73 goto out_delete_evlist; 75 goto out_delete_evlist;
74 } 76 }
75 77
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
new file mode 100644
index 000000000000..cc68648c7c55
--- /dev/null
+++ b/tools/perf/tests/switch-tracking.c
@@ -0,0 +1,572 @@
1#include <sys/time.h>
2#include <sys/prctl.h>
3#include <time.h>
4#include <stdlib.h>
5
6#include "parse-events.h"
7#include "evlist.h"
8#include "evsel.h"
9#include "thread_map.h"
10#include "cpumap.h"
11#include "tests.h"
12
13static int spin_sleep(void)
14{
15 struct timeval start, now, diff, maxtime;
16 struct timespec ts;
17 int err, i;
18
19 maxtime.tv_sec = 0;
20 maxtime.tv_usec = 50000;
21
22 err = gettimeofday(&start, NULL);
23 if (err)
24 return err;
25
26 /* Spin for 50ms */
27 while (1) {
28 for (i = 0; i < 1000; i++)
29 barrier();
30
31 err = gettimeofday(&now, NULL);
32 if (err)
33 return err;
34
35 timersub(&now, &start, &diff);
36 if (timercmp(&diff, &maxtime, > /* For checkpatch */))
37 break;
38 }
39
40 ts.tv_nsec = 50 * 1000 * 1000;
41 ts.tv_sec = 0;
42
43 /* Sleep for 50ms */
44 err = nanosleep(&ts, NULL);
45 if (err == EINTR)
46 err = 0;
47
48 return err;
49}
50
51struct switch_tracking {
52 struct perf_evsel *switch_evsel;
53 struct perf_evsel *cycles_evsel;
54 pid_t *tids;
55 int nr_tids;
56 int comm_seen[4];
57 int cycles_before_comm_1;
58 int cycles_between_comm_2_and_comm_3;
59 int cycles_after_comm_4;
60};
61
62static int check_comm(struct switch_tracking *switch_tracking,
63 union perf_event *event, const char *comm, int nr)
64{
65 if (event->header.type == PERF_RECORD_COMM &&
66 (pid_t)event->comm.pid == getpid() &&
67 (pid_t)event->comm.tid == getpid() &&
68 strcmp(event->comm.comm, comm) == 0) {
69 if (switch_tracking->comm_seen[nr]) {
70 pr_debug("Duplicate comm event\n");
71 return -1;
72 }
73 switch_tracking->comm_seen[nr] = 1;
74 pr_debug3("comm event: %s nr: %d\n", event->comm.comm, nr);
75 return 1;
76 }
77 return 0;
78}
79
80static int check_cpu(struct switch_tracking *switch_tracking, int cpu)
81{
82 int i, nr = cpu + 1;
83
84 if (cpu < 0)
85 return -1;
86
87 if (!switch_tracking->tids) {
88 switch_tracking->tids = calloc(nr, sizeof(pid_t));
89 if (!switch_tracking->tids)
90 return -1;
91 for (i = 0; i < nr; i++)
92 switch_tracking->tids[i] = -1;
93 switch_tracking->nr_tids = nr;
94 return 0;
95 }
96
97 if (cpu >= switch_tracking->nr_tids) {
98 void *addr;
99
100 addr = realloc(switch_tracking->tids, nr * sizeof(pid_t));
101 if (!addr)
102 return -1;
103 switch_tracking->tids = addr;
104 for (i = switch_tracking->nr_tids; i < nr; i++)
105 switch_tracking->tids[i] = -1;
106 switch_tracking->nr_tids = nr;
107 return 0;
108 }
109
110 return 0;
111}
112
113static int process_sample_event(struct perf_evlist *evlist,
114 union perf_event *event,
115 struct switch_tracking *switch_tracking)
116{
117 struct perf_sample sample;
118 struct perf_evsel *evsel;
119 pid_t next_tid, prev_tid;
120 int cpu, err;
121
122 if (perf_evlist__parse_sample(evlist, event, &sample)) {
123 pr_debug("perf_evlist__parse_sample failed\n");
124 return -1;
125 }
126
127 evsel = perf_evlist__id2evsel(evlist, sample.id);
128 if (evsel == switch_tracking->switch_evsel) {
129 next_tid = perf_evsel__intval(evsel, &sample, "next_pid");
130 prev_tid = perf_evsel__intval(evsel, &sample, "prev_pid");
131 cpu = sample.cpu;
132 pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n",
133 cpu, prev_tid, next_tid);
134 err = check_cpu(switch_tracking, cpu);
135 if (err)
136 return err;
137 /*
138 * Check for no missing sched_switch events i.e. that the
139 * evsel->system_wide flag has worked.
140 */
141 if (switch_tracking->tids[cpu] != -1 &&
142 switch_tracking->tids[cpu] != prev_tid) {
143 pr_debug("Missing sched_switch events\n");
144 return -1;
145 }
146 switch_tracking->tids[cpu] = next_tid;
147 }
148
149 if (evsel == switch_tracking->cycles_evsel) {
150 pr_debug3("cycles event\n");
151 if (!switch_tracking->comm_seen[0])
152 switch_tracking->cycles_before_comm_1 = 1;
153 if (switch_tracking->comm_seen[1] &&
154 !switch_tracking->comm_seen[2])
155 switch_tracking->cycles_between_comm_2_and_comm_3 = 1;
156 if (switch_tracking->comm_seen[3])
157 switch_tracking->cycles_after_comm_4 = 1;
158 }
159
160 return 0;
161}
162
163static int process_event(struct perf_evlist *evlist, union perf_event *event,
164 struct switch_tracking *switch_tracking)
165{
166 if (event->header.type == PERF_RECORD_SAMPLE)
167 return process_sample_event(evlist, event, switch_tracking);
168
169 if (event->header.type == PERF_RECORD_COMM) {
170 int err, done = 0;
171
172 err = check_comm(switch_tracking, event, "Test COMM 1", 0);
173 if (err < 0)
174 return -1;
175 done += err;
176 err = check_comm(switch_tracking, event, "Test COMM 2", 1);
177 if (err < 0)
178 return -1;
179 done += err;
180 err = check_comm(switch_tracking, event, "Test COMM 3", 2);
181 if (err < 0)
182 return -1;
183 done += err;
184 err = check_comm(switch_tracking, event, "Test COMM 4", 3);
185 if (err < 0)
186 return -1;
187 done += err;
188 if (done != 1) {
189 pr_debug("Unexpected comm event\n");
190 return -1;
191 }
192 }
193
194 return 0;
195}
196
197struct event_node {
198 struct list_head list;
199 union perf_event *event;
200 u64 event_time;
201};
202
203static int add_event(struct perf_evlist *evlist, struct list_head *events,
204 union perf_event *event)
205{
206 struct perf_sample sample;
207 struct event_node *node;
208
209 node = malloc(sizeof(struct event_node));
210 if (!node) {
211 pr_debug("malloc failed\n");
212 return -1;
213 }
214 node->event = event;
215 list_add(&node->list, events);
216
217 if (perf_evlist__parse_sample(evlist, event, &sample)) {
218 pr_debug("perf_evlist__parse_sample failed\n");
219 return -1;
220 }
221
222 if (!sample.time) {
223 pr_debug("event with no time\n");
224 return -1;
225 }
226
227 node->event_time = sample.time;
228
229 return 0;
230}
231
232static void free_event_nodes(struct list_head *events)
233{
234 struct event_node *node;
235
236 while (!list_empty(events)) {
237 node = list_entry(events->next, struct event_node, list);
238 list_del(&node->list);
239 free(node);
240 }
241}
242
243static int compar(const void *a, const void *b)
244{
245 const struct event_node *nodea = a;
246 const struct event_node *nodeb = b;
247 s64 cmp = nodea->event_time - nodeb->event_time;
248
249 return cmp;
250}
251
252static int process_events(struct perf_evlist *evlist,
253 struct switch_tracking *switch_tracking)
254{
255 union perf_event *event;
256 unsigned pos, cnt = 0;
257 LIST_HEAD(events);
258 struct event_node *events_array, *node;
259 int i, ret;
260
261 for (i = 0; i < evlist->nr_mmaps; i++) {
262 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
263 cnt += 1;
264 ret = add_event(evlist, &events, event);
265 perf_evlist__mmap_consume(evlist, i);
266 if (ret < 0)
267 goto out_free_nodes;
268 }
269 }
270
271 events_array = calloc(cnt, sizeof(struct event_node));
272 if (!events_array) {
273 pr_debug("calloc failed\n");
274 ret = -1;
275 goto out_free_nodes;
276 }
277
278 pos = 0;
279 list_for_each_entry(node, &events, list)
280 events_array[pos++] = *node;
281
282 qsort(events_array, cnt, sizeof(struct event_node), compar);
283
284 for (pos = 0; pos < cnt; pos++) {
285 ret = process_event(evlist, events_array[pos].event,
286 switch_tracking);
287 if (ret < 0)
288 goto out_free;
289 }
290
291 ret = 0;
292out_free:
293 pr_debug("%u events recorded\n", cnt);
294 free(events_array);
295out_free_nodes:
296 free_event_nodes(&events);
297 return ret;
298}
299
300/**
301 * test__switch_tracking - test using sched_switch and tracking events.
302 *
303 * This function implements a test that checks that sched_switch events and
304 * tracking events can be recorded for a workload (current process) using the
305 * evsel->system_wide and evsel->tracking flags (respectively) with other events
306 * sometimes enabled or disabled.
307 */
308int test__switch_tracking(void)
309{
310 const char *sched_switch = "sched:sched_switch";
311 struct switch_tracking switch_tracking = { .tids = NULL, };
312 struct record_opts opts = {
313 .mmap_pages = UINT_MAX,
314 .user_freq = UINT_MAX,
315 .user_interval = ULLONG_MAX,
316 .freq = 4000,
317 .target = {
318 .uses_mmap = true,
319 },
320 };
321 struct thread_map *threads = NULL;
322 struct cpu_map *cpus = NULL;
323 struct perf_evlist *evlist = NULL;
324 struct perf_evsel *evsel, *cpu_clocks_evsel, *cycles_evsel;
325 struct perf_evsel *switch_evsel, *tracking_evsel;
326 const char *comm;
327 int err = -1;
328
329 threads = thread_map__new(-1, getpid(), UINT_MAX);
330 if (!threads) {
331 pr_debug("thread_map__new failed!\n");
332 goto out_err;
333 }
334
335 cpus = cpu_map__new(NULL);
336 if (!cpus) {
337 pr_debug("cpu_map__new failed!\n");
338 goto out_err;
339 }
340
341 evlist = perf_evlist__new();
342 if (!evlist) {
343 pr_debug("perf_evlist__new failed!\n");
344 goto out_err;
345 }
346
347 perf_evlist__set_maps(evlist, cpus, threads);
348
349 /* First event */
350 err = parse_events(evlist, "cpu-clock:u");
351 if (err) {
352 pr_debug("Failed to parse event dummy:u\n");
353 goto out_err;
354 }
355
356 cpu_clocks_evsel = perf_evlist__last(evlist);
357
358 /* Second event */
359 err = parse_events(evlist, "cycles:u");
360 if (err) {
361 pr_debug("Failed to parse event cycles:u\n");
362 goto out_err;
363 }
364
365 cycles_evsel = perf_evlist__last(evlist);
366
367 /* Third event */
368 if (!perf_evlist__can_select_event(evlist, sched_switch)) {
369 fprintf(stderr, " (no sched_switch)");
370 err = 0;
371 goto out;
372 }
373
374 err = parse_events(evlist, sched_switch);
375 if (err) {
376 pr_debug("Failed to parse event %s\n", sched_switch);
377 goto out_err;
378 }
379
380 switch_evsel = perf_evlist__last(evlist);
381
382 perf_evsel__set_sample_bit(switch_evsel, CPU);
383 perf_evsel__set_sample_bit(switch_evsel, TIME);
384
385 switch_evsel->system_wide = true;
386 switch_evsel->no_aux_samples = true;
387 switch_evsel->immediate = true;
388
389 /* Test moving an event to the front */
390 if (cycles_evsel == perf_evlist__first(evlist)) {
391 pr_debug("cycles event already at front");
392 goto out_err;
393 }
394 perf_evlist__to_front(evlist, cycles_evsel);
395 if (cycles_evsel != perf_evlist__first(evlist)) {
396 pr_debug("Failed to move cycles event to front");
397 goto out_err;
398 }
399
400 perf_evsel__set_sample_bit(cycles_evsel, CPU);
401 perf_evsel__set_sample_bit(cycles_evsel, TIME);
402
403 /* Fourth event */
404 err = parse_events(evlist, "dummy:u");
405 if (err) {
406 pr_debug("Failed to parse event dummy:u\n");
407 goto out_err;
408 }
409
410 tracking_evsel = perf_evlist__last(evlist);
411
412 perf_evlist__set_tracking_event(evlist, tracking_evsel);
413
414 tracking_evsel->attr.freq = 0;
415 tracking_evsel->attr.sample_period = 1;
416
417 perf_evsel__set_sample_bit(tracking_evsel, TIME);
418
419 /* Config events */
420 perf_evlist__config(evlist, &opts);
421
422 /* Check moved event is still at the front */
423 if (cycles_evsel != perf_evlist__first(evlist)) {
424 pr_debug("Front event no longer at front");
425 goto out_err;
426 }
427
428 /* Check tracking event is tracking */
429 if (!tracking_evsel->attr.mmap || !tracking_evsel->attr.comm) {
430 pr_debug("Tracking event not tracking\n");
431 goto out_err;
432 }
433
434 /* Check non-tracking events are not tracking */
435 evlist__for_each(evlist, evsel) {
436 if (evsel != tracking_evsel) {
437 if (evsel->attr.mmap || evsel->attr.comm) {
438 pr_debug("Non-tracking event is tracking\n");
439 goto out_err;
440 }
441 }
442 }
443
444 if (perf_evlist__open(evlist) < 0) {
445 fprintf(stderr, " (not supported)");
446 err = 0;
447 goto out;
448 }
449
450 err = perf_evlist__mmap(evlist, UINT_MAX, false);
451 if (err) {
452 pr_debug("perf_evlist__mmap failed!\n");
453 goto out_err;
454 }
455
456 perf_evlist__enable(evlist);
457
458 err = perf_evlist__disable_event(evlist, cpu_clocks_evsel);
459 if (err) {
460 pr_debug("perf_evlist__disable_event failed!\n");
461 goto out_err;
462 }
463
464 err = spin_sleep();
465 if (err) {
466 pr_debug("spin_sleep failed!\n");
467 goto out_err;
468 }
469
470 comm = "Test COMM 1";
471 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
472 if (err) {
473 pr_debug("PR_SET_NAME failed!\n");
474 goto out_err;
475 }
476
477 err = perf_evlist__disable_event(evlist, cycles_evsel);
478 if (err) {
479 pr_debug("perf_evlist__disable_event failed!\n");
480 goto out_err;
481 }
482
483 comm = "Test COMM 2";
484 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
485 if (err) {
486 pr_debug("PR_SET_NAME failed!\n");
487 goto out_err;
488 }
489
490 err = spin_sleep();
491 if (err) {
492 pr_debug("spin_sleep failed!\n");
493 goto out_err;
494 }
495
496 comm = "Test COMM 3";
497 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
498 if (err) {
499 pr_debug("PR_SET_NAME failed!\n");
500 goto out_err;
501 }
502
503 err = perf_evlist__enable_event(evlist, cycles_evsel);
504 if (err) {
505 pr_debug("perf_evlist__disable_event failed!\n");
506 goto out_err;
507 }
508
509 comm = "Test COMM 4";
510 err = prctl(PR_SET_NAME, (unsigned long)comm, 0, 0, 0);
511 if (err) {
512 pr_debug("PR_SET_NAME failed!\n");
513 goto out_err;
514 }
515
516 err = spin_sleep();
517 if (err) {
518 pr_debug("spin_sleep failed!\n");
519 goto out_err;
520 }
521
522 perf_evlist__disable(evlist);
523
524 switch_tracking.switch_evsel = switch_evsel;
525 switch_tracking.cycles_evsel = cycles_evsel;
526
527 err = process_events(evlist, &switch_tracking);
528
529 zfree(&switch_tracking.tids);
530
531 if (err)
532 goto out_err;
533
534 /* Check all 4 comm events were seen i.e. that evsel->tracking works */
535 if (!switch_tracking.comm_seen[0] || !switch_tracking.comm_seen[1] ||
536 !switch_tracking.comm_seen[2] || !switch_tracking.comm_seen[3]) {
537 pr_debug("Missing comm events\n");
538 goto out_err;
539 }
540
541 /* Check cycles event got enabled */
542 if (!switch_tracking.cycles_before_comm_1) {
543 pr_debug("Missing cycles events\n");
544 goto out_err;
545 }
546
547 /* Check cycles event got disabled */
548 if (switch_tracking.cycles_between_comm_2_and_comm_3) {
549 pr_debug("cycles events even though event was disabled\n");
550 goto out_err;
551 }
552
553 /* Check cycles event got enabled again */
554 if (!switch_tracking.cycles_after_comm_4) {
555 pr_debug("Missing cycles events\n");
556 goto out_err;
557 }
558out:
559 if (evlist) {
560 perf_evlist__disable(evlist);
561 perf_evlist__delete(evlist);
562 } else {
563 cpu_map__delete(cpus);
564 thread_map__delete(threads);
565 }
566
567 return err;
568
569out_err:
570 err = -1;
571 goto out;
572}
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 5ff3db318f12..3a8fedef83bc 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -42,6 +42,7 @@ int test__task_exit(void)
42 .uses_mmap = true, 42 .uses_mmap = true,
43 }; 43 };
44 const char *argv[] = { "true", NULL }; 44 const char *argv[] = { "true", NULL };
45 char sbuf[STRERR_BUFSIZE];
45 46
46 signal(SIGCHLD, sig_handler); 47 signal(SIGCHLD, sig_handler);
47 48
@@ -82,13 +83,14 @@ int test__task_exit(void)
82 83
83 err = perf_evlist__open(evlist); 84 err = perf_evlist__open(evlist);
84 if (err < 0) { 85 if (err < 0) {
85 pr_debug("Couldn't open the evlist: %s\n", strerror(-err)); 86 pr_debug("Couldn't open the evlist: %s\n",
87 strerror_r(-err, sbuf, sizeof(sbuf)));
86 goto out_delete_evlist; 88 goto out_delete_evlist;
87 } 89 }
88 90
89 if (perf_evlist__mmap(evlist, 128, true) < 0) { 91 if (perf_evlist__mmap(evlist, 128, true) < 0) {
90 pr_debug("failed to mmap events: %d (%s)\n", errno, 92 pr_debug("failed to mmap events: %d (%s)\n", errno,
91 strerror(errno)); 93 strerror_r(errno, sbuf, sizeof(sbuf)));
92 goto out_delete_evlist; 94 goto out_delete_evlist;
93 } 95 }
94 96
@@ -103,7 +105,7 @@ retry:
103 } 105 }
104 106
105 if (!exited || !nr_exit) { 107 if (!exited || !nr_exit) {
106 poll(evlist->pollfd, evlist->nr_fds, -1); 108 perf_evlist__poll(evlist, -1);
107 goto retry; 109 goto retry;
108 } 110 }
109 111
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index ed64790a395f..00e776a87a9c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -48,6 +48,9 @@ int test__mmap_thread_lookup(void);
48int test__thread_mg_share(void); 48int test__thread_mg_share(void);
49int test__hists_output(void); 49int test__hists_output(void);
50int test__hists_cumulate(void); 50int test__hists_cumulate(void);
51int test__switch_tracking(void);
52int test__fdarray__filter(void);
53int test__fdarray__add(void);
51 54
52#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 55#if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
53#ifdef HAVE_DWARF_UNWIND_SUPPORT 56#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index f0697a3aede0..1e0a2fd80115 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -27,6 +27,7 @@ static struct annotate_browser_opt {
27 bool hide_src_code, 27 bool hide_src_code,
28 use_offset, 28 use_offset,
29 jump_arrows, 29 jump_arrows,
30 show_linenr,
30 show_nr_jumps; 31 show_nr_jumps;
31} annotate_browser__opts = { 32} annotate_browser__opts = {
32 .use_offset = true, 33 .use_offset = true,
@@ -128,7 +129,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
128 if (!*dl->line) 129 if (!*dl->line)
129 slsmg_write_nstring(" ", width - pcnt_width); 130 slsmg_write_nstring(" ", width - pcnt_width);
130 else if (dl->offset == -1) { 131 else if (dl->offset == -1) {
131 printed = scnprintf(bf, sizeof(bf), "%*s ", 132 if (dl->line_nr && annotate_browser__opts.show_linenr)
133 printed = scnprintf(bf, sizeof(bf), "%-*d ",
134 ab->addr_width + 1, dl->line_nr);
135 else
136 printed = scnprintf(bf, sizeof(bf), "%*s ",
132 ab->addr_width, " "); 137 ab->addr_width, " ");
133 slsmg_write_nstring(bf, printed); 138 slsmg_write_nstring(bf, printed);
134 slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1); 139 slsmg_write_nstring(dl->line, width - printed - pcnt_width + 1);
@@ -733,6 +738,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
733 "o Toggle disassembler output/simplified view\n" 738 "o Toggle disassembler output/simplified view\n"
734 "s Toggle source code view\n" 739 "s Toggle source code view\n"
735 "/ Search string\n" 740 "/ Search string\n"
741 "k Toggle line numbers\n"
736 "r Run available scripts\n" 742 "r Run available scripts\n"
737 "? Search string backwards\n"); 743 "? Search string backwards\n");
738 continue; 744 continue;
@@ -741,6 +747,10 @@ static int annotate_browser__run(struct annotate_browser *browser,
741 script_browse(NULL); 747 script_browse(NULL);
742 continue; 748 continue;
743 } 749 }
750 case 'k':
751 annotate_browser__opts.show_linenr =
752 !annotate_browser__opts.show_linenr;
753 break;
744 case 'H': 754 case 'H':
745 nd = browser->curr_hot; 755 nd = browser->curr_hot;
746 break; 756 break;
@@ -984,6 +994,7 @@ static struct annotate_config {
984} annotate__configs[] = { 994} annotate__configs[] = {
985 ANNOTATE_CFG(hide_src_code), 995 ANNOTATE_CFG(hide_src_code),
986 ANNOTATE_CFG(jump_arrows), 996 ANNOTATE_CFG(jump_arrows),
997 ANNOTATE_CFG(show_linenr),
987 ANNOTATE_CFG(show_nr_jumps), 998 ANNOTATE_CFG(show_nr_jumps),
988 ANNOTATE_CFG(use_offset), 999 ANNOTATE_CFG(use_offset),
989}; 1000};
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index 89c16b988618..e8278c558d4a 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -1,6 +1,7 @@
1#include "util/cache.h" 1#include "util/cache.h"
2#include "util/debug.h" 2#include "util/debug.h"
3#include "ui/browser.h" 3#include "ui/browser.h"
4#include "ui/keysyms.h"
4#include "ui/ui.h" 5#include "ui/ui.h"
5#include "ui/util.h" 6#include "ui/util.h"
6#include "ui/libslang.h" 7#include "ui/libslang.h"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index a94b11fc5e00..788506eef567 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -10,6 +10,7 @@
10#include "../../util/pstack.h" 10#include "../../util/pstack.h"
11#include "../../util/sort.h" 11#include "../../util/sort.h"
12#include "../../util/util.h" 12#include "../../util/util.h"
13#include "../../util/top.h"
13#include "../../arch/common.h" 14#include "../../arch/common.h"
14 15
15#include "../browser.h" 16#include "../browser.h"
@@ -34,7 +35,9 @@ struct hist_browser {
34 35
35extern void hist_browser__init_hpp(void); 36extern void hist_browser__init_hpp(void);
36 37
37static int hists__browser_title(struct hists *hists, char *bf, size_t size); 38static int hists__browser_title(struct hists *hists,
39 struct hist_browser_timer *hbt,
40 char *bf, size_t size);
38static void hist_browser__update_nr_entries(struct hist_browser *hb); 41static void hist_browser__update_nr_entries(struct hist_browser *hb);
39 42
40static struct rb_node *hists__filter_entries(struct rb_node *nd, 43static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -224,23 +227,30 @@ static void callchain_node__init_have_children_rb_tree(struct callchain_node *no
224 } 227 }
225} 228}
226 229
227static void callchain_node__init_have_children(struct callchain_node *node) 230static void callchain_node__init_have_children(struct callchain_node *node,
231 bool has_sibling)
228{ 232{
229 struct callchain_list *chain; 233 struct callchain_list *chain;
230 234
231 list_for_each_entry(chain, &node->val, list) 235 chain = list_entry(node->val.next, struct callchain_list, list);
236 chain->ms.has_children = has_sibling;
237
238 if (!list_empty(&node->val)) {
239 chain = list_entry(node->val.prev, struct callchain_list, list);
232 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root); 240 chain->ms.has_children = !RB_EMPTY_ROOT(&node->rb_root);
241 }
233 242
234 callchain_node__init_have_children_rb_tree(node); 243 callchain_node__init_have_children_rb_tree(node);
235} 244}
236 245
237static void callchain__init_have_children(struct rb_root *root) 246static void callchain__init_have_children(struct rb_root *root)
238{ 247{
239 struct rb_node *nd; 248 struct rb_node *nd = rb_first(root);
249 bool has_sibling = nd && rb_next(nd);
240 250
241 for (nd = rb_first(root); nd; nd = rb_next(nd)) { 251 for (nd = rb_first(root); nd; nd = rb_next(nd)) {
242 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node); 252 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
243 callchain_node__init_have_children(node); 253 callchain_node__init_have_children(node, has_sibling);
244 } 254 }
245} 255}
246 256
@@ -387,7 +397,7 @@ static int hist_browser__run(struct hist_browser *browser,
387 browser->b.entries = &browser->hists->entries; 397 browser->b.entries = &browser->hists->entries;
388 browser->b.nr_entries = hist_browser__nr_entries(browser); 398 browser->b.nr_entries = hist_browser__nr_entries(browser);
389 399
390 hists__browser_title(browser->hists, title, sizeof(title)); 400 hists__browser_title(browser->hists, hbt, title, sizeof(title));
391 401
392 if (ui_browser__show(&browser->b, title, 402 if (ui_browser__show(&browser->b, title,
393 "Press '?' for help on key bindings") < 0) 403 "Press '?' for help on key bindings") < 0)
@@ -414,7 +424,8 @@ static int hist_browser__run(struct hist_browser *browser,
414 ui_browser__warn_lost_events(&browser->b); 424 ui_browser__warn_lost_events(&browser->b);
415 } 425 }
416 426
417 hists__browser_title(browser->hists, title, sizeof(title)); 427 hists__browser_title(browser->hists,
428 hbt, title, sizeof(title));
418 ui_browser__show_title(&browser->b, title); 429 ui_browser__show_title(&browser->b, title);
419 continue; 430 continue;
420 } 431 }
@@ -457,43 +468,90 @@ out:
457 return key; 468 return key;
458} 469}
459 470
460static char *callchain_list__sym_name(struct callchain_list *cl, 471struct callchain_print_arg {
461 char *bf, size_t bfsize, bool show_dso) 472 /* for hists browser */
473 off_t row_offset;
474 bool is_current_entry;
475
476 /* for file dump */
477 FILE *fp;
478 int printed;
479};
480
481typedef void (*print_callchain_entry_fn)(struct hist_browser *browser,
482 struct callchain_list *chain,
483 const char *str, int offset,
484 unsigned short row,
485 struct callchain_print_arg *arg);
486
487static void hist_browser__show_callchain_entry(struct hist_browser *browser,
488 struct callchain_list *chain,
489 const char *str, int offset,
490 unsigned short row,
491 struct callchain_print_arg *arg)
492{
493 int color, width;
494 char folded_sign = callchain_list__folded(chain);
495
496 color = HE_COLORSET_NORMAL;
497 width = browser->b.width - (offset + 2);
498 if (ui_browser__is_current_entry(&browser->b, row)) {
499 browser->selection = &chain->ms;
500 color = HE_COLORSET_SELECTED;
501 arg->is_current_entry = true;
502 }
503
504 ui_browser__set_color(&browser->b, color);
505 hist_browser__gotorc(browser, row, 0);
506 slsmg_write_nstring(" ", offset);
507 slsmg_printf("%c ", folded_sign);
508 slsmg_write_nstring(str, width);
509}
510
511static void hist_browser__fprintf_callchain_entry(struct hist_browser *b __maybe_unused,
512 struct callchain_list *chain,
513 const char *str, int offset,
514 unsigned short row __maybe_unused,
515 struct callchain_print_arg *arg)
462{ 516{
463 int printed; 517 char folded_sign = callchain_list__folded(chain);
464 518
465 if (cl->ms.sym) 519 arg->printed += fprintf(arg->fp, "%*s%c %s\n", offset, " ",
466 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name); 520 folded_sign, str);
467 else 521}
468 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip); 522
523typedef bool (*check_output_full_fn)(struct hist_browser *browser,
524 unsigned short row);
469 525
470 if (show_dso) 526static bool hist_browser__check_output_full(struct hist_browser *browser,
471 scnprintf(bf + printed, bfsize - printed, " %s", 527 unsigned short row)
472 cl->ms.map ? cl->ms.map->dso->short_name : "unknown"); 528{
529 return browser->b.rows == row;
530}
473 531
474 return bf; 532static bool hist_browser__check_dump_full(struct hist_browser *browser __maybe_unused,
533 unsigned short row __maybe_unused)
534{
535 return false;
475} 536}
476 537
477#define LEVEL_OFFSET_STEP 3 538#define LEVEL_OFFSET_STEP 3
478 539
479static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browser, 540static int hist_browser__show_callchain(struct hist_browser *browser,
480 struct callchain_node *chain_node, 541 struct rb_root *root, int level,
481 u64 total, int level, 542 unsigned short row, u64 total,
482 unsigned short row, 543 print_callchain_entry_fn print,
483 off_t *row_offset, 544 struct callchain_print_arg *arg,
484 bool *is_current_entry) 545 check_output_full_fn is_output_full)
485{ 546{
486 struct rb_node *node; 547 struct rb_node *node;
487 int first_row = row, width, offset = level * LEVEL_OFFSET_STEP; 548 int first_row = row, offset = level * LEVEL_OFFSET_STEP;
488 u64 new_total, remaining; 549 u64 new_total;
550 bool need_percent;
489 551
490 if (callchain_param.mode == CHAIN_GRAPH_REL) 552 node = rb_first(root);
491 new_total = chain_node->children_hit; 553 need_percent = node && rb_next(node);
492 else
493 new_total = total;
494 554
495 remaining = new_total;
496 node = rb_first(&chain_node->rb_root);
497 while (node) { 555 while (node) {
498 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node); 556 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
499 struct rb_node *next = rb_next(node); 557 struct rb_node *next = rb_next(node);
@@ -503,30 +561,28 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
503 int first = true; 561 int first = true;
504 int extra_offset = 0; 562 int extra_offset = 0;
505 563
506 remaining -= cumul;
507
508 list_for_each_entry(chain, &child->val, list) { 564 list_for_each_entry(chain, &child->val, list) {
509 char bf[1024], *alloc_str; 565 char bf[1024], *alloc_str;
510 const char *str; 566 const char *str;
511 int color;
512 bool was_first = first; 567 bool was_first = first;
513 568
514 if (first) 569 if (first)
515 first = false; 570 first = false;
516 else 571 else if (need_percent)
517 extra_offset = LEVEL_OFFSET_STEP; 572 extra_offset = LEVEL_OFFSET_STEP;
518 573
519 folded_sign = callchain_list__folded(chain); 574 folded_sign = callchain_list__folded(chain);
520 if (*row_offset != 0) { 575 if (arg->row_offset != 0) {
521 --*row_offset; 576 arg->row_offset--;
522 goto do_next; 577 goto do_next;
523 } 578 }
524 579
525 alloc_str = NULL; 580 alloc_str = NULL;
526 str = callchain_list__sym_name(chain, bf, sizeof(bf), 581 str = callchain_list__sym_name(chain, bf, sizeof(bf),
527 browser->show_dso); 582 browser->show_dso);
528 if (was_first) { 583
529 double percent = cumul * 100.0 / new_total; 584 if (was_first && need_percent) {
585 double percent = cumul * 100.0 / total;
530 586
531 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0) 587 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
532 str = "Not enough memory!"; 588 str = "Not enough memory!";
@@ -534,22 +590,11 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *browse
534 str = alloc_str; 590 str = alloc_str;
535 } 591 }
536 592
537 color = HE_COLORSET_NORMAL; 593 print(browser, chain, str, offset + extra_offset, row, arg);
538 width = browser->b.width - (offset + extra_offset + 2);
539 if (ui_browser__is_current_entry(&browser->b, row)) {
540 browser->selection = &chain->ms;
541 color = HE_COLORSET_SELECTED;
542 *is_current_entry = true;
543 }
544 594
545 ui_browser__set_color(&browser->b, color);
546 hist_browser__gotorc(browser, row, 0);
547 slsmg_write_nstring(" ", offset + extra_offset);
548 slsmg_printf("%c ", folded_sign);
549 slsmg_write_nstring(str, width);
550 free(alloc_str); 595 free(alloc_str);
551 596
552 if (++row == browser->b.rows) 597 if (is_output_full(browser, ++row))
553 goto out; 598 goto out;
554do_next: 599do_next:
555 if (folded_sign == '+') 600 if (folded_sign == '+')
@@ -558,89 +603,21 @@ do_next:
558 603
559 if (folded_sign == '-') { 604 if (folded_sign == '-') {
560 const int new_level = level + (extra_offset ? 2 : 1); 605 const int new_level = level + (extra_offset ? 2 : 1);
561 row += hist_browser__show_callchain_node_rb_tree(browser, child, new_total,
562 new_level, row, row_offset,
563 is_current_entry);
564 }
565 if (row == browser->b.rows)
566 goto out;
567 node = next;
568 }
569out:
570 return row - first_row;
571}
572 606
573static int hist_browser__show_callchain_node(struct hist_browser *browser, 607 if (callchain_param.mode == CHAIN_GRAPH_REL)
574 struct callchain_node *node, 608 new_total = child->children_hit;
575 int level, unsigned short row, 609 else
576 off_t *row_offset, 610 new_total = total;
577 bool *is_current_entry)
578{
579 struct callchain_list *chain;
580 int first_row = row,
581 offset = level * LEVEL_OFFSET_STEP,
582 width = browser->b.width - offset;
583 char folded_sign = ' ';
584
585 list_for_each_entry(chain, &node->val, list) {
586 char bf[1024], *s;
587 int color;
588
589 folded_sign = callchain_list__folded(chain);
590
591 if (*row_offset != 0) {
592 --*row_offset;
593 continue;
594 }
595 611
596 color = HE_COLORSET_NORMAL; 612 row += hist_browser__show_callchain(browser, &child->rb_root,
597 if (ui_browser__is_current_entry(&browser->b, row)) { 613 new_level, row, new_total,
598 browser->selection = &chain->ms; 614 print, arg, is_output_full);
599 color = HE_COLORSET_SELECTED;
600 *is_current_entry = true;
601 } 615 }
602 616 if (is_output_full(browser, row))
603 s = callchain_list__sym_name(chain, bf, sizeof(bf),
604 browser->show_dso);
605 hist_browser__gotorc(browser, row, 0);
606 ui_browser__set_color(&browser->b, color);
607 slsmg_write_nstring(" ", offset);
608 slsmg_printf("%c ", folded_sign);
609 slsmg_write_nstring(s, width - 2);
610
611 if (++row == browser->b.rows)
612 goto out;
613 }
614
615 if (folded_sign == '-')
616 row += hist_browser__show_callchain_node_rb_tree(browser, node,
617 browser->hists->stats.total_period,
618 level + 1, row,
619 row_offset,
620 is_current_entry);
621out:
622 return row - first_row;
623}
624
625static int hist_browser__show_callchain(struct hist_browser *browser,
626 struct rb_root *chain,
627 int level, unsigned short row,
628 off_t *row_offset,
629 bool *is_current_entry)
630{
631 struct rb_node *nd;
632 int first_row = row;
633
634 for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
635 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
636
637 row += hist_browser__show_callchain_node(browser, node, level,
638 row, row_offset,
639 is_current_entry);
640 if (row == browser->b.rows)
641 break; 617 break;
618 node = next;
642 } 619 }
643 620out:
644 return row - first_row; 621 return row - first_row;
645} 622}
646 623
@@ -653,17 +630,18 @@ struct hpp_arg {
653static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) 630static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
654{ 631{
655 struct hpp_arg *arg = hpp->ptr; 632 struct hpp_arg *arg = hpp->ptr;
656 int ret; 633 int ret, len;
657 va_list args; 634 va_list args;
658 double percent; 635 double percent;
659 636
660 va_start(args, fmt); 637 va_start(args, fmt);
638 len = va_arg(args, int);
661 percent = va_arg(args, double); 639 percent = va_arg(args, double);
662 va_end(args); 640 va_end(args);
663 641
664 ui_browser__set_percent_color(arg->b, percent, arg->current_entry); 642 ui_browser__set_percent_color(arg->b, percent, arg->current_entry);
665 643
666 ret = scnprintf(hpp->buf, hpp->size, fmt, percent); 644 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
667 slsmg_printf("%s", hpp->buf); 645 slsmg_printf("%s", hpp->buf);
668 646
669 advance_hpp(hpp, ret); 647 advance_hpp(hpp, ret);
@@ -677,12 +655,12 @@ static u64 __hpp_get_##_field(struct hist_entry *he) \
677} \ 655} \
678 \ 656 \
679static int \ 657static int \
680hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 658hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
681 struct perf_hpp *hpp, \ 659 struct perf_hpp *hpp, \
682 struct hist_entry *he) \ 660 struct hist_entry *he) \
683{ \ 661{ \
684 return __hpp__fmt(hpp, he, __hpp_get_##_field, " %6.2f%%", \ 662 return hpp__fmt(fmt, hpp, he, __hpp_get_##_field, " %*.2f%%", \
685 __hpp__slsmg_color_printf, true); \ 663 __hpp__slsmg_color_printf, true); \
686} 664}
687 665
688#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 666#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -692,18 +670,20 @@ static u64 __hpp_get_acc_##_field(struct hist_entry *he) \
692} \ 670} \
693 \ 671 \
694static int \ 672static int \
695hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,\ 673hist_browser__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
696 struct perf_hpp *hpp, \ 674 struct perf_hpp *hpp, \
697 struct hist_entry *he) \ 675 struct hist_entry *he) \
698{ \ 676{ \
699 if (!symbol_conf.cumulate_callchain) { \ 677 if (!symbol_conf.cumulate_callchain) { \
700 int ret = scnprintf(hpp->buf, hpp->size, "%8s", "N/A"); \ 678 int len = fmt->user_len ?: fmt->len; \
679 int ret = scnprintf(hpp->buf, hpp->size, \
680 "%*s", len, "N/A"); \
701 slsmg_printf("%s", hpp->buf); \ 681 slsmg_printf("%s", hpp->buf); \
702 \ 682 \
703 return ret; \ 683 return ret; \
704 } \ 684 } \
705 return __hpp__fmt(hpp, he, __hpp_get_acc_##_field, " %6.2f%%", \ 685 return hpp__fmt(fmt, hpp, he, __hpp_get_acc_##_field, \
706 __hpp__slsmg_color_printf, true); \ 686 " %*.2f%%", __hpp__slsmg_color_printf, true); \
707} 687}
708 688
709__HPP_COLOR_PERCENT_FN(overhead, period) 689__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -812,10 +792,25 @@ static int hist_browser__show_entry(struct hist_browser *browser,
812 --row_offset; 792 --row_offset;
813 793
814 if (folded_sign == '-' && row != browser->b.rows) { 794 if (folded_sign == '-' && row != browser->b.rows) {
815 printed += hist_browser__show_callchain(browser, &entry->sorted_chain, 795 u64 total = hists__total_period(entry->hists);
816 1, row, &row_offset, 796 struct callchain_print_arg arg = {
817 &current_entry); 797 .row_offset = row_offset,
818 if (current_entry) 798 .is_current_entry = current_entry,
799 };
800
801 if (callchain_param.mode == CHAIN_GRAPH_REL) {
802 if (symbol_conf.cumulate_callchain)
803 total = entry->stat_acc->period;
804 else
805 total = entry->stat.period;
806 }
807
808 printed += hist_browser__show_callchain(browser,
809 &entry->sorted_chain, 1, row, total,
810 hist_browser__show_callchain_entry, &arg,
811 hist_browser__check_output_full);
812
813 if (arg.is_current_entry)
819 browser->he_selection = entry; 814 browser->he_selection = entry;
820 } 815 }
821 816
@@ -847,9 +842,6 @@ static int hists__scnprintf_headers(char *buf, size_t size, struct hists *hists)
847 if (perf_hpp__should_skip(fmt)) 842 if (perf_hpp__should_skip(fmt))
848 continue; 843 continue;
849 844
850 /* We need to add the length of the columns header. */
851 perf_hpp__reset_width(fmt, hists);
852
853 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 845 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
854 if (advance_hpp_check(&dummy_hpp, ret)) 846 if (advance_hpp_check(&dummy_hpp, ret))
855 break; 847 break;
@@ -1074,113 +1066,21 @@ do_offset:
1074 } 1066 }
1075} 1067}
1076 1068
1077static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
1078 struct callchain_node *chain_node,
1079 u64 total, int level,
1080 FILE *fp)
1081{
1082 struct rb_node *node;
1083 int offset = level * LEVEL_OFFSET_STEP;
1084 u64 new_total, remaining;
1085 int printed = 0;
1086
1087 if (callchain_param.mode == CHAIN_GRAPH_REL)
1088 new_total = chain_node->children_hit;
1089 else
1090 new_total = total;
1091
1092 remaining = new_total;
1093 node = rb_first(&chain_node->rb_root);
1094 while (node) {
1095 struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
1096 struct rb_node *next = rb_next(node);
1097 u64 cumul = callchain_cumul_hits(child);
1098 struct callchain_list *chain;
1099 char folded_sign = ' ';
1100 int first = true;
1101 int extra_offset = 0;
1102
1103 remaining -= cumul;
1104
1105 list_for_each_entry(chain, &child->val, list) {
1106 char bf[1024], *alloc_str;
1107 const char *str;
1108 bool was_first = first;
1109
1110 if (first)
1111 first = false;
1112 else
1113 extra_offset = LEVEL_OFFSET_STEP;
1114
1115 folded_sign = callchain_list__folded(chain);
1116
1117 alloc_str = NULL;
1118 str = callchain_list__sym_name(chain, bf, sizeof(bf),
1119 browser->show_dso);
1120 if (was_first) {
1121 double percent = cumul * 100.0 / new_total;
1122
1123 if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
1124 str = "Not enough memory!";
1125 else
1126 str = alloc_str;
1127 }
1128
1129 printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
1130 free(alloc_str);
1131 if (folded_sign == '+')
1132 break;
1133 }
1134
1135 if (folded_sign == '-') {
1136 const int new_level = level + (extra_offset ? 2 : 1);
1137 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
1138 new_level, fp);
1139 }
1140
1141 node = next;
1142 }
1143
1144 return printed;
1145}
1146
1147static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
1148 struct callchain_node *node,
1149 int level, FILE *fp)
1150{
1151 struct callchain_list *chain;
1152 int offset = level * LEVEL_OFFSET_STEP;
1153 char folded_sign = ' ';
1154 int printed = 0;
1155
1156 list_for_each_entry(chain, &node->val, list) {
1157 char bf[1024], *s;
1158
1159 folded_sign = callchain_list__folded(chain);
1160 s = callchain_list__sym_name(chain, bf, sizeof(bf), browser->show_dso);
1161 printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
1162 }
1163
1164 if (folded_sign == '-')
1165 printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
1166 browser->hists->stats.total_period,
1167 level + 1, fp);
1168 return printed;
1169}
1170
1171static int hist_browser__fprintf_callchain(struct hist_browser *browser, 1069static int hist_browser__fprintf_callchain(struct hist_browser *browser,
1172 struct rb_root *chain, int level, FILE *fp) 1070 struct hist_entry *he, FILE *fp)
1173{ 1071{
1174 struct rb_node *nd; 1072 u64 total = hists__total_period(he->hists);
1175 int printed = 0; 1073 struct callchain_print_arg arg = {
1176 1074 .fp = fp,
1177 for (nd = rb_first(chain); nd; nd = rb_next(nd)) { 1075 };
1178 struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
1179 1076
1180 printed += hist_browser__fprintf_callchain_node(browser, node, level, fp); 1077 if (symbol_conf.cumulate_callchain)
1181 } 1078 total = he->stat_acc->period;
1182 1079
1183 return printed; 1080 hist_browser__show_callchain(browser, &he->sorted_chain, 1, 0, total,
1081 hist_browser__fprintf_callchain_entry, &arg,
1082 hist_browser__check_dump_full);
1083 return arg.printed;
1184} 1084}
1185 1085
1186static int hist_browser__fprintf_entry(struct hist_browser *browser, 1086static int hist_browser__fprintf_entry(struct hist_browser *browser,
@@ -1219,7 +1119,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1219 printed += fprintf(fp, "%s\n", rtrim(s)); 1119 printed += fprintf(fp, "%s\n", rtrim(s));
1220 1120
1221 if (folded_sign == '-') 1121 if (folded_sign == '-')
1222 printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp); 1122 printed += hist_browser__fprintf_callchain(browser, he, fp);
1223 1123
1224 return printed; 1124 return printed;
1225} 1125}
@@ -1305,7 +1205,15 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
1305 return browser->he_selection->thread; 1205 return browser->he_selection->thread;
1306} 1206}
1307 1207
1308static int hists__browser_title(struct hists *hists, char *bf, size_t size) 1208/* Check whether the browser is for 'top' or 'report' */
1209static inline bool is_report_browser(void *timer)
1210{
1211 return timer == NULL;
1212}
1213
1214static int hists__browser_title(struct hists *hists,
1215 struct hist_browser_timer *hbt,
1216 char *bf, size_t size)
1309{ 1217{
1310 char unit; 1218 char unit;
1311 int printed; 1219 int printed;
@@ -1330,19 +1238,21 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
1330 ev_name = buf; 1238 ev_name = buf;
1331 1239
1332 for_each_group_member(pos, evsel) { 1240 for_each_group_member(pos, evsel) {
1241 struct hists *pos_hists = evsel__hists(pos);
1242
1333 if (symbol_conf.filter_relative) { 1243 if (symbol_conf.filter_relative) {
1334 nr_samples += pos->hists.stats.nr_non_filtered_samples; 1244 nr_samples += pos_hists->stats.nr_non_filtered_samples;
1335 nr_events += pos->hists.stats.total_non_filtered_period; 1245 nr_events += pos_hists->stats.total_non_filtered_period;
1336 } else { 1246 } else {
1337 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1247 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
1338 nr_events += pos->hists.stats.total_period; 1248 nr_events += pos_hists->stats.total_period;
1339 } 1249 }
1340 } 1250 }
1341 } 1251 }
1342 1252
1343 nr_samples = convert_unit(nr_samples, &unit); 1253 nr_samples = convert_unit(nr_samples, &unit);
1344 printed = scnprintf(bf, size, 1254 printed = scnprintf(bf, size,
1345 "Samples: %lu%c of event '%s', Event count (approx.): %lu", 1255 "Samples: %lu%c of event '%s', Event count (approx.): %" PRIu64,
1346 nr_samples, unit, ev_name, nr_events); 1256 nr_samples, unit, ev_name, nr_events);
1347 1257
1348 1258
@@ -1357,6 +1267,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
1357 if (dso) 1267 if (dso)
1358 printed += scnprintf(bf + printed, size - printed, 1268 printed += scnprintf(bf + printed, size - printed,
1359 ", DSO: %s", dso->short_name); 1269 ", DSO: %s", dso->short_name);
1270 if (!is_report_browser(hbt)) {
1271 struct perf_top *top = hbt->arg;
1272
1273 if (top->zero)
1274 printed += scnprintf(bf + printed, size - printed, " [z]");
1275 }
1276
1360 return printed; 1277 return printed;
1361} 1278}
1362 1279
@@ -1368,12 +1285,6 @@ static inline void free_popup_options(char **options, int n)
1368 zfree(&options[i]); 1285 zfree(&options[i]);
1369} 1286}
1370 1287
1371/* Check whether the browser is for 'top' or 'report' */
1372static inline bool is_report_browser(void *timer)
1373{
1374 return timer == NULL;
1375}
1376
1377/* 1288/*
1378 * Only runtime switching of perf data file will make "input_name" point 1289 * Only runtime switching of perf data file will make "input_name" point
1379 * to a malloced buffer. So add "is_input_name_malloced" flag to decide 1290 * to a malloced buffer. So add "is_input_name_malloced" flag to decide
@@ -1488,7 +1399,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1488 float min_pcnt, 1399 float min_pcnt,
1489 struct perf_session_env *env) 1400 struct perf_session_env *env)
1490{ 1401{
1491 struct hists *hists = &evsel->hists; 1402 struct hists *hists = evsel__hists(evsel);
1492 struct hist_browser *browser = hist_browser__new(hists); 1403 struct hist_browser *browser = hist_browser__new(hists);
1493 struct branch_info *bi; 1404 struct branch_info *bi;
1494 struct pstack *fstack; 1405 struct pstack *fstack;
@@ -1498,6 +1409,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1498 char buf[64]; 1409 char buf[64];
1499 char script_opt[64]; 1410 char script_opt[64];
1500 int delay_secs = hbt ? hbt->refresh : 0; 1411 int delay_secs = hbt ? hbt->refresh : 0;
1412 struct perf_hpp_fmt *fmt;
1501 1413
1502#define HIST_BROWSER_HELP_COMMON \ 1414#define HIST_BROWSER_HELP_COMMON \
1503 "h/?/F1 Show this window\n" \ 1415 "h/?/F1 Show this window\n" \
@@ -1529,6 +1441,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1529 "P Print histograms to perf.hist.N\n" 1441 "P Print histograms to perf.hist.N\n"
1530 "t Zoom into current Thread\n" 1442 "t Zoom into current Thread\n"
1531 "V Verbose (DSO names in callchains, etc)\n" 1443 "V Verbose (DSO names in callchains, etc)\n"
1444 "z Toggle zeroing of samples\n"
1532 "/ Filter symbol by name"; 1445 "/ Filter symbol by name";
1533 1446
1534 if (browser == NULL) 1447 if (browser == NULL)
@@ -1547,6 +1460,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1547 1460
1548 memset(options, 0, sizeof(options)); 1461 memset(options, 0, sizeof(options));
1549 1462
1463 perf_hpp__for_each_format(fmt)
1464 perf_hpp__reset_width(fmt, hists);
1465
1466 if (symbol_conf.col_width_list_str)
1467 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
1468
1550 while (1) { 1469 while (1) {
1551 const struct thread *thread = NULL; 1470 const struct thread *thread = NULL;
1552 const struct dso *dso = NULL; 1471 const struct dso *dso = NULL;
@@ -1623,6 +1542,13 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1623 case 'F': 1542 case 'F':
1624 symbol_conf.filter_relative ^= 1; 1543 symbol_conf.filter_relative ^= 1;
1625 continue; 1544 continue;
1545 case 'z':
1546 if (!is_report_browser(hbt)) {
1547 struct perf_top *top = hbt->arg;
1548
1549 top->zero = !top->zero;
1550 }
1551 continue;
1626 case K_F1: 1552 case K_F1:
1627 case 'h': 1553 case 'h':
1628 case '?': 1554 case '?':
@@ -1888,8 +1814,9 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1888 struct perf_evsel_menu *menu = container_of(browser, 1814 struct perf_evsel_menu *menu = container_of(browser,
1889 struct perf_evsel_menu, b); 1815 struct perf_evsel_menu, b);
1890 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1816 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1817 struct hists *hists = evsel__hists(evsel);
1891 bool current_entry = ui_browser__is_current_entry(browser, row); 1818 bool current_entry = ui_browser__is_current_entry(browser, row);
1892 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1819 unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
1893 const char *ev_name = perf_evsel__name(evsel); 1820 const char *ev_name = perf_evsel__name(evsel);
1894 char bf[256], unit; 1821 char bf[256], unit;
1895 const char *warn = " "; 1822 const char *warn = " ";
@@ -1904,7 +1831,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1904 ev_name = perf_evsel__group_name(evsel); 1831 ev_name = perf_evsel__group_name(evsel);
1905 1832
1906 for_each_group_member(pos, evsel) { 1833 for_each_group_member(pos, evsel) {
1907 nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1834 struct hists *pos_hists = evsel__hists(pos);
1835 nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
1908 } 1836 }
1909 } 1837 }
1910 1838
@@ -1913,7 +1841,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1913 unit, unit == ' ' ? "" : " ", ev_name); 1841 unit, unit == ' ' ? "" : " ", ev_name);
1914 slsmg_printf("%s", bf); 1842 slsmg_printf("%s", bf);
1915 1843
1916 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 1844 nr_events = hists->stats.nr_events[PERF_RECORD_LOST];
1917 if (nr_events != 0) { 1845 if (nr_events != 0) {
1918 menu->lost_events = true; 1846 menu->lost_events = true;
1919 if (!current_entry) 1847 if (!current_entry)
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 6ca60e482cdc..4b3585eed1e8 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -11,6 +11,7 @@
11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...) 11static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
12{ 12{
13 int ret = 0; 13 int ret = 0;
14 int len;
14 va_list args; 15 va_list args;
15 double percent; 16 double percent;
16 const char *markup; 17 const char *markup;
@@ -18,6 +19,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
18 size_t size = hpp->size; 19 size_t size = hpp->size;
19 20
20 va_start(args, fmt); 21 va_start(args, fmt);
22 len = va_arg(args, int);
21 percent = va_arg(args, double); 23 percent = va_arg(args, double);
22 va_end(args); 24 va_end(args);
23 25
@@ -25,7 +27,7 @@ static int __percent_color_snprintf(struct perf_hpp *hpp, const char *fmt, ...)
25 if (markup) 27 if (markup)
26 ret += scnprintf(buf, size, markup); 28 ret += scnprintf(buf, size, markup);
27 29
28 ret += scnprintf(buf + ret, size - ret, fmt, percent); 30 ret += scnprintf(buf + ret, size - ret, fmt, len, percent);
29 31
30 if (markup) 32 if (markup)
31 ret += scnprintf(buf + ret, size - ret, "</span>"); 33 ret += scnprintf(buf + ret, size - ret, "</span>");
@@ -39,12 +41,12 @@ static u64 he_get_##_field(struct hist_entry *he) \
39 return he->stat._field; \ 41 return he->stat._field; \
40} \ 42} \
41 \ 43 \
42static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 44static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt, \
43 struct perf_hpp *hpp, \ 45 struct perf_hpp *hpp, \
44 struct hist_entry *he) \ 46 struct hist_entry *he) \
45{ \ 47{ \
46 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 48 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
47 __percent_color_snprintf, true); \ 49 __percent_color_snprintf, true); \
48} 50}
49 51
50#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 52#define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
@@ -57,8 +59,8 @@ static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused,
57 struct perf_hpp *hpp, \ 59 struct perf_hpp *hpp, \
58 struct hist_entry *he) \ 60 struct hist_entry *he) \
59{ \ 61{ \
60 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 62 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
61 __percent_color_snprintf, true); \ 63 __percent_color_snprintf, true); \
62} 64}
63 65
64__HPP_COLOR_PERCENT_FN(overhead, period) 66__HPP_COLOR_PERCENT_FN(overhead, period)
@@ -87,15 +89,6 @@ void perf_gtk__init_hpp(void)
87 perf_gtk__hpp_color_overhead_acc; 89 perf_gtk__hpp_color_overhead_acc;
88} 90}
89 91
90static void callchain_list__sym_name(struct callchain_list *cl,
91 char *bf, size_t bfsize)
92{
93 if (cl->ms.sym)
94 scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
95 else
96 scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
97}
98
99static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store, 92static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
100 GtkTreeIter *parent, int col, u64 total) 93 GtkTreeIter *parent, int col, u64 total)
101{ 94{
@@ -126,7 +119,7 @@ static void perf_gtk__add_callchain(struct rb_root *root, GtkTreeStore *store,
126 scnprintf(buf, sizeof(buf), "%5.2f%%", percent); 119 scnprintf(buf, sizeof(buf), "%5.2f%%", percent);
127 gtk_tree_store_set(store, &iter, 0, buf, -1); 120 gtk_tree_store_set(store, &iter, 0, buf, -1);
128 121
129 callchain_list__sym_name(chain, buf, sizeof(buf)); 122 callchain_list__sym_name(chain, buf, sizeof(buf), false);
130 gtk_tree_store_set(store, &iter, col, buf, -1); 123 gtk_tree_store_set(store, &iter, col, buf, -1);
131 124
132 if (need_new_parent) { 125 if (need_new_parent) {
@@ -205,10 +198,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
205 if (perf_hpp__is_sort_entry(fmt)) 198 if (perf_hpp__is_sort_entry(fmt))
206 sym_col = col_idx; 199 sym_col = col_idx;
207 200
208 fmt->header(fmt, &hpp, hists_to_evsel(hists));
209
210 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), 201 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),
211 -1, ltrim(s), 202 -1, fmt->name,
212 renderer, "markup", 203 renderer, "markup",
213 col_idx++, NULL); 204 col_idx++, NULL);
214 } 205 }
@@ -319,7 +310,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
319 gtk_container_add(GTK_CONTAINER(window), vbox); 310 gtk_container_add(GTK_CONTAINER(window), vbox);
320 311
321 evlist__for_each(evlist, pos) { 312 evlist__for_each(evlist, pos) {
322 struct hists *hists = &pos->hists; 313 struct hists *hists = evsel__hists(pos);
323 const char *evname = perf_evsel__name(pos); 314 const char *evname = perf_evsel__name(pos);
324 GtkWidget *scrolled_window; 315 GtkWidget *scrolled_window;
325 GtkWidget *tab_label; 316 GtkWidget *tab_label;
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 498adb23c02e..482adae3cc44 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -15,9 +15,9 @@
15 __ret; \ 15 __ret; \
16}) 16})
17 17
18int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 18static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
19 hpp_field_fn get_field, const char *fmt, 19 hpp_field_fn get_field, const char *fmt, int len,
20 hpp_snprint_fn print_fn, bool fmt_percent) 20 hpp_snprint_fn print_fn, bool fmt_percent)
21{ 21{
22 int ret; 22 int ret;
23 struct hists *hists = he->hists; 23 struct hists *hists = he->hists;
@@ -32,9 +32,9 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
32 if (total) 32 if (total)
33 percent = 100.0 * get_field(he) / total; 33 percent = 100.0 * get_field(he) / total;
34 34
35 ret = hpp__call_print_fn(hpp, print_fn, fmt, percent); 35 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, percent);
36 } else 36 } else
37 ret = hpp__call_print_fn(hpp, print_fn, fmt, get_field(he)); 37 ret = hpp__call_print_fn(hpp, print_fn, fmt, len, get_field(he));
38 38
39 if (perf_evsel__is_group_event(evsel)) { 39 if (perf_evsel__is_group_event(evsel)) {
40 int prev_idx, idx_delta; 40 int prev_idx, idx_delta;
@@ -60,19 +60,19 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
60 */ 60 */
61 if (fmt_percent) { 61 if (fmt_percent) {
62 ret += hpp__call_print_fn(hpp, print_fn, 62 ret += hpp__call_print_fn(hpp, print_fn,
63 fmt, 0.0); 63 fmt, len, 0.0);
64 } else { 64 } else {
65 ret += hpp__call_print_fn(hpp, print_fn, 65 ret += hpp__call_print_fn(hpp, print_fn,
66 fmt, 0ULL); 66 fmt, len, 0ULL);
67 } 67 }
68 } 68 }
69 69
70 if (fmt_percent) { 70 if (fmt_percent) {
71 ret += hpp__call_print_fn(hpp, print_fn, fmt, 71 ret += hpp__call_print_fn(hpp, print_fn, fmt, len,
72 100.0 * period / total); 72 100.0 * period / total);
73 } else { 73 } else {
74 ret += hpp__call_print_fn(hpp, print_fn, fmt, 74 ret += hpp__call_print_fn(hpp, print_fn, fmt,
75 period); 75 len, period);
76 } 76 }
77 77
78 prev_idx = perf_evsel__group_idx(evsel); 78 prev_idx = perf_evsel__group_idx(evsel);
@@ -86,10 +86,10 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
86 */ 86 */
87 if (fmt_percent) { 87 if (fmt_percent) {
88 ret += hpp__call_print_fn(hpp, print_fn, 88 ret += hpp__call_print_fn(hpp, print_fn,
89 fmt, 0.0); 89 fmt, len, 0.0);
90 } else { 90 } else {
91 ret += hpp__call_print_fn(hpp, print_fn, 91 ret += hpp__call_print_fn(hpp, print_fn,
92 fmt, 0ULL); 92 fmt, len, 0ULL);
93 } 93 }
94 } 94 }
95 } 95 }
@@ -104,16 +104,35 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
104 return ret; 104 return ret;
105} 105}
106 106
107int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 107int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
108 hpp_field_fn get_field, const char *fmt, 108 struct hist_entry *he, hpp_field_fn get_field,
109 hpp_snprint_fn print_fn, bool fmt_percent) 109 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{
111 int len = fmt->user_len ?: fmt->len;
112
113 if (symbol_conf.field_sep) {
114 return __hpp__fmt(hpp, he, get_field, fmtstr, 1,
115 print_fn, fmt_percent);
116 }
117
118 if (fmt_percent)
119 len -= 2; /* 2 for a space and a % sign */
120 else
121 len -= 1;
122
123 return __hpp__fmt(hpp, he, get_field, fmtstr, len, print_fn, fmt_percent);
124}
125
126int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
127 struct hist_entry *he, hpp_field_fn get_field,
128 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent)
110{ 129{
111 if (!symbol_conf.cumulate_callchain) { 130 if (!symbol_conf.cumulate_callchain) {
112 return snprintf(hpp->buf, hpp->size, "%*s", 131 int len = fmt->user_len ?: fmt->len;
113 fmt_percent ? 8 : 12, "N/A"); 132 return snprintf(hpp->buf, hpp->size, " %*s", len - 1, "N/A");
114 } 133 }
115 134
116 return __hpp__fmt(hpp, he, get_field, fmt, print_fn, fmt_percent); 135 return hpp__fmt(fmt, hpp, he, get_field, fmtstr, print_fn, fmt_percent);
117} 136}
118 137
119static int field_cmp(u64 field_a, u64 field_b) 138static int field_cmp(u64 field_a, u64 field_b)
@@ -143,8 +162,8 @@ static int __hpp__sort(struct hist_entry *a, struct hist_entry *b,
143 return ret; 162 return ret;
144 163
145 nr_members = evsel->nr_members; 164 nr_members = evsel->nr_members;
146 fields_a = calloc(sizeof(*fields_a), nr_members); 165 fields_a = calloc(nr_members, sizeof(*fields_a));
147 fields_b = calloc(sizeof(*fields_b), nr_members); 166 fields_b = calloc(nr_members, sizeof(*fields_b));
148 167
149 if (!fields_a || !fields_b) 168 if (!fields_a || !fields_b)
150 goto out; 169 goto out;
@@ -185,35 +204,34 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
185 if (ret) 204 if (ret)
186 return ret; 205 return ret;
187 206
207 if (a->thread != b->thread || !symbol_conf.use_callchain)
208 return 0;
209
188 ret = b->callchain->max_depth - a->callchain->max_depth; 210 ret = b->callchain->max_depth - a->callchain->max_depth;
189 } 211 }
190 return ret; 212 return ret;
191} 213}
192 214
193#define __HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \ 215static int hpp__width_fn(struct perf_hpp_fmt *fmt,
194static int hpp__header_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 216 struct perf_hpp *hpp __maybe_unused,
195 struct perf_hpp *hpp, \ 217 struct perf_evsel *evsel)
196 struct perf_evsel *evsel) \ 218{
197{ \ 219 int len = fmt->user_len ?: fmt->len;
198 int len = _min_width; \ 220
199 \ 221 if (symbol_conf.event_group)
200 if (symbol_conf.event_group) \ 222 len = max(len, evsel->nr_members * fmt->len);
201 len = max(len, evsel->nr_members * _unit_width); \ 223
202 \ 224 if (len < (int)strlen(fmt->name))
203 return scnprintf(hpp->buf, hpp->size, "%*s", len, _str); \ 225 len = strlen(fmt->name);
204} 226
205 227 return len;
206#define __HPP_WIDTH_FN(_type, _min_width, _unit_width) \ 228}
207static int hpp__width_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 229
208 struct perf_hpp *hpp __maybe_unused, \ 230static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
209 struct perf_evsel *evsel) \ 231 struct perf_evsel *evsel)
210{ \ 232{
211 int len = _min_width; \ 233 int len = hpp__width_fn(fmt, hpp, evsel);
212 \ 234 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
213 if (symbol_conf.event_group) \
214 len = max(len, evsel->nr_members * _unit_width); \
215 \
216 return len; \
217} 235}
218 236
219static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 237static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
@@ -221,11 +239,12 @@ static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
221 va_list args; 239 va_list args;
222 ssize_t ssize = hpp->size; 240 ssize_t ssize = hpp->size;
223 double percent; 241 double percent;
224 int ret; 242 int ret, len;
225 243
226 va_start(args, fmt); 244 va_start(args, fmt);
245 len = va_arg(args, int);
227 percent = va_arg(args, double); 246 percent = va_arg(args, double);
228 ret = value_color_snprintf(hpp->buf, hpp->size, fmt, percent); 247 ret = percent_color_len_snprintf(hpp->buf, hpp->size, fmt, len, percent);
229 va_end(args); 248 va_end(args);
230 249
231 return (ret >= ssize) ? (ssize - 1) : ret; 250 return (ret >= ssize) ? (ssize - 1) : ret;
@@ -250,20 +269,19 @@ static u64 he_get_##_field(struct hist_entry *he) \
250 return he->stat._field; \ 269 return he->stat._field; \
251} \ 270} \
252 \ 271 \
253static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 272static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
254 struct perf_hpp *hpp, struct hist_entry *he) \ 273 struct perf_hpp *hpp, struct hist_entry *he) \
255{ \ 274{ \
256 return __hpp__fmt(hpp, he, he_get_##_field, " %6.2f%%", \ 275 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
257 hpp_color_scnprintf, true); \ 276 hpp_color_scnprintf, true); \
258} 277}
259 278
260#define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 279#define __HPP_ENTRY_PERCENT_FN(_type, _field) \
261static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 280static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
262 struct perf_hpp *hpp, struct hist_entry *he) \ 281 struct perf_hpp *hpp, struct hist_entry *he) \
263{ \ 282{ \
264 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 283 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \
265 return __hpp__fmt(hpp, he, he_get_##_field, fmt, \ 284 hpp_entry_scnprintf, true); \
266 hpp_entry_scnprintf, true); \
267} 285}
268 286
269#define __HPP_SORT_FN(_type, _field) \ 287#define __HPP_SORT_FN(_type, _field) \
@@ -278,20 +296,19 @@ static u64 he_get_acc_##_field(struct hist_entry *he) \
278 return he->stat_acc->_field; \ 296 return he->stat_acc->_field; \
279} \ 297} \
280 \ 298 \
281static int hpp__color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ 299static int hpp__color_##_type(struct perf_hpp_fmt *fmt, \
282 struct perf_hpp *hpp, struct hist_entry *he) \ 300 struct perf_hpp *hpp, struct hist_entry *he) \
283{ \ 301{ \
284 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, " %6.2f%%", \ 302 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
285 hpp_color_scnprintf, true); \ 303 hpp_color_scnprintf, true); \
286} 304}
287 305
288#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 306#define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
289static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 307static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
290 struct perf_hpp *hpp, struct hist_entry *he) \ 308 struct perf_hpp *hpp, struct hist_entry *he) \
291{ \ 309{ \
292 const char *fmt = symbol_conf.field_sep ? " %.2f" : " %6.2f%%"; \ 310 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \
293 return __hpp__fmt_acc(hpp, he, he_get_acc_##_field, fmt, \ 311 hpp_entry_scnprintf, true); \
294 hpp_entry_scnprintf, true); \
295} 312}
296 313
297#define __HPP_SORT_ACC_FN(_type, _field) \ 314#define __HPP_SORT_ACC_FN(_type, _field) \
@@ -306,12 +323,11 @@ static u64 he_get_raw_##_field(struct hist_entry *he) \
306 return he->stat._field; \ 323 return he->stat._field; \
307} \ 324} \
308 \ 325 \
309static int hpp__entry_##_type(struct perf_hpp_fmt *_fmt __maybe_unused, \ 326static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \
310 struct perf_hpp *hpp, struct hist_entry *he) \ 327 struct perf_hpp *hpp, struct hist_entry *he) \
311{ \ 328{ \
312 const char *fmt = symbol_conf.field_sep ? " %"PRIu64 : " %11"PRIu64; \ 329 return hpp__fmt(fmt, hpp, he, he_get_raw_##_field, " %*"PRIu64, \
313 return __hpp__fmt(hpp, he, he_get_raw_##_field, fmt, \ 330 hpp_entry_scnprintf, false); \
314 hpp_entry_scnprintf, false); \
315} 331}
316 332
317#define __HPP_SORT_RAW_FN(_type, _field) \ 333#define __HPP_SORT_RAW_FN(_type, _field) \
@@ -321,37 +337,29 @@ static int64_t hpp__sort_##_type(struct hist_entry *a, struct hist_entry *b) \
321} 337}
322 338
323 339
324#define HPP_PERCENT_FNS(_type, _str, _field, _min_width, _unit_width) \ 340#define HPP_PERCENT_FNS(_type, _field) \
325__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
326__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
327__HPP_COLOR_PERCENT_FN(_type, _field) \ 341__HPP_COLOR_PERCENT_FN(_type, _field) \
328__HPP_ENTRY_PERCENT_FN(_type, _field) \ 342__HPP_ENTRY_PERCENT_FN(_type, _field) \
329__HPP_SORT_FN(_type, _field) 343__HPP_SORT_FN(_type, _field)
330 344
331#define HPP_PERCENT_ACC_FNS(_type, _str, _field, _min_width, _unit_width)\ 345#define HPP_PERCENT_ACC_FNS(_type, _field) \
332__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
333__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
334__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 346__HPP_COLOR_ACC_PERCENT_FN(_type, _field) \
335__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 347__HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \
336__HPP_SORT_ACC_FN(_type, _field) 348__HPP_SORT_ACC_FN(_type, _field)
337 349
338#define HPP_RAW_FNS(_type, _str, _field, _min_width, _unit_width) \ 350#define HPP_RAW_FNS(_type, _field) \
339__HPP_HEADER_FN(_type, _str, _min_width, _unit_width) \
340__HPP_WIDTH_FN(_type, _min_width, _unit_width) \
341__HPP_ENTRY_RAW_FN(_type, _field) \ 351__HPP_ENTRY_RAW_FN(_type, _field) \
342__HPP_SORT_RAW_FN(_type, _field) 352__HPP_SORT_RAW_FN(_type, _field)
343 353
344__HPP_HEADER_FN(overhead_self, "Self", 8, 8) 354HPP_PERCENT_FNS(overhead, period)
345 355HPP_PERCENT_FNS(overhead_sys, period_sys)
346HPP_PERCENT_FNS(overhead, "Overhead", period, 8, 8) 356HPP_PERCENT_FNS(overhead_us, period_us)
347HPP_PERCENT_FNS(overhead_sys, "sys", period_sys, 8, 8) 357HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys)
348HPP_PERCENT_FNS(overhead_us, "usr", period_us, 8, 8) 358HPP_PERCENT_FNS(overhead_guest_us, period_guest_us)
349HPP_PERCENT_FNS(overhead_guest_sys, "guest sys", period_guest_sys, 9, 8) 359HPP_PERCENT_ACC_FNS(overhead_acc, period)
350HPP_PERCENT_FNS(overhead_guest_us, "guest usr", period_guest_us, 9, 8)
351HPP_PERCENT_ACC_FNS(overhead_acc, "Children", period, 8, 8)
352 360
353HPP_RAW_FNS(samples, "Samples", nr_events, 12, 12) 361HPP_RAW_FNS(samples, nr_events)
354HPP_RAW_FNS(period, "Period", period, 12, 12) 362HPP_RAW_FNS(period, period)
355 363
356static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused, 364static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
357 struct hist_entry *b __maybe_unused) 365 struct hist_entry *b __maybe_unused)
@@ -359,47 +367,50 @@ static int64_t hpp__nop_cmp(struct hist_entry *a __maybe_unused,
359 return 0; 367 return 0;
360} 368}
361 369
362#define HPP__COLOR_PRINT_FNS(_name) \ 370#define HPP__COLOR_PRINT_FNS(_name, _fn) \
363 { \ 371 { \
364 .header = hpp__header_ ## _name, \ 372 .name = _name, \
365 .width = hpp__width_ ## _name, \ 373 .header = hpp__header_fn, \
366 .color = hpp__color_ ## _name, \ 374 .width = hpp__width_fn, \
367 .entry = hpp__entry_ ## _name, \ 375 .color = hpp__color_ ## _fn, \
376 .entry = hpp__entry_ ## _fn, \
368 .cmp = hpp__nop_cmp, \ 377 .cmp = hpp__nop_cmp, \
369 .collapse = hpp__nop_cmp, \ 378 .collapse = hpp__nop_cmp, \
370 .sort = hpp__sort_ ## _name, \ 379 .sort = hpp__sort_ ## _fn, \
371 } 380 }
372 381
373#define HPP__COLOR_ACC_PRINT_FNS(_name) \ 382#define HPP__COLOR_ACC_PRINT_FNS(_name, _fn) \
374 { \ 383 { \
375 .header = hpp__header_ ## _name, \ 384 .name = _name, \
376 .width = hpp__width_ ## _name, \ 385 .header = hpp__header_fn, \
377 .color = hpp__color_ ## _name, \ 386 .width = hpp__width_fn, \
378 .entry = hpp__entry_ ## _name, \ 387 .color = hpp__color_ ## _fn, \
388 .entry = hpp__entry_ ## _fn, \
379 .cmp = hpp__nop_cmp, \ 389 .cmp = hpp__nop_cmp, \
380 .collapse = hpp__nop_cmp, \ 390 .collapse = hpp__nop_cmp, \
381 .sort = hpp__sort_ ## _name, \ 391 .sort = hpp__sort_ ## _fn, \
382 } 392 }
383 393
384#define HPP__PRINT_FNS(_name) \ 394#define HPP__PRINT_FNS(_name, _fn) \
385 { \ 395 { \
386 .header = hpp__header_ ## _name, \ 396 .name = _name, \
387 .width = hpp__width_ ## _name, \ 397 .header = hpp__header_fn, \
388 .entry = hpp__entry_ ## _name, \ 398 .width = hpp__width_fn, \
399 .entry = hpp__entry_ ## _fn, \
389 .cmp = hpp__nop_cmp, \ 400 .cmp = hpp__nop_cmp, \
390 .collapse = hpp__nop_cmp, \ 401 .collapse = hpp__nop_cmp, \
391 .sort = hpp__sort_ ## _name, \ 402 .sort = hpp__sort_ ## _fn, \
392 } 403 }
393 404
394struct perf_hpp_fmt perf_hpp__format[] = { 405struct perf_hpp_fmt perf_hpp__format[] = {
395 HPP__COLOR_PRINT_FNS(overhead), 406 HPP__COLOR_PRINT_FNS("Overhead", overhead),
396 HPP__COLOR_PRINT_FNS(overhead_sys), 407 HPP__COLOR_PRINT_FNS("sys", overhead_sys),
397 HPP__COLOR_PRINT_FNS(overhead_us), 408 HPP__COLOR_PRINT_FNS("usr", overhead_us),
398 HPP__COLOR_PRINT_FNS(overhead_guest_sys), 409 HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys),
399 HPP__COLOR_PRINT_FNS(overhead_guest_us), 410 HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us),
400 HPP__COLOR_ACC_PRINT_FNS(overhead_acc), 411 HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc),
401 HPP__PRINT_FNS(samples), 412 HPP__PRINT_FNS("Samples", samples),
402 HPP__PRINT_FNS(period) 413 HPP__PRINT_FNS("Period", period)
403}; 414};
404 415
405LIST_HEAD(perf_hpp__list); 416LIST_HEAD(perf_hpp__list);
@@ -444,14 +455,12 @@ void perf_hpp__init(void)
444 /* 455 /*
445 * If user specified field order, no need to setup default fields. 456 * If user specified field order, no need to setup default fields.
446 */ 457 */
447 if (field_order) 458 if (is_strict_order(field_order))
448 return; 459 return;
449 460
450 if (symbol_conf.cumulate_callchain) { 461 if (symbol_conf.cumulate_callchain) {
451 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); 462 perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC);
452 463 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";
453 perf_hpp__format[PERF_HPP__OVERHEAD].header =
454 hpp__header_overhead_self;
455 } 464 }
456 465
457 perf_hpp__column_enable(PERF_HPP__OVERHEAD); 466 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
@@ -513,11 +522,11 @@ void perf_hpp__column_disable(unsigned col)
513 522
514void perf_hpp__cancel_cumulate(void) 523void perf_hpp__cancel_cumulate(void)
515{ 524{
516 if (field_order) 525 if (is_strict_order(field_order))
517 return; 526 return;
518 527
519 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC); 528 perf_hpp__column_disable(PERF_HPP__OVERHEAD_ACC);
520 perf_hpp__format[PERF_HPP__OVERHEAD].header = hpp__header_overhead; 529 perf_hpp__format[PERF_HPP__OVERHEAD].name = "Overhead";
521} 530}
522 531
523void perf_hpp__setup_output_field(void) 532void perf_hpp__setup_output_field(void)
@@ -622,3 +631,59 @@ unsigned int hists__sort_list_width(struct hists *hists)
622 631
623 return ret; 632 return ret;
624} 633}
634
635void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
636{
637 int idx;
638
639 if (perf_hpp__is_sort_entry(fmt))
640 return perf_hpp__reset_sort_width(fmt, hists);
641
642 for (idx = 0; idx < PERF_HPP__MAX_INDEX; idx++) {
643 if (fmt == &perf_hpp__format[idx])
644 break;
645 }
646
647 if (idx == PERF_HPP__MAX_INDEX)
648 return;
649
650 switch (idx) {
651 case PERF_HPP__OVERHEAD:
652 case PERF_HPP__OVERHEAD_SYS:
653 case PERF_HPP__OVERHEAD_US:
654 case PERF_HPP__OVERHEAD_ACC:
655 fmt->len = 8;
656 break;
657
658 case PERF_HPP__OVERHEAD_GUEST_SYS:
659 case PERF_HPP__OVERHEAD_GUEST_US:
660 fmt->len = 9;
661 break;
662
663 case PERF_HPP__SAMPLES:
664 case PERF_HPP__PERIOD:
665 fmt->len = 12;
666 break;
667
668 default:
669 break;
670 }
671}
672
673void perf_hpp__set_user_width(const char *width_list_str)
674{
675 struct perf_hpp_fmt *fmt;
676 const char *ptr = width_list_str;
677
678 perf_hpp__for_each_format(fmt) {
679 char *p;
680
681 int len = strtol(ptr, &p, 10);
682 fmt->user_len = len;
683
684 if (*p == ',')
685 ptr = p + 1;
686 else
687 break;
688 }
689}
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 40af0acb4fe9..dfcbc90146ef 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -41,6 +41,7 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
41{ 41{
42 int i; 42 int i;
43 size_t ret = 0; 43 size_t ret = 0;
44 char bf[1024];
44 45
45 ret += callchain__fprintf_left_margin(fp, left_margin); 46 ret += callchain__fprintf_left_margin(fp, left_margin);
46 for (i = 0; i < depth; i++) { 47 for (i = 0; i < depth; i++) {
@@ -56,11 +57,8 @@ static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
56 } else 57 } else
57 ret += fprintf(fp, "%s", " "); 58 ret += fprintf(fp, "%s", " ");
58 } 59 }
59 if (chain->ms.sym) 60 fputs(callchain_list__sym_name(chain, bf, sizeof(bf), false), fp);
60 ret += fprintf(fp, "%s\n", chain->ms.sym->name); 61 fputc('\n', fp);
61 else
62 ret += fprintf(fp, "0x%0" PRIx64 "\n", chain->ip);
63
64 return ret; 62 return ret;
65} 63}
66 64
@@ -168,6 +166,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
168 struct rb_node *node; 166 struct rb_node *node;
169 int i = 0; 167 int i = 0;
170 int ret = 0; 168 int ret = 0;
169 char bf[1024];
171 170
172 /* 171 /*
173 * If have one single callchain root, don't bother printing 172 * If have one single callchain root, don't bother printing
@@ -196,10 +195,8 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
196 } else 195 } else
197 ret += callchain__fprintf_left_margin(fp, left_margin); 196 ret += callchain__fprintf_left_margin(fp, left_margin);
198 197
199 if (chain->ms.sym) 198 ret += fprintf(fp, "%s\n", callchain_list__sym_name(chain, bf, sizeof(bf),
200 ret += fprintf(fp, " %s\n", chain->ms.sym->name); 199 false));
201 else
202 ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
203 200
204 if (++entries_printed == callchain_param.print_limit) 201 if (++entries_printed == callchain_param.print_limit)
205 break; 202 break;
@@ -219,6 +216,7 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
219{ 216{
220 struct callchain_list *chain; 217 struct callchain_list *chain;
221 size_t ret = 0; 218 size_t ret = 0;
219 char bf[1024];
222 220
223 if (!node) 221 if (!node)
224 return 0; 222 return 0;
@@ -229,11 +227,8 @@ static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
229 list_for_each_entry(chain, &node->val, list) { 227 list_for_each_entry(chain, &node->val, list) {
230 if (chain->ip >= PERF_CONTEXT_MAX) 228 if (chain->ip >= PERF_CONTEXT_MAX)
231 continue; 229 continue;
232 if (chain->ms.sym) 230 ret += fprintf(fp, " %s\n", callchain_list__sym_name(chain,
233 ret += fprintf(fp, " %s\n", chain->ms.sym->name); 231 bf, sizeof(bf), false));
234 else
235 ret += fprintf(fp, " %p\n",
236 (void *)(long)chain->ip);
237 } 232 }
238 233
239 return ret; 234 return ret;
@@ -395,10 +390,12 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
395 390
396 init_rem_hits(); 391 init_rem_hits();
397 392
398
399 perf_hpp__for_each_format(fmt) 393 perf_hpp__for_each_format(fmt)
400 perf_hpp__reset_width(fmt, hists); 394 perf_hpp__reset_width(fmt, hists);
401 395
396 if (symbol_conf.col_width_list_str)
397 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
398
402 if (!show_header) 399 if (!show_header)
403 goto print_entries; 400 goto print_entries;
404 401
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 2f612562978c..3c38f25b1695 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -1,5 +1,8 @@
1#include <signal.h> 1#include <signal.h>
2#include <stdbool.h> 2#include <stdbool.h>
3#ifdef HAVE_BACKTRACE_SUPPORT
4#include <execinfo.h>
5#endif
3 6
4#include "../../util/cache.h" 7#include "../../util/cache.h"
5#include "../../util/debug.h" 8#include "../../util/debug.h"
@@ -88,6 +91,25 @@ int ui__getch(int delay_secs)
88 return SLkp_getkey(); 91 return SLkp_getkey();
89} 92}
90 93
94#ifdef HAVE_BACKTRACE_SUPPORT
95static void ui__signal_backtrace(int sig)
96{
97 void *stackdump[32];
98 size_t size;
99
100 ui__exit(false);
101 psignal(sig, "perf");
102
103 printf("-------- backtrace --------\n");
104 size = backtrace(stackdump, ARRAY_SIZE(stackdump));
105 backtrace_symbols_fd(stackdump, size, STDOUT_FILENO);
106
107 exit(0);
108}
109#else
110# define ui__signal_backtrace ui__signal
111#endif
112
91static void ui__signal(int sig) 113static void ui__signal(int sig)
92{ 114{
93 ui__exit(false); 115 ui__exit(false);
@@ -122,8 +144,8 @@ int ui__init(void)
122 ui_browser__init(); 144 ui_browser__init();
123 tui_progress__init(); 145 tui_progress__init();
124 146
125 signal(SIGSEGV, ui__signal); 147 signal(SIGSEGV, ui__signal_backtrace);
126 signal(SIGFPE, ui__signal); 148 signal(SIGFPE, ui__signal_backtrace);
127 signal(SIGINT, ui__signal); 149 signal(SIGINT, ui__signal);
128 signal(SIGQUIT, ui__signal); 150 signal(SIGQUIT, ui__signal);
129 signal(SIGTERM, ui__signal); 151 signal(SIGTERM, ui__signal);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 809b4c50beae..79999ceaf2be 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,11 +17,13 @@
17#include "debug.h" 17#include "debug.h"
18#include "annotate.h" 18#include "annotate.h"
19#include "evsel.h" 19#include "evsel.h"
20#include <regex.h>
20#include <pthread.h> 21#include <pthread.h>
21#include <linux/bitops.h> 22#include <linux/bitops.h>
22 23
23const char *disassembler_style; 24const char *disassembler_style;
24const char *objdump_path; 25const char *objdump_path;
26static regex_t file_lineno;
25 27
26static struct ins *ins__find(const char *name); 28static struct ins *ins__find(const char *name);
27static int disasm_line__parse(char *line, char **namep, char **rawp); 29static int disasm_line__parse(char *line, char **namep, char **rawp);
@@ -232,9 +234,16 @@ static int mov__parse(struct ins_operands *ops)
232 return -1; 234 return -1;
233 235
234 target = ++s; 236 target = ++s;
237 comment = strchr(s, '#');
235 238
236 while (s[0] != '\0' && !isspace(s[0])) 239 if (comment != NULL)
237 ++s; 240 s = comment - 1;
241 else
242 s = strchr(s, '\0') - 1;
243
244 while (s > target && isspace(s[0]))
245 --s;
246 s++;
238 prev = *s; 247 prev = *s;
239 *s = '\0'; 248 *s = '\0';
240 249
@@ -244,7 +253,6 @@ static int mov__parse(struct ins_operands *ops)
244 if (ops->target.raw == NULL) 253 if (ops->target.raw == NULL)
245 goto out_free_source; 254 goto out_free_source;
246 255
247 comment = strchr(s, '#');
248 if (comment == NULL) 256 if (comment == NULL)
249 return 0; 257 return 0;
250 258
@@ -472,7 +480,7 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
472 480
473 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 481 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
474 482
475 if (addr < sym->start || addr > sym->end) 483 if (addr < sym->start || addr >= sym->end)
476 return -ERANGE; 484 return -ERANGE;
477 485
478 offset = addr - sym->start; 486 offset = addr - sym->start;
@@ -564,13 +572,15 @@ out_free_name:
564 return -1; 572 return -1;
565} 573}
566 574
567static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) 575static struct disasm_line *disasm_line__new(s64 offset, char *line,
576 size_t privsize, int line_nr)
568{ 577{
569 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 578 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
570 579
571 if (dl != NULL) { 580 if (dl != NULL) {
572 dl->offset = offset; 581 dl->offset = offset;
573 dl->line = strdup(line); 582 dl->line = strdup(line);
583 dl->line_nr = line_nr;
574 if (dl->line == NULL) 584 if (dl->line == NULL)
575 goto out_delete; 585 goto out_delete;
576 586
@@ -782,13 +792,15 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
782 * The ops.raw part will be parsed further according to type of the instruction. 792 * The ops.raw part will be parsed further according to type of the instruction.
783 */ 793 */
784static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, 794static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
785 FILE *file, size_t privsize) 795 FILE *file, size_t privsize,
796 int *line_nr)
786{ 797{
787 struct annotation *notes = symbol__annotation(sym); 798 struct annotation *notes = symbol__annotation(sym);
788 struct disasm_line *dl; 799 struct disasm_line *dl;
789 char *line = NULL, *parsed_line, *tmp, *tmp2, *c; 800 char *line = NULL, *parsed_line, *tmp, *tmp2, *c;
790 size_t line_len; 801 size_t line_len;
791 s64 line_ip, offset = -1; 802 s64 line_ip, offset = -1;
803 regmatch_t match[2];
792 804
793 if (getline(&line, &line_len, file) < 0) 805 if (getline(&line, &line_len, file) < 0)
794 return -1; 806 return -1;
@@ -806,6 +818,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
806 line_ip = -1; 818 line_ip = -1;
807 parsed_line = line; 819 parsed_line = line;
808 820
821 /* /filename:linenr ? Save line number and ignore. */
822 if (regexec(&file_lineno, line, 2, match, 0) == 0) {
823 *line_nr = atoi(line + match[1].rm_so);
824 return 0;
825 }
826
809 /* 827 /*
810 * Strip leading spaces: 828 * Strip leading spaces:
811 */ 829 */
@@ -830,14 +848,15 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
830 end = map__rip_2objdump(map, sym->end); 848 end = map__rip_2objdump(map, sym->end);
831 849
832 offset = line_ip - start; 850 offset = line_ip - start;
833 if ((u64)line_ip < start || (u64)line_ip > end) 851 if ((u64)line_ip < start || (u64)line_ip >= end)
834 offset = -1; 852 offset = -1;
835 else 853 else
836 parsed_line = tmp2 + 1; 854 parsed_line = tmp2 + 1;
837 } 855 }
838 856
839 dl = disasm_line__new(offset, parsed_line, privsize); 857 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr);
840 free(line); 858 free(line);
859 (*line_nr)++;
841 860
842 if (dl == NULL) 861 if (dl == NULL)
843 return -1; 862 return -1;
@@ -863,6 +882,11 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
863 return 0; 882 return 0;
864} 883}
865 884
885static __attribute__((constructor)) void symbol__init_regexpr(void)
886{
887 regcomp(&file_lineno, "^/[^:]+:([0-9]+)", REG_EXTENDED);
888}
889
866static void delete_last_nop(struct symbol *sym) 890static void delete_last_nop(struct symbol *sym)
867{ 891{
868 struct annotation *notes = symbol__annotation(sym); 892 struct annotation *notes = symbol__annotation(sym);
@@ -898,11 +922,10 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
898 char symfs_filename[PATH_MAX]; 922 char symfs_filename[PATH_MAX];
899 struct kcore_extract kce; 923 struct kcore_extract kce;
900 bool delete_extract = false; 924 bool delete_extract = false;
925 int lineno = 0;
901 926
902 if (filename) { 927 if (filename)
903 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 928 symbol__join_symfs(symfs_filename, filename);
904 symbol_conf.symfs, filename);
905 }
906 929
907 if (filename == NULL) { 930 if (filename == NULL) {
908 if (dso->has_build_id) { 931 if (dso->has_build_id) {
@@ -911,6 +934,8 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
911 return -ENOMEM; 934 return -ENOMEM;
912 } 935 }
913 goto fallback; 936 goto fallback;
937 } else if (dso__is_kcore(dso)) {
938 goto fallback;
914 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 939 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
915 strstr(command, "[kernel.kallsyms]") || 940 strstr(command, "[kernel.kallsyms]") ||
916 access(symfs_filename, R_OK)) { 941 access(symfs_filename, R_OK)) {
@@ -922,8 +947,7 @@ fallback:
922 * DSO is the same as when 'perf record' ran. 947 * DSO is the same as when 'perf record' ran.
923 */ 948 */
924 filename = (char *)dso->long_name; 949 filename = (char *)dso->long_name;
925 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s", 950 symbol__join_symfs(symfs_filename, filename);
926 symbol_conf.symfs, filename);
927 free_filename = false; 951 free_filename = false;
928 } 952 }
929 953
@@ -963,7 +987,7 @@ fallback:
963 kce.kcore_filename = symfs_filename; 987 kce.kcore_filename = symfs_filename;
964 kce.addr = map__rip_2objdump(map, sym->start); 988 kce.addr = map__rip_2objdump(map, sym->start);
965 kce.offs = sym->start; 989 kce.offs = sym->start;
966 kce.len = sym->end + 1 - sym->start; 990 kce.len = sym->end - sym->start;
967 if (!kcore_extract__create(&kce)) { 991 if (!kcore_extract__create(&kce)) {
968 delete_extract = true; 992 delete_extract = true;
969 strlcpy(symfs_filename, kce.extract_filename, 993 strlcpy(symfs_filename, kce.extract_filename,
@@ -979,12 +1003,12 @@ fallback:
979 snprintf(command, sizeof(command), 1003 snprintf(command, sizeof(command),
980 "%s %s%s --start-address=0x%016" PRIx64 1004 "%s %s%s --start-address=0x%016" PRIx64
981 " --stop-address=0x%016" PRIx64 1005 " --stop-address=0x%016" PRIx64
982 " -d %s %s -C %s 2>/dev/null|grep -v %s|expand", 1006 " -l -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
983 objdump_path ? objdump_path : "objdump", 1007 objdump_path ? objdump_path : "objdump",
984 disassembler_style ? "-M " : "", 1008 disassembler_style ? "-M " : "",
985 disassembler_style ? disassembler_style : "", 1009 disassembler_style ? disassembler_style : "",
986 map__rip_2objdump(map, sym->start), 1010 map__rip_2objdump(map, sym->start),
987 map__rip_2objdump(map, sym->end+1), 1011 map__rip_2objdump(map, sym->end),
988 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 1012 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
989 symbol_conf.annotate_src ? "-S" : "", 1013 symbol_conf.annotate_src ? "-S" : "",
990 symfs_filename, filename); 1014 symfs_filename, filename);
@@ -996,7 +1020,8 @@ fallback:
996 goto out_free_filename; 1020 goto out_free_filename;
997 1021
998 while (!feof(file)) 1022 while (!feof(file))
999 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 1023 if (symbol__parse_objdump_line(sym, map, file, privsize,
1024 &lineno) < 0)
1000 break; 1025 break;
1001 1026
1002 /* 1027 /*
@@ -1167,7 +1192,7 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
1167 goto next; 1192 goto next;
1168 1193
1169 offset = start + i; 1194 offset = start + i;
1170 src_line->path = get_srcline(map->dso, offset); 1195 src_line->path = get_srcline(map->dso, offset, NULL, false);
1171 insert_source_line(&tmp_root, src_line); 1196 insert_source_line(&tmp_root, src_line);
1172 1197
1173 next: 1198 next:
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 112d6e268150..0784a9420528 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -58,6 +58,7 @@ struct disasm_line {
58 char *line; 58 char *line;
59 char *name; 59 char *name;
60 struct ins *ins; 60 struct ins *ins;
61 int line_nr;
61 struct ins_operands ops; 62 struct ins_operands ops;
62}; 63};
63 64
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a904a4cfe7d3..0c72680a977f 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -15,6 +15,11 @@
15#include "debug.h" 15#include "debug.h"
16#include "session.h" 16#include "session.h"
17#include "tool.h" 17#include "tool.h"
18#include "header.h"
19#include "vdso.h"
20
21
22static bool no_buildid_cache;
18 23
19int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, 24int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
20 union perf_event *event, 25 union perf_event *event,
@@ -33,8 +38,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
33 return -1; 38 return -1;
34 } 39 }
35 40
36 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 41 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al);
37 sample->ip, &al);
38 42
39 if (al.map != NULL) 43 if (al.map != NULL)
40 al.map->dso->hit = 1; 44 al.map->dso->hit = 1;
@@ -106,3 +110,340 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
106 build_id_hex, build_id_hex + 2); 110 build_id_hex, build_id_hex + 2);
107 return bf; 111 return bf;
108} 112}
113
114#define dsos__for_each_with_build_id(pos, head) \
115 list_for_each_entry(pos, head, node) \
116 if (!pos->has_build_id) \
117 continue; \
118 else
119
120static int write_buildid(const char *name, size_t name_len, u8 *build_id,
121 pid_t pid, u16 misc, int fd)
122{
123 int err;
124 struct build_id_event b;
125 size_t len;
126
127 len = name_len + 1;
128 len = PERF_ALIGN(len, NAME_ALIGN);
129
130 memset(&b, 0, sizeof(b));
131 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
132 b.pid = pid;
133 b.header.misc = misc;
134 b.header.size = sizeof(b) + len;
135
136 err = writen(fd, &b, sizeof(b));
137 if (err < 0)
138 return err;
139
140 return write_padded(fd, name, name_len + 1, len);
141}
142
143static int __dsos__write_buildid_table(struct list_head *head,
144 struct machine *machine,
145 pid_t pid, u16 misc, int fd)
146{
147 char nm[PATH_MAX];
148 struct dso *pos;
149
150 dsos__for_each_with_build_id(pos, head) {
151 int err;
152 const char *name;
153 size_t name_len;
154
155 if (!pos->hit)
156 continue;
157
158 if (dso__is_vdso(pos)) {
159 name = pos->short_name;
160 name_len = pos->short_name_len + 1;
161 } else if (dso__is_kcore(pos)) {
162 machine__mmap_name(machine, nm, sizeof(nm));
163 name = nm;
164 name_len = strlen(nm) + 1;
165 } else {
166 name = pos->long_name;
167 name_len = pos->long_name_len + 1;
168 }
169
170 err = write_buildid(name, name_len, pos->build_id,
171 pid, misc, fd);
172 if (err)
173 return err;
174 }
175
176 return 0;
177}
178
179static int machine__write_buildid_table(struct machine *machine, int fd)
180{
181 int err;
182 u16 kmisc = PERF_RECORD_MISC_KERNEL,
183 umisc = PERF_RECORD_MISC_USER;
184
185 if (!machine__is_host(machine)) {
186 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
187 umisc = PERF_RECORD_MISC_GUEST_USER;
188 }
189
190 err = __dsos__write_buildid_table(&machine->kernel_dsos.head, machine,
191 machine->pid, kmisc, fd);
192 if (err == 0)
193 err = __dsos__write_buildid_table(&machine->user_dsos.head,
194 machine, machine->pid, umisc,
195 fd);
196 return err;
197}
198
199int perf_session__write_buildid_table(struct perf_session *session, int fd)
200{
201 struct rb_node *nd;
202 int err = machine__write_buildid_table(&session->machines.host, fd);
203
204 if (err)
205 return err;
206
207 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
208 struct machine *pos = rb_entry(nd, struct machine, rb_node);
209 err = machine__write_buildid_table(pos, fd);
210 if (err)
211 break;
212 }
213 return err;
214}
215
216static int __dsos__hit_all(struct list_head *head)
217{
218 struct dso *pos;
219
220 list_for_each_entry(pos, head, node)
221 pos->hit = true;
222
223 return 0;
224}
225
226static int machine__hit_all_dsos(struct machine *machine)
227{
228 int err;
229
230 err = __dsos__hit_all(&machine->kernel_dsos.head);
231 if (err)
232 return err;
233
234 return __dsos__hit_all(&machine->user_dsos.head);
235}
236
237int dsos__hit_all(struct perf_session *session)
238{
239 struct rb_node *nd;
240 int err;
241
242 err = machine__hit_all_dsos(&session->machines.host);
243 if (err)
244 return err;
245
246 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
247 struct machine *pos = rb_entry(nd, struct machine, rb_node);
248
249 err = machine__hit_all_dsos(pos);
250 if (err)
251 return err;
252 }
253
254 return 0;
255}
256
257void disable_buildid_cache(void)
258{
259 no_buildid_cache = true;
260}
261
262int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
263 const char *name, bool is_kallsyms, bool is_vdso)
264{
265 const size_t size = PATH_MAX;
266 char *realname, *filename = zalloc(size),
267 *linkname = zalloc(size), *targetname;
268 int len, err = -1;
269 bool slash = is_kallsyms || is_vdso;
270
271 if (is_kallsyms) {
272 if (symbol_conf.kptr_restrict) {
273 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
274 err = 0;
275 goto out_free;
276 }
277 realname = (char *) name;
278 } else
279 realname = realpath(name, NULL);
280
281 if (realname == NULL || filename == NULL || linkname == NULL)
282 goto out_free;
283
284 len = scnprintf(filename, size, "%s%s%s",
285 debugdir, slash ? "/" : "",
286 is_vdso ? DSO__NAME_VDSO : realname);
287 if (mkdir_p(filename, 0755))
288 goto out_free;
289
290 snprintf(filename + len, size - len, "/%s", sbuild_id);
291
292 if (access(filename, F_OK)) {
293 if (is_kallsyms) {
294 if (copyfile("/proc/kallsyms", filename))
295 goto out_free;
296 } else if (link(realname, filename) && copyfile(name, filename))
297 goto out_free;
298 }
299
300 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
301 debugdir, sbuild_id);
302
303 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
304 goto out_free;
305
306 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
307 targetname = filename + strlen(debugdir) - 5;
308 memcpy(targetname, "../..", 5);
309
310 if (symlink(targetname, linkname) == 0)
311 err = 0;
312out_free:
313 if (!is_kallsyms)
314 free(realname);
315 free(filename);
316 free(linkname);
317 return err;
318}
319
320static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
321 const char *name, const char *debugdir,
322 bool is_kallsyms, bool is_vdso)
323{
324 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
325
326 build_id__sprintf(build_id, build_id_size, sbuild_id);
327
328 return build_id_cache__add_s(sbuild_id, debugdir, name,
329 is_kallsyms, is_vdso);
330}
331
332int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
333{
334 const size_t size = PATH_MAX;
335 char *filename = zalloc(size),
336 *linkname = zalloc(size);
337 int err = -1;
338
339 if (filename == NULL || linkname == NULL)
340 goto out_free;
341
342 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
343 debugdir, sbuild_id, sbuild_id + 2);
344
345 if (access(linkname, F_OK))
346 goto out_free;
347
348 if (readlink(linkname, filename, size - 1) < 0)
349 goto out_free;
350
351 if (unlink(linkname))
352 goto out_free;
353
354 /*
355 * Since the link is relative, we must make it absolute:
356 */
357 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
358 debugdir, sbuild_id, filename);
359
360 if (unlink(linkname))
361 goto out_free;
362
363 err = 0;
364out_free:
365 free(filename);
366 free(linkname);
367 return err;
368}
369
370static int dso__cache_build_id(struct dso *dso, struct machine *machine,
371 const char *debugdir)
372{
373 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
374 bool is_vdso = dso__is_vdso(dso);
375 const char *name = dso->long_name;
376 char nm[PATH_MAX];
377
378 if (dso__is_kcore(dso)) {
379 is_kallsyms = true;
380 machine__mmap_name(machine, nm, sizeof(nm));
381 name = nm;
382 }
383 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
384 debugdir, is_kallsyms, is_vdso);
385}
386
387static int __dsos__cache_build_ids(struct list_head *head,
388 struct machine *machine, const char *debugdir)
389{
390 struct dso *pos;
391 int err = 0;
392
393 dsos__for_each_with_build_id(pos, head)
394 if (dso__cache_build_id(pos, machine, debugdir))
395 err = -1;
396
397 return err;
398}
399
400static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
401{
402 int ret = __dsos__cache_build_ids(&machine->kernel_dsos.head, machine,
403 debugdir);
404 ret |= __dsos__cache_build_ids(&machine->user_dsos.head, machine,
405 debugdir);
406 return ret;
407}
408
409int perf_session__cache_build_ids(struct perf_session *session)
410{
411 struct rb_node *nd;
412 int ret;
413
414 if (no_buildid_cache)
415 return 0;
416
417 if (mkdir(buildid_dir, 0755) != 0 && errno != EEXIST)
418 return -1;
419
420 ret = machine__cache_build_ids(&session->machines.host, buildid_dir);
421
422 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
423 struct machine *pos = rb_entry(nd, struct machine, rb_node);
424 ret |= machine__cache_build_ids(pos, buildid_dir);
425 }
426 return ret ? -1 : 0;
427}
428
429static bool machine__read_build_ids(struct machine *machine, bool with_hits)
430{
431 bool ret;
432
433 ret = __dsos__read_build_ids(&machine->kernel_dsos.head, with_hits);
434 ret |= __dsos__read_build_ids(&machine->user_dsos.head, with_hits);
435 return ret;
436}
437
438bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
439{
440 struct rb_node *nd;
441 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
442
443 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
444 struct machine *pos = rb_entry(nd, struct machine, rb_node);
445 ret |= machine__read_build_ids(pos, with_hits);
446 }
447
448 return ret;
449}
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index ae392561470b..8236319514d5 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -15,4 +15,16 @@ char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event, 15int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
16 struct perf_sample *sample, struct perf_evsel *evsel, 16 struct perf_sample *sample, struct perf_evsel *evsel,
17 struct machine *machine); 17 struct machine *machine);
18
19int dsos__hit_all(struct perf_session *session);
20
21bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
22int perf_session__write_buildid_table(struct perf_session *session, int fd);
23int perf_session__cache_build_ids(struct perf_session *session);
24
25int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
26 const char *name, bool is_kallsyms, bool is_vdso);
27int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
28void disable_buildid_cache(void);
29
18#endif 30#endif
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 7b176dd02e1a..5cf9e1b5989d 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -22,6 +22,7 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
22extern int perf_default_config(const char *, const char *, void *); 22extern int perf_default_config(const char *, const char *, void *);
23extern int perf_config(config_fn_t fn, void *); 23extern int perf_config(config_fn_t fn, void *);
24extern int perf_config_int(const char *, const char *); 24extern int perf_config_int(const char *, const char *);
25extern u64 perf_config_u64(const char *, const char *);
25extern int perf_config_bool(const char *, const char *); 26extern int perf_config_bool(const char *, const char *);
26extern int config_error_nonbool(const char *); 27extern int config_error_nonbool(const char *);
27extern const char *perf_config_dirname(const char *, const char *); 28extern const char *perf_config_dirname(const char *, const char *);
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 437ee09727e6..14e7a123d43b 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -25,77 +25,176 @@
25 25
26__thread struct callchain_cursor callchain_cursor; 26__thread struct callchain_cursor callchain_cursor;
27 27
28int 28#ifdef HAVE_DWARF_UNWIND_SUPPORT
29parse_callchain_report_opt(const char *arg) 29static int get_stack_size(const char *str, unsigned long *_size)
30{ 30{
31 char *tok, *tok2;
32 char *endptr; 31 char *endptr;
32 unsigned long size;
33 unsigned long max_size = round_down(USHRT_MAX, sizeof(u64));
33 34
34 symbol_conf.use_callchain = true; 35 size = strtoul(str, &endptr, 0);
35 36
36 if (!arg) 37 do {
38 if (*endptr)
39 break;
40
41 size = round_up(size, sizeof(u64));
42 if (!size || size > max_size)
43 break;
44
45 *_size = size;
37 return 0; 46 return 0;
38 47
39 tok = strtok((char *)arg, ","); 48 } while (0);
40 if (!tok)
41 return -1;
42 49
43 /* get the output mode */ 50 pr_err("callchain: Incorrect stack dump size (max %ld): %s\n",
44 if (!strncmp(tok, "graph", strlen(arg))) { 51 max_size, str);
45 callchain_param.mode = CHAIN_GRAPH_ABS; 52 return -1;
53}
54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
46 55
47 } else if (!strncmp(tok, "flat", strlen(arg))) { 56int parse_callchain_record_opt(const char *arg)
48 callchain_param.mode = CHAIN_FLAT; 57{
49 } else if (!strncmp(tok, "fractal", strlen(arg))) { 58 char *tok, *name, *saveptr = NULL;
50 callchain_param.mode = CHAIN_GRAPH_REL; 59 char *buf;
51 } else if (!strncmp(tok, "none", strlen(arg))) { 60 int ret = -1;
52 callchain_param.mode = CHAIN_NONE; 61
53 symbol_conf.use_callchain = false; 62 /* We need buffer that we know we can write to. */
54 return 0; 63 buf = malloc(strlen(arg) + 1);
55 } else { 64 if (!buf)
56 return -1; 65 return -ENOMEM;
57 } 66
67 strcpy(buf, arg);
68
69 tok = strtok_r((char *)buf, ",", &saveptr);
70 name = tok ? : (char *)buf;
71
72 do {
73 /* Framepointer style */
74 if (!strncmp(name, "fp", sizeof("fp"))) {
75 if (!strtok_r(NULL, ",", &saveptr)) {
76 callchain_param.record_mode = CALLCHAIN_FP;
77 ret = 0;
78 } else
79 pr_err("callchain: No more arguments "
80 "needed for --call-graph fp\n");
81 break;
58 82
59 /* get the min percentage */ 83#ifdef HAVE_DWARF_UNWIND_SUPPORT
60 tok = strtok(NULL, ","); 84 /* Dwarf style */
61 if (!tok) 85 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
62 goto setup; 86 const unsigned long default_stack_dump_size = 8192;
63 87
64 callchain_param.min_percent = strtod(tok, &endptr); 88 ret = 0;
65 if (tok == endptr) 89 callchain_param.record_mode = CALLCHAIN_DWARF;
66 return -1; 90 callchain_param.dump_size = default_stack_dump_size;
91
92 tok = strtok_r(NULL, ",", &saveptr);
93 if (tok) {
94 unsigned long size = 0;
95
96 ret = get_stack_size(tok, &size);
97 callchain_param.dump_size = size;
98 }
99#endif /* HAVE_DWARF_UNWIND_SUPPORT */
100 } else {
101 pr_err("callchain: Unknown --call-graph option "
102 "value: %s\n", arg);
103 break;
104 }
67 105
68 /* get the print limit */ 106 } while (0);
69 tok2 = strtok(NULL, ",");
70 if (!tok2)
71 goto setup;
72 107
73 if (tok2[0] != 'c') { 108 free(buf);
74 callchain_param.print_limit = strtoul(tok2, &endptr, 0); 109 return ret;
75 tok2 = strtok(NULL, ","); 110}
76 if (!tok2) 111
77 goto setup; 112static int parse_callchain_mode(const char *value)
113{
114 if (!strncmp(value, "graph", strlen(value))) {
115 callchain_param.mode = CHAIN_GRAPH_ABS;
116 return 0;
117 }
118 if (!strncmp(value, "flat", strlen(value))) {
119 callchain_param.mode = CHAIN_FLAT;
120 return 0;
78 } 121 }
122 if (!strncmp(value, "fractal", strlen(value))) {
123 callchain_param.mode = CHAIN_GRAPH_REL;
124 return 0;
125 }
126 return -1;
127}
79 128
80 /* get the call chain order */ 129static int parse_callchain_order(const char *value)
81 if (!strncmp(tok2, "caller", strlen("caller"))) 130{
131 if (!strncmp(value, "caller", strlen(value))) {
82 callchain_param.order = ORDER_CALLER; 132 callchain_param.order = ORDER_CALLER;
83 else if (!strncmp(tok2, "callee", strlen("callee"))) 133 return 0;
134 }
135 if (!strncmp(value, "callee", strlen(value))) {
84 callchain_param.order = ORDER_CALLEE; 136 callchain_param.order = ORDER_CALLEE;
85 else 137 return 0;
86 return -1; 138 }
139 return -1;
140}
87 141
88 /* Get the sort key */ 142static int parse_callchain_sort_key(const char *value)
89 tok2 = strtok(NULL, ","); 143{
90 if (!tok2) 144 if (!strncmp(value, "function", strlen(value))) {
91 goto setup;
92 if (!strncmp(tok2, "function", strlen("function")))
93 callchain_param.key = CCKEY_FUNCTION; 145 callchain_param.key = CCKEY_FUNCTION;
94 else if (!strncmp(tok2, "address", strlen("address"))) 146 return 0;
147 }
148 if (!strncmp(value, "address", strlen(value))) {
95 callchain_param.key = CCKEY_ADDRESS; 149 callchain_param.key = CCKEY_ADDRESS;
96 else 150 return 0;
97 return -1; 151 }
98setup: 152 if (!strncmp(value, "branch", strlen(value))) {
153 callchain_param.branch_callstack = 1;
154 return 0;
155 }
156 return -1;
157}
158
159int
160parse_callchain_report_opt(const char *arg)
161{
162 char *tok;
163 char *endptr;
164 bool minpcnt_set = false;
165
166 symbol_conf.use_callchain = true;
167
168 if (!arg)
169 return 0;
170
171 while ((tok = strtok((char *)arg, ",")) != NULL) {
172 if (!strncmp(tok, "none", strlen(tok))) {
173 callchain_param.mode = CHAIN_NONE;
174 symbol_conf.use_callchain = false;
175 return 0;
176 }
177
178 if (!parse_callchain_mode(tok) ||
179 !parse_callchain_order(tok) ||
180 !parse_callchain_sort_key(tok)) {
181 /* parsing ok - move on to the next */
182 } else if (!minpcnt_set) {
183 /* try to get the min percent */
184 callchain_param.min_percent = strtod(tok, &endptr);
185 if (tok == endptr)
186 return -1;
187 minpcnt_set = true;
188 } else {
189 /* try print limit at last */
190 callchain_param.print_limit = strtoul(tok, &endptr, 0);
191 if (tok == endptr)
192 return -1;
193 }
194
195 arg = NULL;
196 }
197
99 if (callchain_register_param(&callchain_param) < 0) { 198 if (callchain_register_param(&callchain_param) < 0) {
100 pr_err("Can't register callchain params\n"); 199 pr_err("Can't register callchain params\n");
101 return -1; 200 return -1;
@@ -103,6 +202,47 @@ setup:
103 return 0; 202 return 0;
104} 203}
105 204
205int perf_callchain_config(const char *var, const char *value)
206{
207 char *endptr;
208
209 if (prefixcmp(var, "call-graph."))
210 return 0;
211 var += sizeof("call-graph.") - 1;
212
213 if (!strcmp(var, "record-mode"))
214 return parse_callchain_record_opt(value);
215#ifdef HAVE_DWARF_UNWIND_SUPPORT
216 if (!strcmp(var, "dump-size")) {
217 unsigned long size = 0;
218 int ret;
219
220 ret = get_stack_size(value, &size);
221 callchain_param.dump_size = size;
222
223 return ret;
224 }
225#endif
226 if (!strcmp(var, "print-type"))
227 return parse_callchain_mode(value);
228 if (!strcmp(var, "order"))
229 return parse_callchain_order(value);
230 if (!strcmp(var, "sort-key"))
231 return parse_callchain_sort_key(value);
232 if (!strcmp(var, "threshold")) {
233 callchain_param.min_percent = strtod(value, &endptr);
234 if (value == endptr)
235 return -1;
236 }
237 if (!strcmp(var, "print-limit")) {
238 callchain_param.print_limit = strtod(value, &endptr);
239 if (value == endptr)
240 return -1;
241 }
242
243 return 0;
244}
245
106static void 246static void
107rb_insert_callchain(struct rb_root *root, struct callchain_node *chain, 247rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
108 enum chain_mode mode) 248 enum chain_mode mode)
@@ -618,8 +758,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent
618 758
619 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain || 759 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
620 sort__has_parent) { 760 sort__has_parent) {
621 return machine__resolve_callchain(al->machine, evsel, al->thread, 761 return thread__resolve_callchain(al->thread, evsel, sample,
622 sample, parent, al, max_stack); 762 parent, al, max_stack);
623 } 763 }
624 return 0; 764 return 0;
625} 765}
@@ -672,3 +812,62 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
672out: 812out:
673 return 1; 813 return 1;
674} 814}
815
816char *callchain_list__sym_name(struct callchain_list *cl,
817 char *bf, size_t bfsize, bool show_dso)
818{
819 int printed;
820
821 if (cl->ms.sym) {
822 if (callchain_param.key == CCKEY_ADDRESS &&
823 cl->ms.map && !cl->srcline)
824 cl->srcline = get_srcline(cl->ms.map->dso,
825 map__rip_2objdump(cl->ms.map,
826 cl->ip),
827 cl->ms.sym, false);
828 if (cl->srcline)
829 printed = scnprintf(bf, bfsize, "%s %s",
830 cl->ms.sym->name, cl->srcline);
831 else
832 printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
833 } else
834 printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
835
836 if (show_dso)
837 scnprintf(bf + printed, bfsize - printed, " %s",
838 cl->ms.map ?
839 cl->ms.map->dso->short_name :
840 "unknown");
841
842 return bf;
843}
844
845static void free_callchain_node(struct callchain_node *node)
846{
847 struct callchain_list *list, *tmp;
848 struct callchain_node *child;
849 struct rb_node *n;
850
851 list_for_each_entry_safe(list, tmp, &node->val, list) {
852 list_del(&list->list);
853 free(list);
854 }
855
856 n = rb_first(&node->rb_root_in);
857 while (n) {
858 child = container_of(n, struct callchain_node, rb_node_in);
859 n = rb_next(n);
860 rb_erase(&child->rb_node_in, &node->rb_root_in);
861
862 free_callchain_node(child);
863 free(child);
864 }
865}
866
867void free_callchain(struct callchain_root *root)
868{
869 if (!symbol_conf.use_callchain)
870 return;
871
872 free_callchain_node(&root->node);
873}
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index da43619d6173..c0ec1acc38e4 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -54,17 +54,24 @@ enum chain_key {
54}; 54};
55 55
56struct callchain_param { 56struct callchain_param {
57 bool enabled;
58 enum perf_call_graph_mode record_mode;
59 u32 dump_size;
57 enum chain_mode mode; 60 enum chain_mode mode;
58 u32 print_limit; 61 u32 print_limit;
59 double min_percent; 62 double min_percent;
60 sort_chain_func_t sort; 63 sort_chain_func_t sort;
61 enum chain_order order; 64 enum chain_order order;
62 enum chain_key key; 65 enum chain_key key;
66 bool branch_callstack;
63}; 67};
64 68
69extern struct callchain_param callchain_param;
70
65struct callchain_list { 71struct callchain_list {
66 u64 ip; 72 u64 ip;
67 struct map_symbol ms; 73 struct map_symbol ms;
74 char *srcline;
68 struct list_head list; 75 struct list_head list;
69}; 76};
70 77
@@ -154,7 +161,6 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
154struct option; 161struct option;
155struct hist_entry; 162struct hist_entry;
156 163
157int record_parse_callchain(const char *arg, struct record_opts *opts);
158int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 164int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
159int record_callchain_opt(const struct option *opt, const char *arg, int unset); 165int record_callchain_opt(const struct option *opt, const char *arg, int unset);
160 166
@@ -166,7 +172,9 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
166 bool hide_unresolved); 172 bool hide_unresolved);
167 173
168extern const char record_callchain_help[]; 174extern const char record_callchain_help[];
175int parse_callchain_record_opt(const char *arg);
169int parse_callchain_report_opt(const char *arg); 176int parse_callchain_report_opt(const char *arg);
177int perf_callchain_config(const char *var, const char *value);
170 178
171static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, 179static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
172 struct callchain_cursor *src) 180 struct callchain_cursor *src)
@@ -178,15 +186,18 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest,
178} 186}
179 187
180#ifdef HAVE_SKIP_CALLCHAIN_IDX 188#ifdef HAVE_SKIP_CALLCHAIN_IDX
181extern int arch_skip_callchain_idx(struct machine *machine, 189extern int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain);
182 struct thread *thread, struct ip_callchain *chain);
183#else 190#else
184static inline int arch_skip_callchain_idx(struct machine *machine __maybe_unused, 191static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused,
185 struct thread *thread __maybe_unused,
186 struct ip_callchain *chain __maybe_unused) 192 struct ip_callchain *chain __maybe_unused)
187{ 193{
188 return -1; 194 return -1;
189} 195}
190#endif 196#endif
191 197
198char *callchain_list__sym_name(struct callchain_list *cl,
199 char *bf, size_t bfsize, bool show_dso);
200
201void free_callchain(struct callchain_root *root);
202
192#endif /* __PERF_CALLCHAIN_H */ 203#endif /* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index c5d05ec17220..47b78b3f0325 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,7 +1,9 @@
1#include <sched.h>
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
4#include "asm/bug.h" 5#include "asm/bug.h"
6#include "debug.h"
5 7
6static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 8static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7 9
@@ -9,15 +11,30 @@ static int perf_flag_probe(void)
9{ 11{
10 /* use 'safest' configuration as used in perf_evsel__fallback() */ 12 /* use 'safest' configuration as used in perf_evsel__fallback() */
11 struct perf_event_attr attr = { 13 struct perf_event_attr attr = {
12 .type = PERF_COUNT_SW_CPU_CLOCK, 14 .type = PERF_TYPE_SOFTWARE,
13 .config = PERF_COUNT_SW_CPU_CLOCK, 15 .config = PERF_COUNT_SW_CPU_CLOCK,
16 .exclude_kernel = 1,
14 }; 17 };
15 int fd; 18 int fd;
16 int err; 19 int err;
20 int cpu;
21 pid_t pid = -1;
22 char sbuf[STRERR_BUFSIZE];
17 23
18 /* check cloexec flag */ 24 cpu = sched_getcpu();
19 fd = sys_perf_event_open(&attr, 0, -1, -1, 25 if (cpu < 0)
20 PERF_FLAG_FD_CLOEXEC); 26 cpu = 0;
27
28 while (1) {
29 /* check cloexec flag */
30 fd = sys_perf_event_open(&attr, pid, cpu, -1,
31 PERF_FLAG_FD_CLOEXEC);
32 if (fd < 0 && pid == -1 && errno == EACCES) {
33 pid = 0;
34 continue;
35 }
36 break;
37 }
21 err = errno; 38 err = errno;
22 39
23 if (fd >= 0) { 40 if (fd >= 0) {
@@ -25,17 +42,17 @@ static int perf_flag_probe(void)
25 return 1; 42 return 1;
26 } 43 }
27 44
28 WARN_ONCE(err != EINVAL, 45 WARN_ONCE(err != EINVAL && err != EBUSY,
29 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 46 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
30 err, strerror(err)); 47 err, strerror_r(err, sbuf, sizeof(sbuf)));
31 48
32 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 49 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 50 fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
34 err = errno; 51 err = errno;
35 52
36 if (WARN_ONCE(fd < 0, 53 if (WARN_ONCE(fd < 0 && err != EBUSY,
37 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 54 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
38 err, strerror(err))) 55 err, strerror_r(err, sbuf, sizeof(sbuf))))
39 return -1; 56 return -1;
40 57
41 close(fd); 58 close(fd);
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 87b8672eb413..f4654183d391 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -335,3 +335,19 @@ int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...)
335 va_end(args); 335 va_end(args);
336 return value_color_snprintf(bf, size, fmt, percent); 336 return value_color_snprintf(bf, size, fmt, percent);
337} 337}
338
339int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...)
340{
341 va_list args;
342 int len;
343 double percent;
344 const char *color;
345
346 va_start(args, fmt);
347 len = va_arg(args, int);
348 percent = va_arg(args, double);
349 va_end(args);
350
351 color = get_percent_color(percent);
352 return color_snprintf(bf, size, color, fmt, len, percent);
353}
diff --git a/tools/perf/util/color.h b/tools/perf/util/color.h
index 7ff30a62a132..0a594b8a0c26 100644
--- a/tools/perf/util/color.h
+++ b/tools/perf/util/color.h
@@ -41,6 +41,7 @@ int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); 41int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); 42int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); 43int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_len_snprintf(char *bf, size_t size, const char *fmt, ...);
44int percent_color_fprintf(FILE *fp, const char *fmt, double percent); 45int percent_color_fprintf(FILE *fp, const char *fmt, double percent);
45const char *get_percent_color(double percent); 46const char *get_percent_color(double percent);
46 47
diff --git a/tools/perf/util/comm.c b/tools/perf/util/comm.c
index f9e777629e21..b2bb59df65e1 100644
--- a/tools/perf/util/comm.c
+++ b/tools/perf/util/comm.c
@@ -74,7 +74,7 @@ static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
74 return new; 74 return new;
75} 75}
76 76
77struct comm *comm__new(const char *str, u64 timestamp) 77struct comm *comm__new(const char *str, u64 timestamp, bool exec)
78{ 78{
79 struct comm *comm = zalloc(sizeof(*comm)); 79 struct comm *comm = zalloc(sizeof(*comm));
80 80
@@ -82,6 +82,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
82 return NULL; 82 return NULL;
83 83
84 comm->start = timestamp; 84 comm->start = timestamp;
85 comm->exec = exec;
85 86
86 comm->comm_str = comm_str__findnew(str, &comm_str_root); 87 comm->comm_str = comm_str__findnew(str, &comm_str_root);
87 if (!comm->comm_str) { 88 if (!comm->comm_str) {
@@ -94,7 +95,7 @@ struct comm *comm__new(const char *str, u64 timestamp)
94 return comm; 95 return comm;
95} 96}
96 97
97int comm__override(struct comm *comm, const char *str, u64 timestamp) 98int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
98{ 99{
99 struct comm_str *new, *old = comm->comm_str; 100 struct comm_str *new, *old = comm->comm_str;
100 101
@@ -106,6 +107,8 @@ int comm__override(struct comm *comm, const char *str, u64 timestamp)
106 comm_str__put(old); 107 comm_str__put(old);
107 comm->comm_str = new; 108 comm->comm_str = new;
108 comm->start = timestamp; 109 comm->start = timestamp;
110 if (exec)
111 comm->exec = true;
109 112
110 return 0; 113 return 0;
111} 114}
diff --git a/tools/perf/util/comm.h b/tools/perf/util/comm.h
index fac5bd51befc..71c9c39340d4 100644
--- a/tools/perf/util/comm.h
+++ b/tools/perf/util/comm.h
@@ -11,11 +11,17 @@ struct comm {
11 struct comm_str *comm_str; 11 struct comm_str *comm_str;
12 u64 start; 12 u64 start;
13 struct list_head list; 13 struct list_head list;
14 bool exec;
15 union { /* Tool specific area */
16 void *priv;
17 u64 db_id;
18 };
14}; 19};
15 20
16void comm__free(struct comm *comm); 21void comm__free(struct comm *comm);
17struct comm *comm__new(const char *str, u64 timestamp); 22struct comm *comm__new(const char *str, u64 timestamp, bool exec);
18const char *comm__str(const struct comm *comm); 23const char *comm__str(const struct comm *comm);
19int comm__override(struct comm *comm, const char *str, u64 timestamp); 24int comm__override(struct comm *comm, const char *str, u64 timestamp,
25 bool exec);
20 26
21#endif /* __PERF_COMM_H */ 27#endif /* __PERF_COMM_H */
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 1e5e2e5af6b1..e18f653cd7db 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -222,7 +222,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
222 const unsigned char *bomptr = utf8_bom; 222 const unsigned char *bomptr = utf8_bom;
223 223
224 for (;;) { 224 for (;;) {
225 int c = get_next_char(); 225 int line, c = get_next_char();
226
226 if (bomptr && *bomptr) { 227 if (bomptr && *bomptr) {
227 /* We are at the file beginning; skip UTF8-encoded BOM 228 /* We are at the file beginning; skip UTF8-encoded BOM
228 * if present. Sane editors won't put this in on their 229 * if present. Sane editors won't put this in on their
@@ -261,8 +262,16 @@ static int perf_parse_file(config_fn_t fn, void *data)
261 if (!isalpha(c)) 262 if (!isalpha(c))
262 break; 263 break;
263 var[baselen] = tolower(c); 264 var[baselen] = tolower(c);
264 if (get_value(fn, data, var, baselen+1) < 0) 265
266 /*
267 * The get_value function might or might not reach the '\n',
268 * so saving the current line number for error reporting.
269 */
270 line = config_linenr;
271 if (get_value(fn, data, var, baselen+1) < 0) {
272 config_linenr = line;
265 break; 273 break;
274 }
266 } 275 }
267 die("bad config file line %d in %s", config_linenr, config_file_name); 276 die("bad config file line %d in %s", config_linenr, config_file_name);
268} 277}
@@ -286,6 +295,21 @@ static int parse_unit_factor(const char *end, unsigned long *val)
286 return 0; 295 return 0;
287} 296}
288 297
298static int perf_parse_llong(const char *value, long long *ret)
299{
300 if (value && *value) {
301 char *end;
302 long long val = strtoll(value, &end, 0);
303 unsigned long factor = 1;
304
305 if (!parse_unit_factor(end, &factor))
306 return 0;
307 *ret = val * factor;
308 return 1;
309 }
310 return 0;
311}
312
289static int perf_parse_long(const char *value, long *ret) 313static int perf_parse_long(const char *value, long *ret)
290{ 314{
291 if (value && *value) { 315 if (value && *value) {
@@ -307,6 +331,15 @@ static void die_bad_config(const char *name)
307 die("bad config value for '%s'", name); 331 die("bad config value for '%s'", name);
308} 332}
309 333
334u64 perf_config_u64(const char *name, const char *value)
335{
336 long long ret = 0;
337
338 if (!perf_parse_llong(value, &ret))
339 die_bad_config(name);
340 return (u64) ret;
341}
342
310int perf_config_int(const char *name, const char *value) 343int perf_config_int(const char *name, const char *value)
311{ 344{
312 long ret = 0; 345 long ret = 0;
@@ -372,6 +405,9 @@ int perf_default_config(const char *var, const char *value,
372 if (!prefixcmp(var, "ui.")) 405 if (!prefixcmp(var, "ui."))
373 return perf_ui_config(var, value); 406 return perf_ui_config(var, value);
374 407
408 if (!prefixcmp(var, "call-graph."))
409 return perf_callchain_config(var, value);
410
375 /* Add other config variables here. */ 411 /* Add other config variables here. */
376 return 0; 412 return 0;
377} 413}
@@ -486,7 +522,7 @@ static int buildid_dir_command_config(const char *var, const char *value,
486 const char *v; 522 const char *v;
487 523
488 /* same dir for all commands */ 524 /* same dir for all commands */
489 if (!prefixcmp(var, "buildid.") && !strcmp(var + 8, "dir")) { 525 if (!strcmp(var, "buildid.dir")) {
490 v = perf_config_dirname(var, value); 526 v = perf_config_dirname(var, value);
491 if (!v) 527 if (!v)
492 return -1; 528 return -1;
@@ -503,12 +539,14 @@ static void check_buildid_dir_config(void)
503 perf_config(buildid_dir_command_config, &c); 539 perf_config(buildid_dir_command_config, &c);
504} 540}
505 541
506void set_buildid_dir(void) 542void set_buildid_dir(const char *dir)
507{ 543{
508 buildid_dir[0] = '\0'; 544 if (dir)
545 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
509 546
510 /* try config file */ 547 /* try config file */
511 check_buildid_dir_config(); 548 if (buildid_dir[0] == '\0')
549 check_buildid_dir_config();
512 550
513 /* default to $HOME/.debug */ 551 /* default to $HOME/.debug */
514 if (buildid_dir[0] == '\0') { 552 if (buildid_dir[0] == '\0') {
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 29d720cf5844..1921942fc2e0 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -50,12 +50,14 @@ static int open_file_read(struct perf_data_file *file)
50{ 50{
51 struct stat st; 51 struct stat st;
52 int fd; 52 int fd;
53 char sbuf[STRERR_BUFSIZE];
53 54
54 fd = open(file->path, O_RDONLY); 55 fd = open(file->path, O_RDONLY);
55 if (fd < 0) { 56 if (fd < 0) {
56 int err = errno; 57 int err = errno;
57 58
58 pr_err("failed to open %s: %s", file->path, strerror(err)); 59 pr_err("failed to open %s: %s", file->path,
60 strerror_r(err, sbuf, sizeof(sbuf)));
59 if (err == ENOENT && !strcmp(file->path, "perf.data")) 61 if (err == ENOENT && !strcmp(file->path, "perf.data"))
60 pr_err(" (try 'perf record' first)"); 62 pr_err(" (try 'perf record' first)");
61 pr_err("\n"); 63 pr_err("\n");
@@ -88,6 +90,7 @@ static int open_file_read(struct perf_data_file *file)
88static int open_file_write(struct perf_data_file *file) 90static int open_file_write(struct perf_data_file *file)
89{ 91{
90 int fd; 92 int fd;
93 char sbuf[STRERR_BUFSIZE];
91 94
92 if (check_backup(file)) 95 if (check_backup(file))
93 return -1; 96 return -1;
@@ -95,7 +98,8 @@ static int open_file_write(struct perf_data_file *file)
95 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR); 98 fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC, S_IRUSR|S_IWUSR);
96 99
97 if (fd < 0) 100 if (fd < 0)
98 pr_err("failed to open %s : %s\n", file->path, strerror(errno)); 101 pr_err("failed to open %s : %s\n", file->path,
102 strerror_r(errno, sbuf, sizeof(sbuf)));
99 103
100 return fd; 104 return fd;
101} 105}
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
new file mode 100644
index 000000000000..c81dae399763
--- /dev/null
+++ b/tools/perf/util/db-export.c
@@ -0,0 +1,428 @@
1/*
2 * db-export.c: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <errno.h>
17
18#include "evsel.h"
19#include "machine.h"
20#include "thread.h"
21#include "comm.h"
22#include "symbol.h"
23#include "event.h"
24#include "util.h"
25#include "thread-stack.h"
26#include "db-export.h"
27
28struct deferred_export {
29 struct list_head node;
30 struct comm *comm;
31};
32
33static int db_export__deferred(struct db_export *dbe)
34{
35 struct deferred_export *de;
36 int err;
37
38 while (!list_empty(&dbe->deferred)) {
39 de = list_entry(dbe->deferred.next, struct deferred_export,
40 node);
41 err = dbe->export_comm(dbe, de->comm);
42 list_del(&de->node);
43 free(de);
44 if (err)
45 return err;
46 }
47
48 return 0;
49}
50
51static void db_export__free_deferred(struct db_export *dbe)
52{
53 struct deferred_export *de;
54
55 while (!list_empty(&dbe->deferred)) {
56 de = list_entry(dbe->deferred.next, struct deferred_export,
57 node);
58 list_del(&de->node);
59 free(de);
60 }
61}
62
63static int db_export__defer_comm(struct db_export *dbe, struct comm *comm)
64{
65 struct deferred_export *de;
66
67 de = zalloc(sizeof(struct deferred_export));
68 if (!de)
69 return -ENOMEM;
70
71 de->comm = comm;
72 list_add_tail(&de->node, &dbe->deferred);
73
74 return 0;
75}
76
77int db_export__init(struct db_export *dbe)
78{
79 memset(dbe, 0, sizeof(struct db_export));
80 INIT_LIST_HEAD(&dbe->deferred);
81 return 0;
82}
83
84int db_export__flush(struct db_export *dbe)
85{
86 return db_export__deferred(dbe);
87}
88
89void db_export__exit(struct db_export *dbe)
90{
91 db_export__free_deferred(dbe);
92 call_return_processor__free(dbe->crp);
93 dbe->crp = NULL;
94}
95
96int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel)
97{
98 if (evsel->db_id)
99 return 0;
100
101 evsel->db_id = ++dbe->evsel_last_db_id;
102
103 if (dbe->export_evsel)
104 return dbe->export_evsel(dbe, evsel);
105
106 return 0;
107}
108
109int db_export__machine(struct db_export *dbe, struct machine *machine)
110{
111 if (machine->db_id)
112 return 0;
113
114 machine->db_id = ++dbe->machine_last_db_id;
115
116 if (dbe->export_machine)
117 return dbe->export_machine(dbe, machine);
118
119 return 0;
120}
121
122int db_export__thread(struct db_export *dbe, struct thread *thread,
123 struct machine *machine, struct comm *comm)
124{
125 u64 main_thread_db_id = 0;
126 int err;
127
128 if (thread->db_id)
129 return 0;
130
131 thread->db_id = ++dbe->thread_last_db_id;
132
133 if (thread->pid_ != -1) {
134 struct thread *main_thread;
135
136 if (thread->pid_ == thread->tid) {
137 main_thread = thread;
138 } else {
139 main_thread = machine__findnew_thread(machine,
140 thread->pid_,
141 thread->pid_);
142 if (!main_thread)
143 return -ENOMEM;
144 err = db_export__thread(dbe, main_thread, machine,
145 comm);
146 if (err)
147 return err;
148 if (comm) {
149 err = db_export__comm_thread(dbe, comm, thread);
150 if (err)
151 return err;
152 }
153 }
154 main_thread_db_id = main_thread->db_id;
155 }
156
157 if (dbe->export_thread)
158 return dbe->export_thread(dbe, thread, main_thread_db_id,
159 machine);
160
161 return 0;
162}
163
164int db_export__comm(struct db_export *dbe, struct comm *comm,
165 struct thread *main_thread)
166{
167 int err;
168
169 if (comm->db_id)
170 return 0;
171
172 comm->db_id = ++dbe->comm_last_db_id;
173
174 if (dbe->export_comm) {
175 if (main_thread->comm_set)
176 err = dbe->export_comm(dbe, comm);
177 else
178 err = db_export__defer_comm(dbe, comm);
179 if (err)
180 return err;
181 }
182
183 return db_export__comm_thread(dbe, comm, main_thread);
184}
185
186int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
187 struct thread *thread)
188{
189 u64 db_id;
190
191 db_id = ++dbe->comm_thread_last_db_id;
192
193 if (dbe->export_comm_thread)
194 return dbe->export_comm_thread(dbe, db_id, comm, thread);
195
196 return 0;
197}
198
199int db_export__dso(struct db_export *dbe, struct dso *dso,
200 struct machine *machine)
201{
202 if (dso->db_id)
203 return 0;
204
205 dso->db_id = ++dbe->dso_last_db_id;
206
207 if (dbe->export_dso)
208 return dbe->export_dso(dbe, dso, machine);
209
210 return 0;
211}
212
213int db_export__symbol(struct db_export *dbe, struct symbol *sym,
214 struct dso *dso)
215{
216 u64 *sym_db_id = symbol__priv(sym);
217
218 if (*sym_db_id)
219 return 0;
220
221 *sym_db_id = ++dbe->symbol_last_db_id;
222
223 if (dbe->export_symbol)
224 return dbe->export_symbol(dbe, sym, dso);
225
226 return 0;
227}
228
229static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
230{
231 if (thread->pid_ == thread->tid)
232 return thread;
233
234 if (thread->pid_ == -1)
235 return NULL;
236
237 return machine__find_thread(machine, thread->pid_, thread->pid_);
238}
239
240static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
241 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
242{
243 int err;
244
245 if (al->map) {
246 struct dso *dso = al->map->dso;
247
248 err = db_export__dso(dbe, dso, al->machine);
249 if (err)
250 return err;
251 *dso_db_id = dso->db_id;
252
253 if (!al->sym) {
254 al->sym = symbol__new(al->addr, 0, 0, "unknown");
255 if (al->sym)
256 symbols__insert(&dso->symbols[al->map->type],
257 al->sym);
258 }
259
260 if (al->sym) {
261 u64 *db_id = symbol__priv(al->sym);
262
263 err = db_export__symbol(dbe, al->sym, dso);
264 if (err)
265 return err;
266 *sym_db_id = *db_id;
267 *offset = al->addr - al->sym->start;
268 }
269 }
270
271 return 0;
272}
273
274int db_export__branch_type(struct db_export *dbe, u32 branch_type,
275 const char *name)
276{
277 if (dbe->export_branch_type)
278 return dbe->export_branch_type(dbe, branch_type, name);
279
280 return 0;
281}
282
283int db_export__sample(struct db_export *dbe, union perf_event *event,
284 struct perf_sample *sample, struct perf_evsel *evsel,
285 struct thread *thread, struct addr_location *al)
286{
287 struct export_sample es = {
288 .event = event,
289 .sample = sample,
290 .evsel = evsel,
291 .thread = thread,
292 .al = al,
293 };
294 struct thread *main_thread;
295 struct comm *comm = NULL;
296 int err;
297
298 err = db_export__evsel(dbe, evsel);
299 if (err)
300 return err;
301
302 err = db_export__machine(dbe, al->machine);
303 if (err)
304 return err;
305
306 main_thread = get_main_thread(al->machine, thread);
307 if (main_thread)
308 comm = machine__thread_exec_comm(al->machine, main_thread);
309
310 err = db_export__thread(dbe, thread, al->machine, comm);
311 if (err)
312 return err;
313
314 if (comm) {
315 err = db_export__comm(dbe, comm, main_thread);
316 if (err)
317 return err;
318 es.comm_db_id = comm->db_id;
319 }
320
321 es.db_id = ++dbe->sample_last_db_id;
322
323 err = db_ids_from_al(dbe, al, &es.dso_db_id, &es.sym_db_id, &es.offset);
324 if (err)
325 return err;
326
327 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
328 sample_addr_correlates_sym(&evsel->attr)) {
329 struct addr_location addr_al;
330
331 perf_event__preprocess_sample_addr(event, sample, thread, &addr_al);
332 err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id,
333 &es.addr_sym_db_id, &es.addr_offset);
334 if (err)
335 return err;
336 if (dbe->crp) {
337 err = thread_stack__process(thread, comm, sample, al,
338 &addr_al, es.db_id,
339 dbe->crp);
340 if (err)
341 return err;
342 }
343 }
344
345 if (dbe->export_sample)
346 return dbe->export_sample(dbe, &es);
347
348 return 0;
349}
350
351static struct {
352 u32 branch_type;
353 const char *name;
354} branch_types[] = {
355 {0, "no branch"},
356 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
357 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
358 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "conditional jump"},
359 {PERF_IP_FLAG_BRANCH, "unconditional jump"},
360 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT,
361 "software interrupt"},
362 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT,
363 "return from interrupt"},
364 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET,
365 "system call"},
366 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET,
367 "return from system call"},
368 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "asynchronous branch"},
369 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
370 PERF_IP_FLAG_INTERRUPT, "hardware interrupt"},
371 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "transaction abort"},
372 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "trace begin"},
373 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "trace end"},
374 {0, NULL}
375};
376
377int db_export__branch_types(struct db_export *dbe)
378{
379 int i, err = 0;
380
381 for (i = 0; branch_types[i].name ; i++) {
382 err = db_export__branch_type(dbe, branch_types[i].branch_type,
383 branch_types[i].name);
384 if (err)
385 break;
386 }
387 return err;
388}
389
390int db_export__call_path(struct db_export *dbe, struct call_path *cp)
391{
392 int err;
393
394 if (cp->db_id)
395 return 0;
396
397 if (cp->parent) {
398 err = db_export__call_path(dbe, cp->parent);
399 if (err)
400 return err;
401 }
402
403 cp->db_id = ++dbe->call_path_last_db_id;
404
405 if (dbe->export_call_path)
406 return dbe->export_call_path(dbe, cp);
407
408 return 0;
409}
410
411int db_export__call_return(struct db_export *dbe, struct call_return *cr)
412{
413 int err;
414
415 if (cr->db_id)
416 return 0;
417
418 err = db_export__call_path(dbe, cr->cp);
419 if (err)
420 return err;
421
422 cr->db_id = ++dbe->call_return_last_db_id;
423
424 if (dbe->export_call_return)
425 return dbe->export_call_return(dbe, cr);
426
427 return 0;
428}
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
new file mode 100644
index 000000000000..adbd22d66798
--- /dev/null
+++ b/tools/perf/util/db-export.h
@@ -0,0 +1,107 @@
1/*
2 * db-export.h: Support for exporting data suitable for import to a database
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_DB_EXPORT_H
17#define __PERF_DB_EXPORT_H
18
19#include <linux/types.h>
20#include <linux/list.h>
21
22struct perf_evsel;
23struct machine;
24struct thread;
25struct comm;
26struct dso;
27struct perf_sample;
28struct addr_location;
29struct call_return_processor;
30struct call_path;
31struct call_return;
32
33struct export_sample {
34 union perf_event *event;
35 struct perf_sample *sample;
36 struct perf_evsel *evsel;
37 struct thread *thread;
38 struct addr_location *al;
39 u64 db_id;
40 u64 comm_db_id;
41 u64 dso_db_id;
42 u64 sym_db_id;
43 u64 offset; /* ip offset from symbol start */
44 u64 addr_dso_db_id;
45 u64 addr_sym_db_id;
46 u64 addr_offset; /* addr offset from symbol start */
47};
48
49struct db_export {
50 int (*export_evsel)(struct db_export *dbe, struct perf_evsel *evsel);
51 int (*export_machine)(struct db_export *dbe, struct machine *machine);
52 int (*export_thread)(struct db_export *dbe, struct thread *thread,
53 u64 main_thread_db_id, struct machine *machine);
54 int (*export_comm)(struct db_export *dbe, struct comm *comm);
55 int (*export_comm_thread)(struct db_export *dbe, u64 db_id,
56 struct comm *comm, struct thread *thread);
57 int (*export_dso)(struct db_export *dbe, struct dso *dso,
58 struct machine *machine);
59 int (*export_symbol)(struct db_export *dbe, struct symbol *sym,
60 struct dso *dso);
61 int (*export_branch_type)(struct db_export *dbe, u32 branch_type,
62 const char *name);
63 int (*export_sample)(struct db_export *dbe, struct export_sample *es);
64 int (*export_call_path)(struct db_export *dbe, struct call_path *cp);
65 int (*export_call_return)(struct db_export *dbe,
66 struct call_return *cr);
67 struct call_return_processor *crp;
68 u64 evsel_last_db_id;
69 u64 machine_last_db_id;
70 u64 thread_last_db_id;
71 u64 comm_last_db_id;
72 u64 comm_thread_last_db_id;
73 u64 dso_last_db_id;
74 u64 symbol_last_db_id;
75 u64 sample_last_db_id;
76 u64 call_path_last_db_id;
77 u64 call_return_last_db_id;
78 struct list_head deferred;
79};
80
81int db_export__init(struct db_export *dbe);
82int db_export__flush(struct db_export *dbe);
83void db_export__exit(struct db_export *dbe);
84int db_export__evsel(struct db_export *dbe, struct perf_evsel *evsel);
85int db_export__machine(struct db_export *dbe, struct machine *machine);
86int db_export__thread(struct db_export *dbe, struct thread *thread,
87 struct machine *machine, struct comm *comm);
88int db_export__comm(struct db_export *dbe, struct comm *comm,
89 struct thread *main_thread);
90int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
91 struct thread *thread);
92int db_export__dso(struct db_export *dbe, struct dso *dso,
93 struct machine *machine);
94int db_export__symbol(struct db_export *dbe, struct symbol *sym,
95 struct dso *dso);
96int db_export__branch_type(struct db_export *dbe, u32 branch_type,
97 const char *name);
98int db_export__sample(struct db_export *dbe, union perf_event *event,
99 struct perf_sample *sample, struct perf_evsel *evsel,
100 struct thread *thread, struct addr_location *al);
101
102int db_export__branch_types(struct db_export *dbe);
103
104int db_export__call_path(struct db_export *dbe, struct call_path *cp);
105int db_export__call_return(struct db_export *dbe, struct call_return *cr);
106
107#endif
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 71d419362634..ad60b2f20258 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -13,15 +13,20 @@
13#include "util.h" 13#include "util.h"
14#include "target.h" 14#include "target.h"
15 15
16#define NSECS_PER_SEC 1000000000ULL
17#define NSECS_PER_USEC 1000ULL
18
16int verbose; 19int verbose;
17bool dump_trace = false, quiet = false; 20bool dump_trace = false, quiet = false;
21int debug_ordered_events;
22static int redirect_to_stderr;
18 23
19static int _eprintf(int level, int var, const char *fmt, va_list args) 24static int _eprintf(int level, int var, const char *fmt, va_list args)
20{ 25{
21 int ret = 0; 26 int ret = 0;
22 27
23 if (var >= level) { 28 if (var >= level) {
24 if (use_browser >= 1) 29 if (use_browser >= 1 && !redirect_to_stderr)
25 ui_helpline__vshow(fmt, args); 30 ui_helpline__vshow(fmt, args);
26 else 31 else
27 ret = vfprintf(stderr, fmt, args); 32 ret = vfprintf(stderr, fmt, args);
@@ -42,6 +47,35 @@ int eprintf(int level, int var, const char *fmt, ...)
42 return ret; 47 return ret;
43} 48}
44 49
50static int __eprintf_time(u64 t, const char *fmt, va_list args)
51{
52 int ret = 0;
53 u64 secs, usecs, nsecs = t;
54
55 secs = nsecs / NSECS_PER_SEC;
56 nsecs -= secs * NSECS_PER_SEC;
57 usecs = nsecs / NSECS_PER_USEC;
58
59 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
60 secs, usecs);
61 ret += vfprintf(stderr, fmt, args);
62 return ret;
63}
64
65int eprintf_time(int level, int var, u64 t, const char *fmt, ...)
66{
67 int ret = 0;
68 va_list args;
69
70 if (var >= level) {
71 va_start(args, fmt);
72 ret = __eprintf_time(t, fmt, args);
73 va_end(args);
74 }
75
76 return ret;
77}
78
45/* 79/*
46 * Overloading libtraceevent standard info print 80 * Overloading libtraceevent standard info print
47 * function, display with -v in perf. 81 * function, display with -v in perf.
@@ -110,7 +144,9 @@ static struct debug_variable {
110 const char *name; 144 const char *name;
111 int *ptr; 145 int *ptr;
112} debug_variables[] = { 146} debug_variables[] = {
113 { .name = "verbose", .ptr = &verbose }, 147 { .name = "verbose", .ptr = &verbose },
148 { .name = "ordered-events", .ptr = &debug_ordered_events},
149 { .name = "stderr", .ptr = &redirect_to_stderr},
114 { .name = NULL, } 150 { .name = NULL, }
115}; 151};
116 152
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 89fb6b0f7ab2..be264d6f3b30 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -3,6 +3,7 @@
3#define __PERF_DEBUG_H 3#define __PERF_DEBUG_H
4 4
5#include <stdbool.h> 5#include <stdbool.h>
6#include <string.h>
6#include "event.h" 7#include "event.h"
7#include "../ui/helpline.h" 8#include "../ui/helpline.h"
8#include "../ui/progress.h" 9#include "../ui/progress.h"
@@ -10,6 +11,7 @@
10 11
11extern int verbose; 12extern int verbose;
12extern bool quiet, dump_trace; 13extern bool quiet, dump_trace;
14extern int debug_ordered_events;
13 15
14#ifndef pr_fmt 16#ifndef pr_fmt
15#define pr_fmt(fmt) fmt 17#define pr_fmt(fmt) fmt
@@ -29,6 +31,14 @@ extern bool quiet, dump_trace;
29#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__) 31#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
30#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__) 32#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
31 33
34#define pr_time_N(n, var, t, fmt, ...) \
35 eprintf_time(n, var, t, fmt, ##__VA_ARGS__)
36
37#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
38#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
39
40#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
41
32int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 42int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
33void trace_event(union perf_event *event); 43void trace_event(union perf_event *event);
34 44
@@ -38,6 +48,7 @@ int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
38void pr_stat(const char *fmt, ...); 48void pr_stat(const char *fmt, ...);
39 49
40int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4))); 50int eprintf(int level, int var, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
51int eprintf_time(int level, int var, u64 t, const char *fmt, ...) __attribute__((format(printf, 4, 5)));
41 52
42int perf_debug_option(const char *str); 53int perf_debug_option(const char *str);
43 54
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 90d02c661dd4..45be944d450a 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -21,8 +21,10 @@ char dso__symtab_origin(const struct dso *dso)
21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b', 21 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd', 22 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K', 23 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
24 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm',
24 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g', 25 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
25 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G', 26 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
27 [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M',
26 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V', 28 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
27 }; 29 };
28 30
@@ -37,6 +39,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
37{ 39{
38 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 40 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
39 int ret = 0; 41 int ret = 0;
42 size_t len;
40 43
41 switch (type) { 44 switch (type) {
42 case DSO_BINARY_TYPE__DEBUGLINK: { 45 case DSO_BINARY_TYPE__DEBUGLINK: {
@@ -60,26 +63,25 @@ int dso__read_binary_type_filename(const struct dso *dso,
60 break; 63 break;
61 64
62 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO: 65 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
63 snprintf(filename, size, "%s/usr/lib/debug%s.debug", 66 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
64 symbol_conf.symfs, dso->long_name); 67 snprintf(filename + len, size - len, "%s.debug", dso->long_name);
65 break; 68 break;
66 69
67 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO: 70 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
68 snprintf(filename, size, "%s/usr/lib/debug%s", 71 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
69 symbol_conf.symfs, dso->long_name); 72 snprintf(filename + len, size - len, "%s", dso->long_name);
70 break; 73 break;
71 74
72 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO: 75 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
73 { 76 {
74 const char *last_slash; 77 const char *last_slash;
75 size_t len;
76 size_t dir_size; 78 size_t dir_size;
77 79
78 last_slash = dso->long_name + dso->long_name_len; 80 last_slash = dso->long_name + dso->long_name_len;
79 while (last_slash != dso->long_name && *last_slash != '/') 81 while (last_slash != dso->long_name && *last_slash != '/')
80 last_slash--; 82 last_slash--;
81 83
82 len = scnprintf(filename, size, "%s", symbol_conf.symfs); 84 len = __symbol__join_symfs(filename, size, "");
83 dir_size = last_slash - dso->long_name + 2; 85 dir_size = last_slash - dso->long_name + 2;
84 if (dir_size > (size - len)) { 86 if (dir_size > (size - len)) {
85 ret = -1; 87 ret = -1;
@@ -100,26 +102,26 @@ int dso__read_binary_type_filename(const struct dso *dso,
100 build_id__sprintf(dso->build_id, 102 build_id__sprintf(dso->build_id,
101 sizeof(dso->build_id), 103 sizeof(dso->build_id),
102 build_id_hex); 104 build_id_hex);
103 snprintf(filename, size, 105 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
104 "%s/usr/lib/debug/.build-id/%.2s/%s.debug", 106 snprintf(filename + len, size - len, "%.2s/%s.debug",
105 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 107 build_id_hex, build_id_hex + 2);
106 break; 108 break;
107 109
108 case DSO_BINARY_TYPE__VMLINUX: 110 case DSO_BINARY_TYPE__VMLINUX:
109 case DSO_BINARY_TYPE__GUEST_VMLINUX: 111 case DSO_BINARY_TYPE__GUEST_VMLINUX:
110 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 112 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
111 snprintf(filename, size, "%s%s", 113 __symbol__join_symfs(filename, size, dso->long_name);
112 symbol_conf.symfs, dso->long_name);
113 break; 114 break;
114 115
115 case DSO_BINARY_TYPE__GUEST_KMODULE: 116 case DSO_BINARY_TYPE__GUEST_KMODULE:
116 snprintf(filename, size, "%s%s%s", symbol_conf.symfs, 117 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
117 root_dir, dso->long_name); 118 path__join3(filename, size, symbol_conf.symfs,
119 root_dir, dso->long_name);
118 break; 120 break;
119 121
120 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 122 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
121 snprintf(filename, size, "%s%s", symbol_conf.symfs, 123 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
122 dso->long_name); 124 __symbol__join_symfs(filename, size, dso->long_name);
123 break; 125 break;
124 126
125 case DSO_BINARY_TYPE__KCORE: 127 case DSO_BINARY_TYPE__KCORE:
@@ -139,6 +141,73 @@ int dso__read_binary_type_filename(const struct dso *dso,
139 return ret; 141 return ret;
140} 142}
141 143
144static const struct {
145 const char *fmt;
146 int (*decompress)(const char *input, int output);
147} compressions[] = {
148#ifdef HAVE_ZLIB_SUPPORT
149 { "gz", gzip_decompress_to_file },
150#endif
151 { NULL, NULL },
152};
153
154bool is_supported_compression(const char *ext)
155{
156 unsigned i;
157
158 for (i = 0; compressions[i].fmt; i++) {
159 if (!strcmp(ext, compressions[i].fmt))
160 return true;
161 }
162 return false;
163}
164
165bool is_kmodule_extension(const char *ext)
166{
167 if (strncmp(ext, "ko", 2))
168 return false;
169
170 if (ext[2] == '\0' || (ext[2] == '.' && is_supported_compression(ext+3)))
171 return true;
172
173 return false;
174}
175
176bool is_kernel_module(const char *pathname, bool *compressed)
177{
178 const char *ext = strrchr(pathname, '.');
179
180 if (ext == NULL)
181 return false;
182
183 if (is_supported_compression(ext + 1)) {
184 if (compressed)
185 *compressed = true;
186 ext -= 3;
187 } else if (compressed)
188 *compressed = false;
189
190 return is_kmodule_extension(ext + 1);
191}
192
193bool decompress_to_file(const char *ext, const char *filename, int output_fd)
194{
195 unsigned i;
196
197 for (i = 0; compressions[i].fmt; i++) {
198 if (!strcmp(ext, compressions[i].fmt))
199 return !compressions[i].decompress(filename,
200 output_fd);
201 }
202 return false;
203}
204
205bool dso__needs_decompress(struct dso *dso)
206{
207 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
208 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
209}
210
142/* 211/*
143 * Global list of open DSOs and the counter. 212 * Global list of open DSOs and the counter.
144 */ 213 */
@@ -164,13 +233,15 @@ static void close_first_dso(void);
164static int do_open(char *name) 233static int do_open(char *name)
165{ 234{
166 int fd; 235 int fd;
236 char sbuf[STRERR_BUFSIZE];
167 237
168 do { 238 do {
169 fd = open(name, O_RDONLY); 239 fd = open(name, O_RDONLY);
170 if (fd >= 0) 240 if (fd >= 0)
171 return fd; 241 return fd;
172 242
173 pr_debug("dso open failed, mmap: %s\n", strerror(errno)); 243 pr_debug("dso open failed, mmap: %s\n",
244 strerror_r(errno, sbuf, sizeof(sbuf)));
174 if (!dso__data_open_cnt || errno != EMFILE) 245 if (!dso__data_open_cnt || errno != EMFILE)
175 break; 246 break;
176 247
@@ -532,10 +603,12 @@ static ssize_t cached_read(struct dso *dso, u64 offset, u8 *data, ssize_t size)
532static int data_file_size(struct dso *dso) 603static int data_file_size(struct dso *dso)
533{ 604{
534 struct stat st; 605 struct stat st;
606 char sbuf[STRERR_BUFSIZE];
535 607
536 if (!dso->data.file_size) { 608 if (!dso->data.file_size) {
537 if (fstat(dso->data.fd, &st)) { 609 if (fstat(dso->data.fd, &st)) {
538 pr_err("dso mmap failed, fstat: %s\n", strerror(errno)); 610 pr_err("dso mmap failed, fstat: %s\n",
611 strerror_r(errno, sbuf, sizeof(sbuf)));
539 return -1; 612 return -1;
540 } 613 }
541 dso->data.file_size = st.st_size; 614 dso->data.file_size = st.st_size;
@@ -651,6 +724,65 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
651 return dso; 724 return dso;
652} 725}
653 726
727/*
728 * Find a matching entry and/or link current entry to RB tree.
729 * Either one of the dso or name parameter must be non-NULL or the
730 * function will not work.
731 */
732static struct dso *dso__findlink_by_longname(struct rb_root *root,
733 struct dso *dso, const char *name)
734{
735 struct rb_node **p = &root->rb_node;
736 struct rb_node *parent = NULL;
737
738 if (!name)
739 name = dso->long_name;
740 /*
741 * Find node with the matching name
742 */
743 while (*p) {
744 struct dso *this = rb_entry(*p, struct dso, rb_node);
745 int rc = strcmp(name, this->long_name);
746
747 parent = *p;
748 if (rc == 0) {
749 /*
750 * In case the new DSO is a duplicate of an existing
751 * one, print an one-time warning & put the new entry
752 * at the end of the list of duplicates.
753 */
754 if (!dso || (dso == this))
755 return this; /* Find matching dso */
756 /*
757 * The core kernel DSOs may have duplicated long name.
758 * In this case, the short name should be different.
759 * Comparing the short names to differentiate the DSOs.
760 */
761 rc = strcmp(dso->short_name, this->short_name);
762 if (rc == 0) {
763 pr_err("Duplicated dso name: %s\n", name);
764 return NULL;
765 }
766 }
767 if (rc < 0)
768 p = &parent->rb_left;
769 else
770 p = &parent->rb_right;
771 }
772 if (dso) {
773 /* Add new node and rebalance tree */
774 rb_link_node(&dso->rb_node, parent, p);
775 rb_insert_color(&dso->rb_node, root);
776 }
777 return NULL;
778}
779
780static inline struct dso *
781dso__find_by_longname(const struct rb_root *root, const char *name)
782{
783 return dso__findlink_by_longname((struct rb_root *)root, NULL, name);
784}
785
654void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 786void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
655{ 787{
656 if (name == NULL) 788 if (name == NULL)
@@ -753,6 +885,7 @@ struct dso *dso__new(const char *name)
753 dso->a2l_fails = 1; 885 dso->a2l_fails = 1;
754 dso->kernel = DSO_TYPE_USER; 886 dso->kernel = DSO_TYPE_USER;
755 dso->needs_swap = DSO_SWAP__UNSET; 887 dso->needs_swap = DSO_SWAP__UNSET;
888 RB_CLEAR_NODE(&dso->rb_node);
756 INIT_LIST_HEAD(&dso->node); 889 INIT_LIST_HEAD(&dso->node);
757 INIT_LIST_HEAD(&dso->data.open_entry); 890 INIT_LIST_HEAD(&dso->data.open_entry);
758 } 891 }
@@ -763,6 +896,10 @@ struct dso *dso__new(const char *name)
763void dso__delete(struct dso *dso) 896void dso__delete(struct dso *dso)
764{ 897{
765 int i; 898 int i;
899
900 if (!RB_EMPTY_NODE(&dso->rb_node))
901 pr_err("DSO %s is still in rbtree when being deleted!\n",
902 dso->long_name);
766 for (i = 0; i < MAP__NR_TYPES; ++i) 903 for (i = 0; i < MAP__NR_TYPES; ++i)
767 symbols__delete(&dso->symbols[i]); 904 symbols__delete(&dso->symbols[i]);
768 905
@@ -849,35 +986,34 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
849 return have_build_id; 986 return have_build_id;
850} 987}
851 988
852void dsos__add(struct list_head *head, struct dso *dso) 989void dsos__add(struct dsos *dsos, struct dso *dso)
853{ 990{
854 list_add_tail(&dso->node, head); 991 list_add_tail(&dso->node, &dsos->head);
992 dso__findlink_by_longname(&dsos->root, dso, NULL);
855} 993}
856 994
857struct dso *dsos__find(const struct list_head *head, const char *name, bool cmp_short) 995struct dso *dsos__find(const struct dsos *dsos, const char *name,
996 bool cmp_short)
858{ 997{
859 struct dso *pos; 998 struct dso *pos;
860 999
861 if (cmp_short) { 1000 if (cmp_short) {
862 list_for_each_entry(pos, head, node) 1001 list_for_each_entry(pos, &dsos->head, node)
863 if (strcmp(pos->short_name, name) == 0) 1002 if (strcmp(pos->short_name, name) == 0)
864 return pos; 1003 return pos;
865 return NULL; 1004 return NULL;
866 } 1005 }
867 list_for_each_entry(pos, head, node) 1006 return dso__find_by_longname(&dsos->root, name);
868 if (strcmp(pos->long_name, name) == 0)
869 return pos;
870 return NULL;
871} 1007}
872 1008
873struct dso *__dsos__findnew(struct list_head *head, const char *name) 1009struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
874{ 1010{
875 struct dso *dso = dsos__find(head, name, false); 1011 struct dso *dso = dsos__find(dsos, name, false);
876 1012
877 if (!dso) { 1013 if (!dso) {
878 dso = dso__new(name); 1014 dso = dso__new(name);
879 if (dso != NULL) { 1015 if (dso != NULL) {
880 dsos__add(head, dso); 1016 dsos__add(dsos, dso);
881 dso__set_basename(dso); 1017 dso__set_basename(dso);
882 } 1018 }
883 } 1019 }
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 5e463c0964d4..3782c82c6e44 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -22,7 +22,9 @@ enum dso_binary_type {
22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 22 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 23 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
24 DSO_BINARY_TYPE__GUEST_KMODULE, 24 DSO_BINARY_TYPE__GUEST_KMODULE,
25 DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
25 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 26 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
27 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
26 DSO_BINARY_TYPE__KCORE, 28 DSO_BINARY_TYPE__KCORE,
27 DSO_BINARY_TYPE__GUEST_KCORE, 29 DSO_BINARY_TYPE__GUEST_KCORE,
28 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 30 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
@@ -90,8 +92,18 @@ struct dso_cache {
90 char data[0]; 92 char data[0];
91}; 93};
92 94
95/*
96 * DSOs are put into both a list for fast iteration and rbtree for fast
97 * long name lookup.
98 */
99struct dsos {
100 struct list_head head;
101 struct rb_root root; /* rbtree root sorted by long name */
102};
103
93struct dso { 104struct dso {
94 struct list_head node; 105 struct list_head node;
106 struct rb_node rb_node; /* rbtree node sorted by long name */
95 struct rb_root symbols[MAP__NR_TYPES]; 107 struct rb_root symbols[MAP__NR_TYPES];
96 struct rb_root symbol_names[MAP__NR_TYPES]; 108 struct rb_root symbol_names[MAP__NR_TYPES];
97 void *a2l; 109 void *a2l;
@@ -117,6 +129,7 @@ struct dso {
117 const char *long_name; 129 const char *long_name;
118 u16 long_name_len; 130 u16 long_name_len;
119 u16 short_name_len; 131 u16 short_name_len;
132 void *dwfl; /* DWARF debug info */
120 133
121 /* dso data file */ 134 /* dso data file */
122 struct { 135 struct {
@@ -128,6 +141,11 @@ struct dso {
128 struct list_head open_entry; 141 struct list_head open_entry;
129 } data; 142 } data;
130 143
144 union { /* Tool specific area */
145 void *priv;
146 u64 db_id;
147 };
148
131 char name[0]; 149 char name[0];
132}; 150};
133 151
@@ -169,6 +187,11 @@ int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
169char dso__symtab_origin(const struct dso *dso); 187char dso__symtab_origin(const struct dso *dso);
170int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type, 188int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type type,
171 char *root_dir, char *filename, size_t size); 189 char *root_dir, char *filename, size_t size);
190bool is_supported_compression(const char *ext);
191bool is_kmodule_extension(const char *ext);
192bool is_kernel_module(const char *pathname, bool *compressed);
193bool decompress_to_file(const char *ext, const char *filename, int output_fd);
194bool dso__needs_decompress(struct dso *dso);
172 195
173/* 196/*
174 * The dso__data_* external interface provides following functions: 197 * The dso__data_* external interface provides following functions:
@@ -224,10 +247,10 @@ struct map *dso__new_map(const char *name);
224struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 247struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
225 const char *short_name, int dso_type); 248 const char *short_name, int dso_type);
226 249
227void dsos__add(struct list_head *head, struct dso *dso); 250void dsos__add(struct dsos *dsos, struct dso *dso);
228struct dso *dsos__find(const struct list_head *head, const char *name, 251struct dso *dsos__find(const struct dsos *dsos, const char *name,
229 bool cmp_short); 252 bool cmp_short);
230struct dso *__dsos__findnew(struct list_head *head, const char *name); 253struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
231bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 254bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
232 255
233size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 256size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 1398c83d896d..6c6d044e959a 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -28,6 +28,7 @@ static const char *perf_event__names[] = {
28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", 28 [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", 29 [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", 30 [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
31 [PERF_RECORD_ID_INDEX] = "ID_INDEX",
31}; 32};
32 33
33const char *perf_event__name(unsigned int id) 34const char *perf_event__name(unsigned int id)
@@ -558,13 +559,17 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
558 struct map *map; 559 struct map *map;
559 struct kmap *kmap; 560 struct kmap *kmap;
560 int err; 561 int err;
562 union perf_event *event;
563
564 if (machine->vmlinux_maps[0] == NULL)
565 return -1;
566
561 /* 567 /*
562 * We should get this from /sys/kernel/sections/.text, but till that is 568 * We should get this from /sys/kernel/sections/.text, but till that is
563 * available use this, and after it is use this as a fallback for older 569 * available use this, and after it is use this as a fallback for older
564 * kernels. 570 * kernels.
565 */ 571 */
566 union perf_event *event = zalloc((sizeof(event->mmap) + 572 event = zalloc((sizeof(event->mmap) + machine->id_hdr_size));
567 machine->id_hdr_size));
568 if (event == NULL) { 573 if (event == NULL) {
569 pr_debug("Not enough memory synthesizing mmap event " 574 pr_debug("Not enough memory synthesizing mmap event "
570 "for kernel modules\n"); 575 "for kernel modules\n");
@@ -726,12 +731,12 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
726 return machine__process_event(machine, event, sample); 731 return machine__process_event(machine, event, sample);
727} 732}
728 733
729void thread__find_addr_map(struct thread *thread, 734void thread__find_addr_map(struct thread *thread, u8 cpumode,
730 struct machine *machine, u8 cpumode,
731 enum map_type type, u64 addr, 735 enum map_type type, u64 addr,
732 struct addr_location *al) 736 struct addr_location *al)
733{ 737{
734 struct map_groups *mg = thread->mg; 738 struct map_groups *mg = thread->mg;
739 struct machine *machine = mg->machine;
735 bool load_map = false; 740 bool load_map = false;
736 741
737 al->machine = machine; 742 al->machine = machine;
@@ -784,9 +789,9 @@ try_again:
784 * "[vdso]" dso, but for now lets use the old trick of looking 789 * "[vdso]" dso, but for now lets use the old trick of looking
785 * in the whole kernel symbol list. 790 * in the whole kernel symbol list.
786 */ 791 */
787 if ((long long)al->addr < 0 && 792 if (cpumode == PERF_RECORD_MISC_USER && machine &&
788 cpumode == PERF_RECORD_MISC_USER && 793 mg != &machine->kmaps &&
789 machine && mg != &machine->kmaps) { 794 machine__kernel_ip(machine, al->addr)) {
790 mg = &machine->kmaps; 795 mg = &machine->kmaps;
791 load_map = true; 796 load_map = true;
792 goto try_again; 797 goto try_again;
@@ -802,14 +807,14 @@ try_again:
802 } 807 }
803} 808}
804 809
805void thread__find_addr_location(struct thread *thread, struct machine *machine, 810void thread__find_addr_location(struct thread *thread,
806 u8 cpumode, enum map_type type, u64 addr, 811 u8 cpumode, enum map_type type, u64 addr,
807 struct addr_location *al) 812 struct addr_location *al)
808{ 813{
809 thread__find_addr_map(thread, machine, cpumode, type, addr, al); 814 thread__find_addr_map(thread, cpumode, type, addr, al);
810 if (al->map != NULL) 815 if (al->map != NULL)
811 al->sym = map__find_symbol(al->map, al->addr, 816 al->sym = map__find_symbol(al->map, al->addr,
812 machine->symbol_filter); 817 thread->mg->machine->symbol_filter);
813 else 818 else
814 al->sym = NULL; 819 al->sym = NULL;
815} 820}
@@ -838,8 +843,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
838 machine->vmlinux_maps[MAP__FUNCTION] == NULL) 843 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
839 machine__create_kernel_maps(machine); 844 machine__create_kernel_maps(machine);
840 845
841 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 846 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al);
842 sample->ip, al);
843 dump_printf(" ...... dso: %s\n", 847 dump_printf(" ...... dso: %s\n",
844 al->map ? al->map->dso->long_name : 848 al->map ? al->map->dso->long_name :
845 al->level == 'H' ? "[hypervisor]" : "<not found>"); 849 al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -898,16 +902,14 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr)
898 902
899void perf_event__preprocess_sample_addr(union perf_event *event, 903void perf_event__preprocess_sample_addr(union perf_event *event,
900 struct perf_sample *sample, 904 struct perf_sample *sample,
901 struct machine *machine,
902 struct thread *thread, 905 struct thread *thread,
903 struct addr_location *al) 906 struct addr_location *al)
904{ 907{
905 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 908 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
906 909
907 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 910 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al);
908 sample->addr, al);
909 if (!al->map) 911 if (!al->map)
910 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, 912 thread__find_addr_map(thread, cpumode, MAP__VARIABLE,
911 sample->addr, al); 913 sample->addr, al);
912 914
913 al->cpu = sample->cpu; 915 al->cpu = sample->cpu;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 94d6976180da..c4ffe2bd0738 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -143,6 +143,32 @@ struct branch_stack {
143 struct branch_entry entries[0]; 143 struct branch_entry entries[0];
144}; 144};
145 145
146enum {
147 PERF_IP_FLAG_BRANCH = 1ULL << 0,
148 PERF_IP_FLAG_CALL = 1ULL << 1,
149 PERF_IP_FLAG_RETURN = 1ULL << 2,
150 PERF_IP_FLAG_CONDITIONAL = 1ULL << 3,
151 PERF_IP_FLAG_SYSCALLRET = 1ULL << 4,
152 PERF_IP_FLAG_ASYNC = 1ULL << 5,
153 PERF_IP_FLAG_INTERRUPT = 1ULL << 6,
154 PERF_IP_FLAG_TX_ABORT = 1ULL << 7,
155 PERF_IP_FLAG_TRACE_BEGIN = 1ULL << 8,
156 PERF_IP_FLAG_TRACE_END = 1ULL << 9,
157 PERF_IP_FLAG_IN_TX = 1ULL << 10,
158};
159
160#define PERF_BRANCH_MASK (\
161 PERF_IP_FLAG_BRANCH |\
162 PERF_IP_FLAG_CALL |\
163 PERF_IP_FLAG_RETURN |\
164 PERF_IP_FLAG_CONDITIONAL |\
165 PERF_IP_FLAG_SYSCALLRET |\
166 PERF_IP_FLAG_ASYNC |\
167 PERF_IP_FLAG_INTERRUPT |\
168 PERF_IP_FLAG_TX_ABORT |\
169 PERF_IP_FLAG_TRACE_BEGIN |\
170 PERF_IP_FLAG_TRACE_END)
171
146struct perf_sample { 172struct perf_sample {
147 u64 ip; 173 u64 ip;
148 u32 pid, tid; 174 u32 pid, tid;
@@ -156,10 +182,13 @@ struct perf_sample {
156 u32 cpu; 182 u32 cpu;
157 u32 raw_size; 183 u32 raw_size;
158 u64 data_src; 184 u64 data_src;
185 u32 flags;
186 u16 insn_len;
159 void *raw_data; 187 void *raw_data;
160 struct ip_callchain *callchain; 188 struct ip_callchain *callchain;
161 struct branch_stack *branch_stack; 189 struct branch_stack *branch_stack;
162 struct regs_dump user_regs; 190 struct regs_dump user_regs;
191 struct regs_dump intr_regs;
163 struct stack_dump user_stack; 192 struct stack_dump user_stack;
164 struct sample_read read; 193 struct sample_read read;
165}; 194};
@@ -185,9 +214,37 @@ enum perf_user_event_type { /* above any possible kernel type */
185 PERF_RECORD_HEADER_TRACING_DATA = 66, 214 PERF_RECORD_HEADER_TRACING_DATA = 66,
186 PERF_RECORD_HEADER_BUILD_ID = 67, 215 PERF_RECORD_HEADER_BUILD_ID = 67,
187 PERF_RECORD_FINISHED_ROUND = 68, 216 PERF_RECORD_FINISHED_ROUND = 68,
217 PERF_RECORD_ID_INDEX = 69,
188 PERF_RECORD_HEADER_MAX 218 PERF_RECORD_HEADER_MAX
189}; 219};
190 220
221/*
222 * The kernel collects the number of events it couldn't send in a stretch and
223 * when possible sends this number in a PERF_RECORD_LOST event. The number of
224 * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
225 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
226 * the sum of all struct lost_event.lost fields reported.
227 *
228 * The total_period is needed because by default auto-freq is used, so
229 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
230 * the total number of low level events, it is necessary to to sum all struct
231 * sample_event.period and stash the result in total_period.
232 */
233struct events_stats {
234 u64 total_period;
235 u64 total_non_filtered_period;
236 u64 total_lost;
237 u64 total_invalid_chains;
238 u32 nr_events[PERF_RECORD_HEADER_MAX];
239 u32 nr_non_filtered_samples;
240 u32 nr_lost_warned;
241 u32 nr_unknown_events;
242 u32 nr_invalid_chains;
243 u32 nr_unknown_id;
244 u32 nr_unprocessable_samples;
245 u32 nr_unordered_events;
246};
247
191struct attr_event { 248struct attr_event {
192 struct perf_event_header header; 249 struct perf_event_header header;
193 struct perf_event_attr attr; 250 struct perf_event_attr attr;
@@ -211,6 +268,19 @@ struct tracing_data_event {
211 u32 size; 268 u32 size;
212}; 269};
213 270
271struct id_index_entry {
272 u64 id;
273 u64 idx;
274 u64 cpu;
275 u64 tid;
276};
277
278struct id_index_event {
279 struct perf_event_header header;
280 u64 nr;
281 struct id_index_entry entries[0];
282};
283
214union perf_event { 284union perf_event {
215 struct perf_event_header header; 285 struct perf_event_header header;
216 struct mmap_event mmap; 286 struct mmap_event mmap;
@@ -225,6 +295,7 @@ union perf_event {
225 struct event_type_event event_type; 295 struct event_type_event event_type;
226 struct tracing_data_event tracing_data; 296 struct tracing_data_event tracing_data;
227 struct build_id_event build_id; 297 struct build_id_event build_id;
298 struct id_index_event id_index;
228}; 299};
229 300
230void perf_event__print_totals(void); 301void perf_event__print_totals(void);
@@ -294,7 +365,6 @@ bool is_bts_event(struct perf_event_attr *attr);
294bool sample_addr_correlates_sym(struct perf_event_attr *attr); 365bool sample_addr_correlates_sym(struct perf_event_attr *attr);
295void perf_event__preprocess_sample_addr(union perf_event *event, 366void perf_event__preprocess_sample_addr(union perf_event *event,
296 struct perf_sample *sample, 367 struct perf_sample *sample,
297 struct machine *machine,
298 struct thread *thread, 368 struct thread *thread,
299 struct addr_location *al); 369 struct addr_location *al);
300 370
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 814e954c1318..cbab1fb77b1d 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -8,6 +8,7 @@
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include <api/fs/debugfs.h> 10#include <api/fs/debugfs.h>
11#include <api/fs/fs.h>
11#include <poll.h> 12#include <poll.h>
12#include "cpumap.h" 13#include "cpumap.h"
13#include "thread_map.h" 14#include "thread_map.h"
@@ -24,6 +25,10 @@
24 25
25#include <linux/bitops.h> 26#include <linux/bitops.h>
26#include <linux/hash.h> 27#include <linux/hash.h>
28#include <linux/log2.h>
29
30static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx);
31static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx);
27 32
28#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 33#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
29#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 34#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
@@ -37,6 +42,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
37 INIT_HLIST_HEAD(&evlist->heads[i]); 42 INIT_HLIST_HEAD(&evlist->heads[i]);
38 INIT_LIST_HEAD(&evlist->entries); 43 INIT_LIST_HEAD(&evlist->entries);
39 perf_evlist__set_maps(evlist, cpus, threads); 44 perf_evlist__set_maps(evlist, cpus, threads);
45 fdarray__init(&evlist->pollfd, 64);
40 evlist->workload.pid = -1; 46 evlist->workload.pid = -1;
41} 47}
42 48
@@ -102,7 +108,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
102void perf_evlist__exit(struct perf_evlist *evlist) 108void perf_evlist__exit(struct perf_evlist *evlist)
103{ 109{
104 zfree(&evlist->mmap); 110 zfree(&evlist->mmap);
105 zfree(&evlist->pollfd); 111 fdarray__exit(&evlist->pollfd);
106} 112}
107 113
108void perf_evlist__delete(struct perf_evlist *evlist) 114void perf_evlist__delete(struct perf_evlist *evlist)
@@ -122,6 +128,7 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
122{ 128{
123 list_add_tail(&entry->node, &evlist->entries); 129 list_add_tail(&entry->node, &evlist->entries);
124 entry->idx = evlist->nr_entries; 130 entry->idx = evlist->nr_entries;
131 entry->tracking = !entry->idx;
125 132
126 if (!evlist->nr_entries++) 133 if (!evlist->nr_entries++)
127 perf_evlist__set_id_pos(evlist); 134 perf_evlist__set_id_pos(evlist);
@@ -265,17 +272,27 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
265 return 0; 272 return 0;
266} 273}
267 274
275static int perf_evlist__nr_threads(struct perf_evlist *evlist,
276 struct perf_evsel *evsel)
277{
278 if (evsel->system_wide)
279 return 1;
280 else
281 return thread_map__nr(evlist->threads);
282}
283
268void perf_evlist__disable(struct perf_evlist *evlist) 284void perf_evlist__disable(struct perf_evlist *evlist)
269{ 285{
270 int cpu, thread; 286 int cpu, thread;
271 struct perf_evsel *pos; 287 struct perf_evsel *pos;
272 int nr_cpus = cpu_map__nr(evlist->cpus); 288 int nr_cpus = cpu_map__nr(evlist->cpus);
273 int nr_threads = thread_map__nr(evlist->threads); 289 int nr_threads;
274 290
275 for (cpu = 0; cpu < nr_cpus; cpu++) { 291 for (cpu = 0; cpu < nr_cpus; cpu++) {
276 evlist__for_each(evlist, pos) { 292 evlist__for_each(evlist, pos) {
277 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 293 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
278 continue; 294 continue;
295 nr_threads = perf_evlist__nr_threads(evlist, pos);
279 for (thread = 0; thread < nr_threads; thread++) 296 for (thread = 0; thread < nr_threads; thread++)
280 ioctl(FD(pos, cpu, thread), 297 ioctl(FD(pos, cpu, thread),
281 PERF_EVENT_IOC_DISABLE, 0); 298 PERF_EVENT_IOC_DISABLE, 0);
@@ -288,12 +305,13 @@ void perf_evlist__enable(struct perf_evlist *evlist)
288 int cpu, thread; 305 int cpu, thread;
289 struct perf_evsel *pos; 306 struct perf_evsel *pos;
290 int nr_cpus = cpu_map__nr(evlist->cpus); 307 int nr_cpus = cpu_map__nr(evlist->cpus);
291 int nr_threads = thread_map__nr(evlist->threads); 308 int nr_threads;
292 309
293 for (cpu = 0; cpu < nr_cpus; cpu++) { 310 for (cpu = 0; cpu < nr_cpus; cpu++) {
294 evlist__for_each(evlist, pos) { 311 evlist__for_each(evlist, pos) {
295 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 312 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
296 continue; 313 continue;
314 nr_threads = perf_evlist__nr_threads(evlist, pos);
297 for (thread = 0; thread < nr_threads; thread++) 315 for (thread = 0; thread < nr_threads; thread++)
298 ioctl(FD(pos, cpu, thread), 316 ioctl(FD(pos, cpu, thread),
299 PERF_EVENT_IOC_ENABLE, 0); 317 PERF_EVENT_IOC_ENABLE, 0);
@@ -305,12 +323,14 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
305 struct perf_evsel *evsel) 323 struct perf_evsel *evsel)
306{ 324{
307 int cpu, thread, err; 325 int cpu, thread, err;
326 int nr_cpus = cpu_map__nr(evlist->cpus);
327 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
308 328
309 if (!evsel->fd) 329 if (!evsel->fd)
310 return 0; 330 return 0;
311 331
312 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 332 for (cpu = 0; cpu < nr_cpus; cpu++) {
313 for (thread = 0; thread < evlist->threads->nr; thread++) { 333 for (thread = 0; thread < nr_threads; thread++) {
314 err = ioctl(FD(evsel, cpu, thread), 334 err = ioctl(FD(evsel, cpu, thread),
315 PERF_EVENT_IOC_DISABLE, 0); 335 PERF_EVENT_IOC_DISABLE, 0);
316 if (err) 336 if (err)
@@ -324,12 +344,14 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
324 struct perf_evsel *evsel) 344 struct perf_evsel *evsel)
325{ 345{
326 int cpu, thread, err; 346 int cpu, thread, err;
347 int nr_cpus = cpu_map__nr(evlist->cpus);
348 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
327 349
328 if (!evsel->fd) 350 if (!evsel->fd)
329 return -EINVAL; 351 return -EINVAL;
330 352
331 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 353 for (cpu = 0; cpu < nr_cpus; cpu++) {
332 for (thread = 0; thread < evlist->threads->nr; thread++) { 354 for (thread = 0; thread < nr_threads; thread++) {
333 err = ioctl(FD(evsel, cpu, thread), 355 err = ioctl(FD(evsel, cpu, thread),
334 PERF_EVENT_IOC_ENABLE, 0); 356 PERF_EVENT_IOC_ENABLE, 0);
335 if (err) 357 if (err)
@@ -339,21 +361,111 @@ int perf_evlist__enable_event(struct perf_evlist *evlist,
339 return 0; 361 return 0;
340} 362}
341 363
342static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 364static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
365 struct perf_evsel *evsel, int cpu)
366{
367 int thread, err;
368 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
369
370 if (!evsel->fd)
371 return -EINVAL;
372
373 for (thread = 0; thread < nr_threads; thread++) {
374 err = ioctl(FD(evsel, cpu, thread),
375 PERF_EVENT_IOC_ENABLE, 0);
376 if (err)
377 return err;
378 }
379 return 0;
380}
381
382static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
383 struct perf_evsel *evsel,
384 int thread)
385{
386 int cpu, err;
387 int nr_cpus = cpu_map__nr(evlist->cpus);
388
389 if (!evsel->fd)
390 return -EINVAL;
391
392 for (cpu = 0; cpu < nr_cpus; cpu++) {
393 err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
394 if (err)
395 return err;
396 }
397 return 0;
398}
399
400int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
401 struct perf_evsel *evsel, int idx)
402{
403 bool per_cpu_mmaps = !cpu_map__empty(evlist->cpus);
404
405 if (per_cpu_mmaps)
406 return perf_evlist__enable_event_cpu(evlist, evsel, idx);
407 else
408 return perf_evlist__enable_event_thread(evlist, evsel, idx);
409}
410
411int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
343{ 412{
344 int nr_cpus = cpu_map__nr(evlist->cpus); 413 int nr_cpus = cpu_map__nr(evlist->cpus);
345 int nr_threads = thread_map__nr(evlist->threads); 414 int nr_threads = thread_map__nr(evlist->threads);
346 int nfds = nr_cpus * nr_threads * evlist->nr_entries; 415 int nfds = 0;
347 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 416 struct perf_evsel *evsel;
348 return evlist->pollfd != NULL ? 0 : -ENOMEM; 417
418 evlist__for_each(evlist, evsel) {
419 if (evsel->system_wide)
420 nfds += nr_cpus;
421 else
422 nfds += nr_cpus * nr_threads;
423 }
424
425 if (fdarray__available_entries(&evlist->pollfd) < nfds &&
426 fdarray__grow(&evlist->pollfd, nfds) < 0)
427 return -ENOMEM;
428
429 return 0;
349} 430}
350 431
351void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 432static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx)
352{ 433{
353 fcntl(fd, F_SETFL, O_NONBLOCK); 434 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP);
354 evlist->pollfd[evlist->nr_fds].fd = fd; 435 /*
355 evlist->pollfd[evlist->nr_fds].events = POLLIN; 436 * Save the idx so that when we filter out fds POLLHUP'ed we can
356 evlist->nr_fds++; 437 * close the associated evlist->mmap[] entry.
438 */
439 if (pos >= 0) {
440 evlist->pollfd.priv[pos].idx = idx;
441
442 fcntl(fd, F_SETFL, O_NONBLOCK);
443 }
444
445 return pos;
446}
447
448int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
449{
450 return __perf_evlist__add_pollfd(evlist, fd, -1);
451}
452
453static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd)
454{
455 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd);
456
457 perf_evlist__mmap_put(evlist, fda->priv[fd].idx);
458}
459
460int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
461{
462 return fdarray__filter(&evlist->pollfd, revents_and_mask,
463 perf_evlist__munmap_filtered);
464}
465
466int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
467{
468 return fdarray__poll(&evlist->pollfd, timeout);
357} 469}
358 470
359static void perf_evlist__id_hash(struct perf_evlist *evlist, 471static void perf_evlist__id_hash(struct perf_evlist *evlist,
@@ -417,6 +529,22 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
417 return 0; 529 return 0;
418} 530}
419 531
532static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
533 struct perf_evsel *evsel, int idx, int cpu,
534 int thread)
535{
536 struct perf_sample_id *sid = SID(evsel, cpu, thread);
537 sid->idx = idx;
538 if (evlist->cpus && cpu >= 0)
539 sid->cpu = evlist->cpus->map[cpu];
540 else
541 sid->cpu = -1;
542 if (!evsel->system_wide && evlist->threads && thread >= 0)
543 sid->tid = evlist->threads->map[thread];
544 else
545 sid->tid = -1;
546}
547
420struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id) 548struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
421{ 549{
422 struct hlist_head *head; 550 struct hlist_head *head;
@@ -566,14 +694,36 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
566 return event; 694 return event;
567} 695}
568 696
697static bool perf_mmap__empty(struct perf_mmap *md)
698{
699 return perf_mmap__read_head(md) != md->prev;
700}
701
702static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx)
703{
704 ++evlist->mmap[idx].refcnt;
705}
706
707static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx)
708{
709 BUG_ON(evlist->mmap[idx].refcnt == 0);
710
711 if (--evlist->mmap[idx].refcnt == 0)
712 __perf_evlist__munmap(evlist, idx);
713}
714
569void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 715void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
570{ 716{
717 struct perf_mmap *md = &evlist->mmap[idx];
718
571 if (!evlist->overwrite) { 719 if (!evlist->overwrite) {
572 struct perf_mmap *md = &evlist->mmap[idx];
573 unsigned int old = md->prev; 720 unsigned int old = md->prev;
574 721
575 perf_mmap__write_tail(md, old); 722 perf_mmap__write_tail(md, old);
576 } 723 }
724
725 if (md->refcnt == 1 && perf_mmap__empty(md))
726 perf_evlist__mmap_put(evlist, idx);
577} 727}
578 728
579static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 729static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
@@ -581,6 +731,7 @@ static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx)
581 if (evlist->mmap[idx].base != NULL) { 731 if (evlist->mmap[idx].base != NULL) {
582 munmap(evlist->mmap[idx].base, evlist->mmap_len); 732 munmap(evlist->mmap[idx].base, evlist->mmap_len);
583 evlist->mmap[idx].base = NULL; 733 evlist->mmap[idx].base = NULL;
734 evlist->mmap[idx].refcnt = 0;
584 } 735 }
585} 736}
586 737
@@ -614,6 +765,20 @@ struct mmap_params {
614static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 765static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
615 struct mmap_params *mp, int fd) 766 struct mmap_params *mp, int fd)
616{ 767{
768 /*
769 * The last one will be done at perf_evlist__mmap_consume(), so that we
770 * make sure we don't prevent tools from consuming every last event in
771 * the ring buffer.
772 *
773 * I.e. we can get the POLLHUP meaning that the fd doesn't exist
774 * anymore, but the last events for it are still in the ring buffer,
775 * waiting to be consumed.
776 *
777 * Tools can chose to ignore this at their own discretion, but the
778 * evlist layer can't just drop it when filtering events in
779 * perf_evlist__filter_pollfd().
780 */
781 evlist->mmap[idx].refcnt = 2;
617 evlist->mmap[idx].prev = 0; 782 evlist->mmap[idx].prev = 0;
618 evlist->mmap[idx].mask = mp->mask; 783 evlist->mmap[idx].mask = mp->mask;
619 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 784 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot,
@@ -625,7 +790,6 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
625 return -1; 790 return -1;
626 } 791 }
627 792
628 perf_evlist__add_pollfd(evlist, fd);
629 return 0; 793 return 0;
630} 794}
631 795
@@ -636,7 +800,12 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
636 struct perf_evsel *evsel; 800 struct perf_evsel *evsel;
637 801
638 evlist__for_each(evlist, evsel) { 802 evlist__for_each(evlist, evsel) {
639 int fd = FD(evsel, cpu, thread); 803 int fd;
804
805 if (evsel->system_wide && thread)
806 continue;
807
808 fd = FD(evsel, cpu, thread);
640 809
641 if (*output == -1) { 810 if (*output == -1) {
642 *output = fd; 811 *output = fd;
@@ -645,11 +814,30 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
645 } else { 814 } else {
646 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 815 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
647 return -1; 816 return -1;
817
818 perf_evlist__mmap_get(evlist, idx);
648 } 819 }
649 820
650 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 821 /*
651 perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0) 822 * The system_wide flag causes a selected event to be opened
823 * always without a pid. Consequently it will never get a
824 * POLLHUP, but it is used for tracking in combination with
825 * other events, so it should not need to be polled anyway.
826 * Therefore don't add it for polling.
827 */
828 if (!evsel->system_wide &&
829 __perf_evlist__add_pollfd(evlist, fd, idx) < 0) {
830 perf_evlist__mmap_put(evlist, idx);
652 return -1; 831 return -1;
832 }
833
834 if (evsel->attr.read_format & PERF_FORMAT_ID) {
835 if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread,
836 fd) < 0)
837 return -1;
838 perf_evlist__set_sid_idx(evlist, evsel, idx, cpu,
839 thread);
840 }
653 } 841 }
654 842
655 return 0; 843 return 0;
@@ -706,10 +894,24 @@ out_unmap:
706 894
707static size_t perf_evlist__mmap_size(unsigned long pages) 895static size_t perf_evlist__mmap_size(unsigned long pages)
708{ 896{
709 /* 512 kiB: default amount of unprivileged mlocked memory */ 897 if (pages == UINT_MAX) {
710 if (pages == UINT_MAX) 898 int max;
711 pages = (512 * 1024) / page_size; 899
712 else if (!is_power_of_2(pages)) 900 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
901 /*
902 * Pick a once upon a time good value, i.e. things look
903 * strange since we can't read a sysctl value, but lets not
904 * die yet...
905 */
906 max = 512;
907 } else {
908 max -= (page_size / 1024);
909 }
910
911 pages = (max * 1024) / page_size;
912 if (!is_power_of_2(pages))
913 pages = rounddown_pow_of_two(pages);
914 } else if (!is_power_of_2(pages))
713 return 0; 915 return 0;
714 916
715 return (pages + 1) * page_size; 917 return (pages + 1) * page_size;
@@ -746,7 +948,7 @@ static long parse_pages_arg(const char *str, unsigned long min,
746 /* leave number of pages at 0 */ 948 /* leave number of pages at 0 */
747 } else if (!is_power_of_2(pages)) { 949 } else if (!is_power_of_2(pages)) {
748 /* round pages up to next power of 2 */ 950 /* round pages up to next power of 2 */
749 pages = next_pow2_l(pages); 951 pages = roundup_pow_of_two(pages);
750 if (!pages) 952 if (!pages)
751 return -EINVAL; 953 return -EINVAL;
752 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n", 954 pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
@@ -804,7 +1006,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
804 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 1006 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
805 return -ENOMEM; 1007 return -ENOMEM;
806 1008
807 if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 1009 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
808 return -ENOMEM; 1010 return -ENOMEM;
809 1011
810 evlist->overwrite = overwrite; 1012 evlist->overwrite = overwrite;
@@ -845,6 +1047,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
845 1047
846out_delete_threads: 1048out_delete_threads:
847 thread_map__delete(evlist->threads); 1049 thread_map__delete(evlist->threads);
1050 evlist->threads = NULL;
848 return -1; 1051 return -1;
849} 1052}
850 1053
@@ -1017,11 +1220,51 @@ void perf_evlist__close(struct perf_evlist *evlist)
1017 } 1220 }
1018} 1221}
1019 1222
1223static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
1224{
1225 int err = -ENOMEM;
1226
1227 /*
1228 * Try reading /sys/devices/system/cpu/online to get
1229 * an all cpus map.
1230 *
1231 * FIXME: -ENOMEM is the best we can do here, the cpu_map
1232 * code needs an overhaul to properly forward the
1233 * error, and we may not want to do that fallback to a
1234 * default cpu identity map :-\
1235 */
1236 evlist->cpus = cpu_map__new(NULL);
1237 if (evlist->cpus == NULL)
1238 goto out;
1239
1240 evlist->threads = thread_map__new_dummy();
1241 if (evlist->threads == NULL)
1242 goto out_free_cpus;
1243
1244 err = 0;
1245out:
1246 return err;
1247out_free_cpus:
1248 cpu_map__delete(evlist->cpus);
1249 evlist->cpus = NULL;
1250 goto out;
1251}
1252
1020int perf_evlist__open(struct perf_evlist *evlist) 1253int perf_evlist__open(struct perf_evlist *evlist)
1021{ 1254{
1022 struct perf_evsel *evsel; 1255 struct perf_evsel *evsel;
1023 int err; 1256 int err;
1024 1257
1258 /*
1259 * Default: one fd per CPU, all threads, aka systemwide
1260 * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
1261 */
1262 if (evlist->threads == NULL && evlist->cpus == NULL) {
1263 err = perf_evlist__create_syswide_maps(evlist);
1264 if (err < 0)
1265 goto out_err;
1266 }
1267
1025 perf_evlist__update_id_pos(evlist); 1268 perf_evlist__update_id_pos(evlist);
1026 1269
1027 evlist__for_each(evlist, evsel) { 1270 evlist__for_each(evlist, evsel) {
@@ -1061,6 +1304,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1061 } 1304 }
1062 1305
1063 if (!evlist->workload.pid) { 1306 if (!evlist->workload.pid) {
1307 int ret;
1308
1064 if (pipe_output) 1309 if (pipe_output)
1065 dup2(2, 1); 1310 dup2(2, 1);
1066 1311
@@ -1078,8 +1323,22 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1078 /* 1323 /*
1079 * Wait until the parent tells us to go. 1324 * Wait until the parent tells us to go.
1080 */ 1325 */
1081 if (read(go_pipe[0], &bf, 1) == -1) 1326 ret = read(go_pipe[0], &bf, 1);
1082 perror("unable to read pipe"); 1327 /*
1328 * The parent will ask for the execvp() to be performed by
1329 * writing exactly one byte, in workload.cork_fd, usually via
1330 * perf_evlist__start_workload().
1331 *
1332 * For cancelling the workload without actuallin running it,
1333 * the parent will just close workload.cork_fd, without writing
1334 * anything, i.e. read will return zero and we just exit()
1335 * here.
1336 */
1337 if (ret != 1) {
1338 if (ret == -1)
1339 perror("unable to read pipe");
1340 exit(ret);
1341 }
1083 1342
1084 execvp(argv[0], (char **)argv); 1343 execvp(argv[0], (char **)argv);
1085 1344
@@ -1102,8 +1361,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1102 sigaction(SIGUSR1, &act, NULL); 1361 sigaction(SIGUSR1, &act, NULL);
1103 } 1362 }
1104 1363
1105 if (target__none(target)) 1364 if (target__none(target)) {
1365 if (evlist->threads == NULL) {
1366 fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
1367 __func__, __LINE__);
1368 goto out_close_pipes;
1369 }
1106 evlist->threads->map[0] = evlist->workload.pid; 1370 evlist->threads->map[0] = evlist->workload.pid;
1371 }
1107 1372
1108 close(child_ready_pipe[1]); 1373 close(child_ready_pipe[1]);
1109 close(go_pipe[0]); 1374 close(go_pipe[0]);
@@ -1202,7 +1467,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1202 int err, char *buf, size_t size) 1467 int err, char *buf, size_t size)
1203{ 1468{
1204 int printed, value; 1469 int printed, value;
1205 char sbuf[128], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1470 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1206 1471
1207 switch (err) { 1472 switch (err) {
1208 case EACCES: 1473 case EACCES:
@@ -1234,6 +1499,37 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist __maybe_unused,
1234 return 0; 1499 return 0;
1235} 1500}
1236 1501
1502int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1503{
1504 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf));
1505 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1506
1507 switch (err) {
1508 case EPERM:
1509 sysctl__read_int("kernel/perf_event_mlock_kb", &pages_max_per_user);
1510 printed += scnprintf(buf + printed, size - printed,
1511 "Error:\t%s.\n"
1512 "Hint:\tCheck /proc/sys/kernel/perf_event_mlock_kb (%d kB) setting.\n"
1513 "Hint:\tTried using %zd kB.\n",
1514 emsg, pages_max_per_user, pages_attempted);
1515
1516 if (pages_attempted >= pages_max_per_user) {
1517 printed += scnprintf(buf + printed, size - printed,
1518 "Hint:\tTry 'sudo sh -c \"echo %d > /proc/sys/kernel/perf_event_mlock_kb\"', or\n",
1519 pages_max_per_user + pages_attempted);
1520 }
1521
1522 printed += scnprintf(buf + printed, size - printed,
1523 "Hint:\tTry using a smaller -m/--mmap-pages value.");
1524 break;
1525 default:
1526 scnprintf(buf, size, "%s", emsg);
1527 break;
1528 }
1529
1530 return 0;
1531}
1532
1237void perf_evlist__to_front(struct perf_evlist *evlist, 1533void perf_evlist__to_front(struct perf_evlist *evlist,
1238 struct perf_evsel *move_evsel) 1534 struct perf_evsel *move_evsel)
1239{ 1535{
@@ -1250,3 +1546,19 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1250 1546
1251 list_splice(&move, &evlist->entries); 1547 list_splice(&move, &evlist->entries);
1252} 1548}
1549
1550void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1551 struct perf_evsel *tracking_evsel)
1552{
1553 struct perf_evsel *evsel;
1554
1555 if (tracking_evsel->tracking)
1556 return;
1557
1558 evlist__for_each(evlist, evsel) {
1559 if (evsel != tracking_evsel)
1560 evsel->tracking = false;
1561 }
1562
1563 tracking_evsel->tracking = true;
1564}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index f5173cd63693..0ba93f67ab94 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,6 +2,7 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <api/fd/array.h>
5#include <stdio.h> 6#include <stdio.h>
6#include "../perf.h" 7#include "../perf.h"
7#include "event.h" 8#include "event.h"
@@ -17,9 +18,15 @@ struct record_opts;
17#define PERF_EVLIST__HLIST_BITS 8 18#define PERF_EVLIST__HLIST_BITS 8
18#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 19#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
19 20
21/**
22 * struct perf_mmap - perf's ring buffer mmap details
23 *
24 * @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
25 */
20struct perf_mmap { 26struct perf_mmap {
21 void *base; 27 void *base;
22 int mask; 28 int mask;
29 int refcnt;
23 unsigned int prev; 30 unsigned int prev;
24 char event_copy[PERF_SAMPLE_MAX_SIZE]; 31 char event_copy[PERF_SAMPLE_MAX_SIZE];
25}; 32};
@@ -29,7 +36,6 @@ struct perf_evlist {
29 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 36 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
30 int nr_entries; 37 int nr_entries;
31 int nr_groups; 38 int nr_groups;
32 int nr_fds;
33 int nr_mmaps; 39 int nr_mmaps;
34 size_t mmap_len; 40 size_t mmap_len;
35 int id_pos; 41 int id_pos;
@@ -40,8 +46,8 @@ struct perf_evlist {
40 pid_t pid; 46 pid_t pid;
41 } workload; 47 } workload;
42 bool overwrite; 48 bool overwrite;
49 struct fdarray pollfd;
43 struct perf_mmap *mmap; 50 struct perf_mmap *mmap;
44 struct pollfd *pollfd;
45 struct thread_map *threads; 51 struct thread_map *threads;
46 struct cpu_map *cpus; 52 struct cpu_map *cpus;
47 struct perf_evsel *selected; 53 struct perf_evsel *selected;
@@ -82,7 +88,11 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
82void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 88void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
83 int cpu, int thread, u64 id); 89 int cpu, int thread, u64 id);
84 90
85void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 91int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
92int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
93int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask);
94
95int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
86 96
87struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 97struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
88 98
@@ -107,6 +117,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
107 void *ucontext)); 117 void *ucontext));
108int perf_evlist__start_workload(struct perf_evlist *evlist); 118int perf_evlist__start_workload(struct perf_evlist *evlist);
109 119
120struct option;
121
110int perf_evlist__parse_mmap_pages(const struct option *opt, 122int perf_evlist__parse_mmap_pages(const struct option *opt,
111 const char *str, 123 const char *str,
112 int unset); 124 int unset);
@@ -122,6 +134,8 @@ int perf_evlist__disable_event(struct perf_evlist *evlist,
122 struct perf_evsel *evsel); 134 struct perf_evsel *evsel);
123int perf_evlist__enable_event(struct perf_evlist *evlist, 135int perf_evlist__enable_event(struct perf_evlist *evlist,
124 struct perf_evsel *evsel); 136 struct perf_evsel *evsel);
137int perf_evlist__enable_event_idx(struct perf_evlist *evlist,
138 struct perf_evsel *evsel, int idx);
125 139
126void perf_evlist__set_selected(struct perf_evlist *evlist, 140void perf_evlist__set_selected(struct perf_evlist *evlist,
127 struct perf_evsel *evsel); 141 struct perf_evsel *evsel);
@@ -171,6 +185,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
171 185
172int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size); 186int perf_evlist__strerror_tp(struct perf_evlist *evlist, int err, char *buf, size_t size);
173int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 187int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
188int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
174 189
175static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 190static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
176{ 191{
@@ -262,4 +277,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
262#define evlist__for_each_safe(evlist, tmp, evsel) \ 277#define evlist__for_each_safe(evlist, tmp, evsel) \
263 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 278 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
264 279
280void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
281 struct perf_evsel *tracking_evsel);
282
265#endif /* __PERF_EVLIST_H */ 283#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21a373ebea22..1e90c8557ede 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,6 +15,8 @@
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <sys/resource.h> 16#include <sys/resource.h>
17#include "asm/bug.h" 17#include "asm/bug.h"
18#include "callchain.h"
19#include "cgroup.h"
18#include "evsel.h" 20#include "evsel.h"
19#include "evlist.h" 21#include "evlist.h"
20#include "util.h" 22#include "util.h"
@@ -32,6 +34,48 @@ static struct {
32 bool cloexec; 34 bool cloexec;
33} perf_missing_features; 35} perf_missing_features;
34 36
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
38{
39 return 0;
40}
41
42static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused)
43{
44}
45
46static struct {
47 size_t size;
48 int (*init)(struct perf_evsel *evsel);
49 void (*fini)(struct perf_evsel *evsel);
50} perf_evsel__object = {
51 .size = sizeof(struct perf_evsel),
52 .init = perf_evsel__no_extra_init,
53 .fini = perf_evsel__no_extra_fini,
54};
55
56int perf_evsel__object_config(size_t object_size,
57 int (*init)(struct perf_evsel *evsel),
58 void (*fini)(struct perf_evsel *evsel))
59{
60
61 if (object_size == 0)
62 goto set_methods;
63
64 if (perf_evsel__object.size > object_size)
65 return -EINVAL;
66
67 perf_evsel__object.size = object_size;
68
69set_methods:
70 if (init != NULL)
71 perf_evsel__object.init = init;
72
73 if (fini != NULL)
74 perf_evsel__object.fini = fini;
75
76 return 0;
77}
78
35#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 79#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
36 80
37int __perf_evsel__sample_size(u64 sample_type) 81int __perf_evsel__sample_size(u64 sample_type)
@@ -116,16 +160,6 @@ void perf_evsel__calc_id_pos(struct perf_evsel *evsel)
116 evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); 160 evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type);
117} 161}
118 162
119void hists__init(struct hists *hists)
120{
121 memset(hists, 0, sizeof(*hists));
122 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
123 hists->entries_in = &hists->entries_in_array[0];
124 hists->entries_collapsed = RB_ROOT;
125 hists->entries = RB_ROOT;
126 pthread_mutex_init(&hists->lock, NULL);
127}
128
129void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 163void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
130 enum perf_event_sample_format bit) 164 enum perf_event_sample_format bit)
131{ 165{
@@ -162,19 +196,20 @@ void perf_evsel__init(struct perf_evsel *evsel,
162 struct perf_event_attr *attr, int idx) 196 struct perf_event_attr *attr, int idx)
163{ 197{
164 evsel->idx = idx; 198 evsel->idx = idx;
199 evsel->tracking = !idx;
165 evsel->attr = *attr; 200 evsel->attr = *attr;
166 evsel->leader = evsel; 201 evsel->leader = evsel;
167 evsel->unit = ""; 202 evsel->unit = "";
168 evsel->scale = 1.0; 203 evsel->scale = 1.0;
169 INIT_LIST_HEAD(&evsel->node); 204 INIT_LIST_HEAD(&evsel->node);
170 hists__init(&evsel->hists); 205 perf_evsel__object.init(evsel);
171 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 206 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
172 perf_evsel__calc_id_pos(evsel); 207 perf_evsel__calc_id_pos(evsel);
173} 208}
174 209
175struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 210struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
176{ 211{
177 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 212 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
178 213
179 if (evsel != NULL) 214 if (evsel != NULL)
180 perf_evsel__init(evsel, attr, idx); 215 perf_evsel__init(evsel, attr, idx);
@@ -184,7 +219,7 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
184 219
185struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 220struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
186{ 221{
187 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 222 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
188 223
189 if (evsel != NULL) { 224 if (evsel != NULL) {
190 struct perf_event_attr attr = { 225 struct perf_event_attr attr = {
@@ -502,20 +537,19 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
502} 537}
503 538
504static void 539static void
505perf_evsel__config_callgraph(struct perf_evsel *evsel, 540perf_evsel__config_callgraph(struct perf_evsel *evsel)
506 struct record_opts *opts)
507{ 541{
508 bool function = perf_evsel__is_function_event(evsel); 542 bool function = perf_evsel__is_function_event(evsel);
509 struct perf_event_attr *attr = &evsel->attr; 543 struct perf_event_attr *attr = &evsel->attr;
510 544
511 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 545 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
512 546
513 if (opts->call_graph == CALLCHAIN_DWARF) { 547 if (callchain_param.record_mode == CALLCHAIN_DWARF) {
514 if (!function) { 548 if (!function) {
515 perf_evsel__set_sample_bit(evsel, REGS_USER); 549 perf_evsel__set_sample_bit(evsel, REGS_USER);
516 perf_evsel__set_sample_bit(evsel, STACK_USER); 550 perf_evsel__set_sample_bit(evsel, STACK_USER);
517 attr->sample_regs_user = PERF_REGS_MASK; 551 attr->sample_regs_user = PERF_REGS_MASK;
518 attr->sample_stack_user = opts->stack_dump_size; 552 attr->sample_stack_user = callchain_param.dump_size;
519 attr->exclude_callchain_user = 1; 553 attr->exclude_callchain_user = 1;
520 } else { 554 } else {
521 pr_info("Cannot use DWARF unwind for function trace event," 555 pr_info("Cannot use DWARF unwind for function trace event,"
@@ -561,7 +595,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
561{ 595{
562 struct perf_evsel *leader = evsel->leader; 596 struct perf_evsel *leader = evsel->leader;
563 struct perf_event_attr *attr = &evsel->attr; 597 struct perf_event_attr *attr = &evsel->attr;
564 int track = !evsel->idx; /* only the first counter needs these */ 598 int track = evsel->tracking;
565 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread; 599 bool per_cpu = opts->target.default_per_cpu && !opts->target.per_thread;
566 600
567 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 601 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
@@ -624,8 +658,21 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
624 attr->mmap_data = track; 658 attr->mmap_data = track;
625 } 659 }
626 660
627 if (opts->call_graph_enabled && !evsel->no_aux_samples) 661 /*
628 perf_evsel__config_callgraph(evsel, opts); 662 * We don't allow user space callchains for function trace
663 * event, due to issues with page faults while tracing page
664 * fault handler and its overall trickiness nature.
665 */
666 if (perf_evsel__is_function_event(evsel))
667 evsel->attr.exclude_callchain_user = 1;
668
669 if (callchain_param.enabled && !evsel->no_aux_samples)
670 perf_evsel__config_callgraph(evsel);
671
672 if (opts->sample_intr_regs) {
673 attr->sample_regs_intr = PERF_REGS_MASK;
674 perf_evsel__set_sample_bit(evsel, REGS_INTR);
675 }
629 676
630 if (target__has_cpu(&opts->target)) 677 if (target__has_cpu(&opts->target))
631 perf_evsel__set_sample_bit(evsel, CPU); 678 perf_evsel__set_sample_bit(evsel, CPU);
@@ -633,9 +680,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
633 if (opts->period) 680 if (opts->period)
634 perf_evsel__set_sample_bit(evsel, PERIOD); 681 perf_evsel__set_sample_bit(evsel, PERIOD);
635 682
636 if (!perf_missing_features.sample_id_all && 683 /*
637 (opts->sample_time || !opts->no_inherit || 684 * When the user explicitely disabled time don't force it here.
638 target__has_cpu(&opts->target) || per_cpu)) 685 */
686 if (opts->sample_time &&
687 (!perf_missing_features.sample_id_all &&
688 (!opts->no_inherit || target__has_cpu(&opts->target) || per_cpu)))
639 perf_evsel__set_sample_bit(evsel, TIME); 689 perf_evsel__set_sample_bit(evsel, TIME);
640 690
641 if (opts->raw_samples && !evsel->no_aux_samples) { 691 if (opts->raw_samples && !evsel->no_aux_samples) {
@@ -689,9 +739,13 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
689 } 739 }
690} 740}
691 741
692int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 742static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
693{ 743{
694 int cpu, thread; 744 int cpu, thread;
745
746 if (evsel->system_wide)
747 nthreads = 1;
748
695 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 749 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
696 750
697 if (evsel->fd) { 751 if (evsel->fd) {
@@ -710,6 +764,9 @@ static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthrea
710{ 764{
711 int cpu, thread; 765 int cpu, thread;
712 766
767 if (evsel->system_wide)
768 nthreads = 1;
769
713 for (cpu = 0; cpu < ncpus; cpu++) { 770 for (cpu = 0; cpu < ncpus; cpu++) {
714 for (thread = 0; thread < nthreads; thread++) { 771 for (thread = 0; thread < nthreads; thread++) {
715 int fd = FD(evsel, cpu, thread), 772 int fd = FD(evsel, cpu, thread),
@@ -740,6 +797,9 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
740 797
741int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 798int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
742{ 799{
800 if (evsel->system_wide)
801 nthreads = 1;
802
743 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 803 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
744 if (evsel->sample_id == NULL) 804 if (evsel->sample_id == NULL)
745 return -ENOMEM; 805 return -ENOMEM;
@@ -767,13 +827,13 @@ int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
767 return evsel->counts != NULL ? 0 : -ENOMEM; 827 return evsel->counts != NULL ? 0 : -ENOMEM;
768} 828}
769 829
770void perf_evsel__free_fd(struct perf_evsel *evsel) 830static void perf_evsel__free_fd(struct perf_evsel *evsel)
771{ 831{
772 xyarray__delete(evsel->fd); 832 xyarray__delete(evsel->fd);
773 evsel->fd = NULL; 833 evsel->fd = NULL;
774} 834}
775 835
776void perf_evsel__free_id(struct perf_evsel *evsel) 836static void perf_evsel__free_id(struct perf_evsel *evsel)
777{ 837{
778 xyarray__delete(evsel->sample_id); 838 xyarray__delete(evsel->sample_id);
779 evsel->sample_id = NULL; 839 evsel->sample_id = NULL;
@@ -784,6 +844,9 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
784{ 844{
785 int cpu, thread; 845 int cpu, thread;
786 846
847 if (evsel->system_wide)
848 nthreads = 1;
849
787 for (cpu = 0; cpu < ncpus; cpu++) 850 for (cpu = 0; cpu < ncpus; cpu++)
788 for (thread = 0; thread < nthreads; ++thread) { 851 for (thread = 0; thread < nthreads; ++thread) {
789 close(FD(evsel, cpu, thread)); 852 close(FD(evsel, cpu, thread));
@@ -801,22 +864,20 @@ void perf_evsel__exit(struct perf_evsel *evsel)
801 assert(list_empty(&evsel->node)); 864 assert(list_empty(&evsel->node));
802 perf_evsel__free_fd(evsel); 865 perf_evsel__free_fd(evsel);
803 perf_evsel__free_id(evsel); 866 perf_evsel__free_id(evsel);
867 close_cgroup(evsel->cgrp);
868 zfree(&evsel->group_name);
869 zfree(&evsel->name);
870 perf_evsel__object.fini(evsel);
804} 871}
805 872
806void perf_evsel__delete(struct perf_evsel *evsel) 873void perf_evsel__delete(struct perf_evsel *evsel)
807{ 874{
808 perf_evsel__exit(evsel); 875 perf_evsel__exit(evsel);
809 close_cgroup(evsel->cgrp);
810 zfree(&evsel->group_name);
811 if (evsel->tp_format)
812 pevent_free_format(evsel->tp_format);
813 zfree(&evsel->name);
814 free(evsel); 876 free(evsel);
815} 877}
816 878
817static inline void compute_deltas(struct perf_evsel *evsel, 879void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
818 int cpu, 880 struct perf_counts_values *count)
819 struct perf_counts_values *count)
820{ 881{
821 struct perf_counts_values tmp; 882 struct perf_counts_values tmp;
822 883
@@ -836,78 +897,60 @@ static inline void compute_deltas(struct perf_evsel *evsel,
836 count->run = count->run - tmp.run; 897 count->run = count->run - tmp.run;
837} 898}
838 899
839int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 900void perf_counts_values__scale(struct perf_counts_values *count,
840 int cpu, int thread, bool scale) 901 bool scale, s8 *pscaled)
841{ 902{
842 struct perf_counts_values count; 903 s8 scaled = 0;
843 size_t nv = scale ? 3 : 1;
844
845 if (FD(evsel, cpu, thread) < 0)
846 return -EINVAL;
847
848 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
849 return -ENOMEM;
850
851 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
852 return -errno;
853
854 compute_deltas(evsel, cpu, &count);
855 904
856 if (scale) { 905 if (scale) {
857 if (count.run == 0) 906 if (count->run == 0) {
858 count.val = 0; 907 scaled = -1;
859 else if (count.run < count.ena) 908 count->val = 0;
860 count.val = (u64)((double)count.val * count.ena / count.run + 0.5); 909 } else if (count->run < count->ena) {
910 scaled = 1;
911 count->val = (u64)((double) count->val * count->ena / count->run + 0.5);
912 }
861 } else 913 } else
862 count.ena = count.run = 0; 914 count->ena = count->run = 0;
863 915
864 evsel->counts->cpu[cpu] = count; 916 if (pscaled)
865 return 0; 917 *pscaled = scaled;
866} 918}
867 919
868int __perf_evsel__read(struct perf_evsel *evsel, 920int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
869 int ncpus, int nthreads, bool scale) 921 perf_evsel__read_cb_t cb)
870{ 922{
871 size_t nv = scale ? 3 : 1; 923 struct perf_counts_values count;
872 int cpu, thread;
873 struct perf_counts_values *aggr = &evsel->counts->aggr, count;
874 924
875 aggr->val = aggr->ena = aggr->run = 0; 925 memset(&count, 0, sizeof(count));
876 926
877 for (cpu = 0; cpu < ncpus; cpu++) { 927 if (FD(evsel, cpu, thread) < 0)
878 for (thread = 0; thread < nthreads; thread++) { 928 return -EINVAL;
879 if (FD(evsel, cpu, thread) < 0)
880 continue;
881 929
882 if (readn(FD(evsel, cpu, thread), 930 if (readn(FD(evsel, cpu, thread), &count, sizeof(count)) < 0)
883 &count, nv * sizeof(u64)) < 0) 931 return -errno;
884 return -errno;
885 932
886 aggr->val += count.val; 933 return cb(evsel, cpu, thread, &count);
887 if (scale) { 934}
888 aggr->ena += count.ena; 935
889 aggr->run += count.run; 936int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
890 } 937 int cpu, int thread, bool scale)
891 } 938{
892 } 939 struct perf_counts_values count;
940 size_t nv = scale ? 3 : 1;
893 941
894 compute_deltas(evsel, -1, aggr); 942 if (FD(evsel, cpu, thread) < 0)
943 return -EINVAL;
895 944
896 evsel->counts->scaled = 0; 945 if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
897 if (scale) { 946 return -ENOMEM;
898 if (aggr->run == 0) {
899 evsel->counts->scaled = -1;
900 aggr->val = 0;
901 return 0;
902 }
903 947
904 if (aggr->run < aggr->ena) { 948 if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
905 evsel->counts->scaled = 1; 949 return -errno;
906 aggr->val = (u64)((double)aggr->val * aggr->ena / aggr->run + 0.5);
907 }
908 } else
909 aggr->ena = aggr->run = 0;
910 950
951 perf_evsel__compute_deltas(evsel, cpu, &count);
952 perf_counts_values__scale(&count, scale, NULL);
953 evsel->counts->cpu[cpu] = count;
911 return 0; 954 return 0;
912} 955}
913 956
@@ -985,6 +1028,7 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
985 ret += PRINT_ATTR_X64(branch_sample_type); 1028 ret += PRINT_ATTR_X64(branch_sample_type);
986 ret += PRINT_ATTR_X64(sample_regs_user); 1029 ret += PRINT_ATTR_X64(sample_regs_user);
987 ret += PRINT_ATTR_U32(sample_stack_user); 1030 ret += PRINT_ATTR_U32(sample_stack_user);
1031 ret += PRINT_ATTR_X64(sample_regs_intr);
988 1032
989 ret += fprintf(fp, "%.60s\n", graph_dotted_line); 1033 ret += fprintf(fp, "%.60s\n", graph_dotted_line);
990 1034
@@ -994,13 +1038,18 @@ static size_t perf_event_attr__fprintf(struct perf_event_attr *attr, FILE *fp)
994static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 1038static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
995 struct thread_map *threads) 1039 struct thread_map *threads)
996{ 1040{
997 int cpu, thread; 1041 int cpu, thread, nthreads;
998 unsigned long flags = PERF_FLAG_FD_CLOEXEC; 1042 unsigned long flags = PERF_FLAG_FD_CLOEXEC;
999 int pid = -1, err; 1043 int pid = -1, err;
1000 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1044 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1001 1045
1046 if (evsel->system_wide)
1047 nthreads = 1;
1048 else
1049 nthreads = threads->nr;
1050
1002 if (evsel->fd == NULL && 1051 if (evsel->fd == NULL &&
1003 perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0) 1052 perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
1004 return -ENOMEM; 1053 return -ENOMEM;
1005 1054
1006 if (evsel->cgrp) { 1055 if (evsel->cgrp) {
@@ -1024,10 +1073,10 @@ retry_sample_id:
1024 1073
1025 for (cpu = 0; cpu < cpus->nr; cpu++) { 1074 for (cpu = 0; cpu < cpus->nr; cpu++) {
1026 1075
1027 for (thread = 0; thread < threads->nr; thread++) { 1076 for (thread = 0; thread < nthreads; thread++) {
1028 int group_fd; 1077 int group_fd;
1029 1078
1030 if (!evsel->cgrp) 1079 if (!evsel->cgrp && !evsel->system_wide)
1031 pid = threads->map[thread]; 1080 pid = threads->map[thread];
1032 1081
1033 group_fd = get_group_fd(evsel, cpu, thread); 1082 group_fd = get_group_fd(evsel, cpu, thread);
@@ -1100,7 +1149,7 @@ out_close:
1100 close(FD(evsel, cpu, thread)); 1149 close(FD(evsel, cpu, thread));
1101 FD(evsel, cpu, thread) = -1; 1150 FD(evsel, cpu, thread) = -1;
1102 } 1151 }
1103 thread = threads->nr; 1152 thread = nthreads;
1104 } while (--cpu >= 0); 1153 } while (--cpu >= 0);
1105 return err; 1154 return err;
1106} 1155}
@@ -1479,6 +1528,23 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1479 array++; 1528 array++;
1480 } 1529 }
1481 1530
1531 data->intr_regs.abi = PERF_SAMPLE_REGS_ABI_NONE;
1532 if (type & PERF_SAMPLE_REGS_INTR) {
1533 OVERFLOW_CHECK_u64(array);
1534 data->intr_regs.abi = *array;
1535 array++;
1536
1537 if (data->intr_regs.abi != PERF_SAMPLE_REGS_ABI_NONE) {
1538 u64 mask = evsel->attr.sample_regs_intr;
1539
1540 sz = hweight_long(mask) * sizeof(u64);
1541 OVERFLOW_CHECK(array, sz, max_size);
1542 data->intr_regs.mask = mask;
1543 data->intr_regs.regs = (u64 *)array;
1544 array = (void *)array + sz;
1545 }
1546 }
1547
1482 return 0; 1548 return 0;
1483} 1549}
1484 1550
@@ -1574,6 +1640,16 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
1574 if (type & PERF_SAMPLE_TRANSACTION) 1640 if (type & PERF_SAMPLE_TRANSACTION)
1575 result += sizeof(u64); 1641 result += sizeof(u64);
1576 1642
1643 if (type & PERF_SAMPLE_REGS_INTR) {
1644 if (sample->intr_regs.abi) {
1645 result += sizeof(u64);
1646 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1647 result += sz;
1648 } else {
1649 result += sizeof(u64);
1650 }
1651 }
1652
1577 return result; 1653 return result;
1578} 1654}
1579 1655
@@ -1752,6 +1828,17 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
1752 array++; 1828 array++;
1753 } 1829 }
1754 1830
1831 if (type & PERF_SAMPLE_REGS_INTR) {
1832 if (sample->intr_regs.abi) {
1833 *array++ = sample->intr_regs.abi;
1834 sz = hweight_long(sample->intr_regs.mask) * sizeof(u64);
1835 memcpy(array, sample->intr_regs.regs, sz);
1836 array = (void *)array + sz;
1837 } else {
1838 *array++ = 0;
1839 }
1840 }
1841
1755 return 0; 1842 return 0;
1756} 1843}
1757 1844
@@ -1881,7 +1968,7 @@ static int sample_type__fprintf(FILE *fp, bool *first, u64 value)
1881 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU), 1968 bit_name(READ), bit_name(CALLCHAIN), bit_name(ID), bit_name(CPU),
1882 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW), 1969 bit_name(PERIOD), bit_name(STREAM_ID), bit_name(RAW),
1883 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER), 1970 bit_name(BRANCH_STACK), bit_name(REGS_USER), bit_name(STACK_USER),
1884 bit_name(IDENTIFIER), 1971 bit_name(IDENTIFIER), bit_name(REGS_INTR),
1885 { .name = NULL, } 1972 { .name = NULL, }
1886 }; 1973 };
1887#undef bit_name 1974#undef bit_name
@@ -2002,6 +2089,8 @@ bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2002int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 2089int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2003 int err, char *msg, size_t size) 2090 int err, char *msg, size_t size)
2004{ 2091{
2092 char sbuf[STRERR_BUFSIZE];
2093
2005 switch (err) { 2094 switch (err) {
2006 case EPERM: 2095 case EPERM:
2007 case EACCES: 2096 case EACCES:
@@ -2036,13 +2125,20 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2036 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it."); 2125 "No APIC? If so then you can boot the kernel with the \"lapic\" boot parameter to force-enable it.");
2037#endif 2126#endif
2038 break; 2127 break;
2128 case EBUSY:
2129 if (find_process("oprofiled"))
2130 return scnprintf(msg, size,
2131 "The PMU counters are busy/taken by another profiler.\n"
2132 "We found oprofile daemon running, please stop it and try again.");
2133 break;
2039 default: 2134 default:
2040 break; 2135 break;
2041 } 2136 }
2042 2137
2043 return scnprintf(msg, size, 2138 return scnprintf(msg, size,
2044 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s). \n" 2139 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2045 "/bin/dmesg may provide additional information.\n" 2140 "/bin/dmesg may provide additional information.\n"
2046 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2141 "No CONFIG_PERF_EVENTS=y kernel support configured?\n",
2047 err, strerror(err), perf_evsel__name(evsel)); 2142 err, strerror_r(err, sbuf, sizeof(sbuf)),
2143 perf_evsel__name(evsel));
2048} 2144}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index d7f93ce0ebc1..38622747d130 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -7,8 +7,6 @@
7#include <linux/perf_event.h> 7#include <linux/perf_event.h>
8#include <linux/types.h> 8#include <linux/types.h>
9#include "xyarray.h" 9#include "xyarray.h"
10#include "cgroup.h"
11#include "hist.h"
12#include "symbol.h" 10#include "symbol.h"
13 11
14struct perf_counts_values { 12struct perf_counts_values {
@@ -38,11 +36,16 @@ struct perf_sample_id {
38 struct hlist_node node; 36 struct hlist_node node;
39 u64 id; 37 u64 id;
40 struct perf_evsel *evsel; 38 struct perf_evsel *evsel;
39 int idx;
40 int cpu;
41 pid_t tid;
41 42
42 /* Holds total ID period value for PERF_SAMPLE_READ processing. */ 43 /* Holds total ID period value for PERF_SAMPLE_READ processing. */
43 u64 period; 44 u64 period;
44}; 45};
45 46
47struct cgroup_sel;
48
46/** struct perf_evsel - event selector 49/** struct perf_evsel - event selector
47 * 50 *
48 * @name - Can be set to retain the original event name passed by the user, 51 * @name - Can be set to retain the original event name passed by the user,
@@ -54,6 +57,7 @@ struct perf_sample_id {
54 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or 57 * @is_pos: the position (counting backwards) of the event id (PERF_SAMPLE_ID or
55 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all 58 * PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
56 * is used there is an id sample appended to non-sample events 59 * is used there is an id sample appended to non-sample events
60 * @priv: And what is in its containing unnamed union are tool specific
57 */ 61 */
58struct perf_evsel { 62struct perf_evsel {
59 struct list_head node; 63 struct list_head node;
@@ -66,14 +70,15 @@ struct perf_evsel {
66 struct perf_counts *prev_raw_counts; 70 struct perf_counts *prev_raw_counts;
67 int idx; 71 int idx;
68 u32 ids; 72 u32 ids;
69 struct hists hists;
70 char *name; 73 char *name;
71 double scale; 74 double scale;
72 const char *unit; 75 const char *unit;
76 bool snapshot;
73 struct event_format *tp_format; 77 struct event_format *tp_format;
74 union { 78 union {
75 void *priv; 79 void *priv;
76 off_t id_offset; 80 off_t id_offset;
81 u64 db_id;
77 }; 82 };
78 struct cgroup_sel *cgrp; 83 struct cgroup_sel *cgrp;
79 void *handler; 84 void *handler;
@@ -85,6 +90,10 @@ struct perf_evsel {
85 bool needs_swap; 90 bool needs_swap;
86 bool no_aux_samples; 91 bool no_aux_samples;
87 bool immediate; 92 bool immediate;
93 bool system_wide;
94 bool tracking;
95 bool per_pkg;
96 unsigned long *per_pkg_mask;
88 /* parse modifier helper */ 97 /* parse modifier helper */
89 int exclude_GH; 98 int exclude_GH;
90 int nr_members; 99 int nr_members;
@@ -98,13 +107,22 @@ union u64_swap {
98 u32 val32[2]; 107 u32 val32[2];
99}; 108};
100 109
101#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
102
103struct cpu_map; 110struct cpu_map;
111struct target;
104struct thread_map; 112struct thread_map;
105struct perf_evlist; 113struct perf_evlist;
106struct record_opts; 114struct record_opts;
107 115
116void perf_counts_values__scale(struct perf_counts_values *count,
117 bool scale, s8 *pscaled);
118
119void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
120 struct perf_counts_values *count);
121
122int perf_evsel__object_config(size_t object_size,
123 int (*init)(struct perf_evsel *evsel),
124 void (*fini)(struct perf_evsel *evsel));
125
108struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); 126struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
109 127
110static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) 128static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
@@ -151,12 +169,9 @@ const char *perf_evsel__name(struct perf_evsel *evsel);
151const char *perf_evsel__group_name(struct perf_evsel *evsel); 169const char *perf_evsel__group_name(struct perf_evsel *evsel);
152int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 170int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
153 171
154int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
155int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 172int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
156int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 173int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
157void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus); 174void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
158void perf_evsel__free_fd(struct perf_evsel *evsel);
159void perf_evsel__free_id(struct perf_evsel *evsel);
160void perf_evsel__free_counts(struct perf_evsel *evsel); 175void perf_evsel__free_counts(struct perf_evsel *evsel);
161void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 176void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
162 177
@@ -221,6 +236,13 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
221 (a)->attr.type == (b)->attr.type && \ 236 (a)->attr.type == (b)->attr.type && \
222 (a)->attr.config == (b)->attr.config) 237 (a)->attr.config == (b)->attr.config)
223 238
239typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,
240 int cpu, int thread,
241 struct perf_counts_values *count);
242
243int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
244 perf_evsel__read_cb_t cb);
245
224int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 246int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
225 int cpu, int thread, bool scale); 247 int cpu, int thread, bool scale);
226 248
@@ -250,37 +272,6 @@ static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
250 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true); 272 return __perf_evsel__read_on_cpu(evsel, cpu, thread, true);
251} 273}
252 274
253int __perf_evsel__read(struct perf_evsel *evsel, int ncpus, int nthreads,
254 bool scale);
255
256/**
257 * perf_evsel__read - Read the aggregate results on all CPUs
258 *
259 * @evsel - event selector to read value
260 * @ncpus - Number of cpus affected, from zero
261 * @nthreads - Number of threads affected, from zero
262 */
263static inline int perf_evsel__read(struct perf_evsel *evsel,
264 int ncpus, int nthreads)
265{
266 return __perf_evsel__read(evsel, ncpus, nthreads, false);
267}
268
269/**
270 * perf_evsel__read_scaled - Read the aggregate results on all CPUs, scaled
271 *
272 * @evsel - event selector to read value
273 * @ncpus - Number of cpus affected, from zero
274 * @nthreads - Number of threads affected, from zero
275 */
276static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
277 int ncpus, int nthreads)
278{
279 return __perf_evsel__read(evsel, ncpus, nthreads, true);
280}
281
282void hists__init(struct hists *hists);
283
284int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 275int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
285 struct perf_sample *sample); 276 struct perf_sample *sample);
286 277
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c
new file mode 100644
index 000000000000..95ef1cffc056
--- /dev/null
+++ b/tools/perf/util/find-vdso-map.c
@@ -0,0 +1,30 @@
1static int find_vdso_map(void **start, void **end)
2{
3 FILE *maps;
4 char line[128];
5 int found = 0;
6
7 maps = fopen("/proc/self/maps", "r");
8 if (!maps) {
9 fprintf(stderr, "vdso: cannot open maps\n");
10 return -1;
11 }
12
13 while (!found && fgets(line, sizeof(line), maps)) {
14 int m = -1;
15
16 /* We care only about private r-x mappings. */
17 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
18 start, end, &m))
19 continue;
20 if (m < 0)
21 continue;
22
23 if (!strncmp(&line[m], VDSO__MAP_NAME,
24 sizeof(VDSO__MAP_NAME) - 1))
25 found = 1;
26 }
27
28 fclose(maps);
29 return !found;
30}
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 158c787ce0c4..b20e40c74468 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -24,8 +24,6 @@
24#include "build-id.h" 24#include "build-id.h"
25#include "data.h" 25#include "data.h"
26 26
27static bool no_buildid_cache = false;
28
29static u32 header_argc; 27static u32 header_argc;
30static const char **header_argv; 28static const char **header_argv;
31 29
@@ -79,10 +77,7 @@ static int do_write(int fd, const void *buf, size_t size)
79 return 0; 77 return 0;
80} 78}
81 79
82#define NAME_ALIGN 64 80int write_padded(int fd, const void *bf, size_t count, size_t count_aligned)
83
84static int write_padded(int fd, const void *bf, size_t count,
85 size_t count_aligned)
86{ 81{
87 static const char zero_buf[NAME_ALIGN]; 82 static const char zero_buf[NAME_ALIGN];
88 int err = do_write(fd, bf, count); 83 int err = do_write(fd, bf, count);
@@ -171,336 +166,6 @@ perf_header__set_cmdline(int argc, const char **argv)
171 return 0; 166 return 0;
172} 167}
173 168
174#define dsos__for_each_with_build_id(pos, head) \
175 list_for_each_entry(pos, head, node) \
176 if (!pos->has_build_id) \
177 continue; \
178 else
179
180static int write_buildid(const char *name, size_t name_len, u8 *build_id,
181 pid_t pid, u16 misc, int fd)
182{
183 int err;
184 struct build_id_event b;
185 size_t len;
186
187 len = name_len + 1;
188 len = PERF_ALIGN(len, NAME_ALIGN);
189
190 memset(&b, 0, sizeof(b));
191 memcpy(&b.build_id, build_id, BUILD_ID_SIZE);
192 b.pid = pid;
193 b.header.misc = misc;
194 b.header.size = sizeof(b) + len;
195
196 err = do_write(fd, &b, sizeof(b));
197 if (err < 0)
198 return err;
199
200 return write_padded(fd, name, name_len + 1, len);
201}
202
203static int __dsos__hit_all(struct list_head *head)
204{
205 struct dso *pos;
206
207 list_for_each_entry(pos, head, node)
208 pos->hit = true;
209
210 return 0;
211}
212
213static int machine__hit_all_dsos(struct machine *machine)
214{
215 int err;
216
217 err = __dsos__hit_all(&machine->kernel_dsos);
218 if (err)
219 return err;
220
221 return __dsos__hit_all(&machine->user_dsos);
222}
223
224int dsos__hit_all(struct perf_session *session)
225{
226 struct rb_node *nd;
227 int err;
228
229 err = machine__hit_all_dsos(&session->machines.host);
230 if (err)
231 return err;
232
233 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
234 struct machine *pos = rb_entry(nd, struct machine, rb_node);
235
236 err = machine__hit_all_dsos(pos);
237 if (err)
238 return err;
239 }
240
241 return 0;
242}
243
244static int __dsos__write_buildid_table(struct list_head *head,
245 struct machine *machine,
246 pid_t pid, u16 misc, int fd)
247{
248 char nm[PATH_MAX];
249 struct dso *pos;
250
251 dsos__for_each_with_build_id(pos, head) {
252 int err;
253 const char *name;
254 size_t name_len;
255
256 if (!pos->hit)
257 continue;
258
259 if (dso__is_vdso(pos)) {
260 name = pos->short_name;
261 name_len = pos->short_name_len + 1;
262 } else if (dso__is_kcore(pos)) {
263 machine__mmap_name(machine, nm, sizeof(nm));
264 name = nm;
265 name_len = strlen(nm) + 1;
266 } else {
267 name = pos->long_name;
268 name_len = pos->long_name_len + 1;
269 }
270
271 err = write_buildid(name, name_len, pos->build_id,
272 pid, misc, fd);
273 if (err)
274 return err;
275 }
276
277 return 0;
278}
279
280static int machine__write_buildid_table(struct machine *machine, int fd)
281{
282 int err;
283 u16 kmisc = PERF_RECORD_MISC_KERNEL,
284 umisc = PERF_RECORD_MISC_USER;
285
286 if (!machine__is_host(machine)) {
287 kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
288 umisc = PERF_RECORD_MISC_GUEST_USER;
289 }
290
291 err = __dsos__write_buildid_table(&machine->kernel_dsos, machine,
292 machine->pid, kmisc, fd);
293 if (err == 0)
294 err = __dsos__write_buildid_table(&machine->user_dsos, machine,
295 machine->pid, umisc, fd);
296 return err;
297}
298
299static int dsos__write_buildid_table(struct perf_header *header, int fd)
300{
301 struct perf_session *session = container_of(header,
302 struct perf_session, header);
303 struct rb_node *nd;
304 int err = machine__write_buildid_table(&session->machines.host, fd);
305
306 if (err)
307 return err;
308
309 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
310 struct machine *pos = rb_entry(nd, struct machine, rb_node);
311 err = machine__write_buildid_table(pos, fd);
312 if (err)
313 break;
314 }
315 return err;
316}
317
318int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
319 const char *name, bool is_kallsyms, bool is_vdso)
320{
321 const size_t size = PATH_MAX;
322 char *realname, *filename = zalloc(size),
323 *linkname = zalloc(size), *targetname;
324 int len, err = -1;
325 bool slash = is_kallsyms || is_vdso;
326
327 if (is_kallsyms) {
328 if (symbol_conf.kptr_restrict) {
329 pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
330 err = 0;
331 goto out_free;
332 }
333 realname = (char *) name;
334 } else
335 realname = realpath(name, NULL);
336
337 if (realname == NULL || filename == NULL || linkname == NULL)
338 goto out_free;
339
340 len = scnprintf(filename, size, "%s%s%s",
341 debugdir, slash ? "/" : "",
342 is_vdso ? DSO__NAME_VDSO : realname);
343 if (mkdir_p(filename, 0755))
344 goto out_free;
345
346 snprintf(filename + len, size - len, "/%s", sbuild_id);
347
348 if (access(filename, F_OK)) {
349 if (is_kallsyms) {
350 if (copyfile("/proc/kallsyms", filename))
351 goto out_free;
352 } else if (link(realname, filename) && copyfile(name, filename))
353 goto out_free;
354 }
355
356 len = scnprintf(linkname, size, "%s/.build-id/%.2s",
357 debugdir, sbuild_id);
358
359 if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
360 goto out_free;
361
362 snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
363 targetname = filename + strlen(debugdir) - 5;
364 memcpy(targetname, "../..", 5);
365
366 if (symlink(targetname, linkname) == 0)
367 err = 0;
368out_free:
369 if (!is_kallsyms)
370 free(realname);
371 free(filename);
372 free(linkname);
373 return err;
374}
375
376static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
377 const char *name, const char *debugdir,
378 bool is_kallsyms, bool is_vdso)
379{
380 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
381
382 build_id__sprintf(build_id, build_id_size, sbuild_id);
383
384 return build_id_cache__add_s(sbuild_id, debugdir, name,
385 is_kallsyms, is_vdso);
386}
387
388int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
389{
390 const size_t size = PATH_MAX;
391 char *filename = zalloc(size),
392 *linkname = zalloc(size);
393 int err = -1;
394
395 if (filename == NULL || linkname == NULL)
396 goto out_free;
397
398 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
399 debugdir, sbuild_id, sbuild_id + 2);
400
401 if (access(linkname, F_OK))
402 goto out_free;
403
404 if (readlink(linkname, filename, size - 1) < 0)
405 goto out_free;
406
407 if (unlink(linkname))
408 goto out_free;
409
410 /*
411 * Since the link is relative, we must make it absolute:
412 */
413 snprintf(linkname, size, "%s/.build-id/%.2s/%s",
414 debugdir, sbuild_id, filename);
415
416 if (unlink(linkname))
417 goto out_free;
418
419 err = 0;
420out_free:
421 free(filename);
422 free(linkname);
423 return err;
424}
425
426static int dso__cache_build_id(struct dso *dso, struct machine *machine,
427 const char *debugdir)
428{
429 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
430 bool is_vdso = dso__is_vdso(dso);
431 const char *name = dso->long_name;
432 char nm[PATH_MAX];
433
434 if (dso__is_kcore(dso)) {
435 is_kallsyms = true;
436 machine__mmap_name(machine, nm, sizeof(nm));
437 name = nm;
438 }
439 return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id), name,
440 debugdir, is_kallsyms, is_vdso);
441}
442
443static int __dsos__cache_build_ids(struct list_head *head,
444 struct machine *machine, const char *debugdir)
445{
446 struct dso *pos;
447 int err = 0;
448
449 dsos__for_each_with_build_id(pos, head)
450 if (dso__cache_build_id(pos, machine, debugdir))
451 err = -1;
452
453 return err;
454}
455
456static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
457{
458 int ret = __dsos__cache_build_ids(&machine->kernel_dsos, machine,
459 debugdir);
460 ret |= __dsos__cache_build_ids(&machine->user_dsos, machine, debugdir);
461 return ret;
462}
463
464static int perf_session__cache_build_ids(struct perf_session *session)
465{
466 struct rb_node *nd;
467 int ret;
468 char debugdir[PATH_MAX];
469
470 snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
471
472 if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
473 return -1;
474
475 ret = machine__cache_build_ids(&session->machines.host, debugdir);
476
477 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
478 struct machine *pos = rb_entry(nd, struct machine, rb_node);
479 ret |= machine__cache_build_ids(pos, debugdir);
480 }
481 return ret ? -1 : 0;
482}
483
484static bool machine__read_build_ids(struct machine *machine, bool with_hits)
485{
486 bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
487 ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
488 return ret;
489}
490
491static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
492{
493 struct rb_node *nd;
494 bool ret = machine__read_build_ids(&session->machines.host, with_hits);
495
496 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
497 struct machine *pos = rb_entry(nd, struct machine, rb_node);
498 ret |= machine__read_build_ids(pos, with_hits);
499 }
500
501 return ret;
502}
503
504static int write_tracing_data(int fd, struct perf_header *h __maybe_unused, 169static int write_tracing_data(int fd, struct perf_header *h __maybe_unused,
505 struct perf_evlist *evlist) 170 struct perf_evlist *evlist)
506{ 171{
@@ -519,13 +184,12 @@ static int write_build_id(int fd, struct perf_header *h,
519 if (!perf_session__read_build_ids(session, true)) 184 if (!perf_session__read_build_ids(session, true))
520 return -1; 185 return -1;
521 186
522 err = dsos__write_buildid_table(h, fd); 187 err = perf_session__write_buildid_table(session, fd);
523 if (err < 0) { 188 if (err < 0) {
524 pr_debug("failed to write buildid table\n"); 189 pr_debug("failed to write buildid table\n");
525 return err; 190 return err;
526 } 191 }
527 if (!no_buildid_cache) 192 perf_session__cache_build_ids(session);
528 perf_session__cache_build_ids(session);
529 193
530 return 0; 194 return 0;
531} 195}
@@ -575,16 +239,12 @@ static int write_version(int fd, struct perf_header *h __maybe_unused,
575 return do_write_string(fd, perf_version_string); 239 return do_write_string(fd, perf_version_string);
576} 240}
577 241
578static int write_cpudesc(int fd, struct perf_header *h __maybe_unused, 242static int __write_cpudesc(int fd, const char *cpuinfo_proc)
579 struct perf_evlist *evlist __maybe_unused)
580{ 243{
581#ifndef CPUINFO_PROC
582#define CPUINFO_PROC NULL
583#endif
584 FILE *file; 244 FILE *file;
585 char *buf = NULL; 245 char *buf = NULL;
586 char *s, *p; 246 char *s, *p;
587 const char *search = CPUINFO_PROC; 247 const char *search = cpuinfo_proc;
588 size_t len = 0; 248 size_t len = 0;
589 int ret = -1; 249 int ret = -1;
590 250
@@ -601,8 +261,10 @@ static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
601 break; 261 break;
602 } 262 }
603 263
604 if (ret) 264 if (ret) {
265 ret = -1;
605 goto done; 266 goto done;
267 }
606 268
607 s = buf; 269 s = buf;
608 270
@@ -634,6 +296,25 @@ done:
634 return ret; 296 return ret;
635} 297}
636 298
299static int write_cpudesc(int fd, struct perf_header *h __maybe_unused,
300 struct perf_evlist *evlist __maybe_unused)
301{
302#ifndef CPUINFO_PROC
303#define CPUINFO_PROC {"model name", }
304#endif
305 const char *cpuinfo_procs[] = CPUINFO_PROC;
306 unsigned int i;
307
308 for (i = 0; i < ARRAY_SIZE(cpuinfo_procs); i++) {
309 int ret;
310 ret = __write_cpudesc(fd, cpuinfo_procs[i]);
311 if (ret >= 0)
312 return ret;
313 }
314 return -1;
315}
316
317
637static int write_nrcpus(int fd, struct perf_header *h __maybe_unused, 318static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
638 struct perf_evlist *evlist __maybe_unused) 319 struct perf_evlist *evlist __maybe_unused)
639{ 320{
@@ -946,7 +627,8 @@ static int write_total_mem(int fd, struct perf_header *h __maybe_unused,
946 n = sscanf(buf, "%*s %"PRIu64, &mem); 627 n = sscanf(buf, "%*s %"PRIu64, &mem);
947 if (n == 1) 628 if (n == 1)
948 ret = do_write(fd, &mem, sizeof(mem)); 629 ret = do_write(fd, &mem, sizeof(mem));
949 } 630 } else
631 ret = -1;
950 free(buf); 632 free(buf);
951 fclose(fp); 633 fclose(fp);
952 return ret; 634 return ret;
@@ -1548,7 +1230,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1548 struct perf_session *session) 1230 struct perf_session *session)
1549{ 1231{
1550 int err = -1; 1232 int err = -1;
1551 struct list_head *head; 1233 struct dsos *dsos;
1552 struct machine *machine; 1234 struct machine *machine;
1553 u16 misc; 1235 u16 misc;
1554 struct dso *dso; 1236 struct dso *dso;
@@ -1563,28 +1245,28 @@ static int __event_process_build_id(struct build_id_event *bev,
1563 switch (misc) { 1245 switch (misc) {
1564 case PERF_RECORD_MISC_KERNEL: 1246 case PERF_RECORD_MISC_KERNEL:
1565 dso_type = DSO_TYPE_KERNEL; 1247 dso_type = DSO_TYPE_KERNEL;
1566 head = &machine->kernel_dsos; 1248 dsos = &machine->kernel_dsos;
1567 break; 1249 break;
1568 case PERF_RECORD_MISC_GUEST_KERNEL: 1250 case PERF_RECORD_MISC_GUEST_KERNEL:
1569 dso_type = DSO_TYPE_GUEST_KERNEL; 1251 dso_type = DSO_TYPE_GUEST_KERNEL;
1570 head = &machine->kernel_dsos; 1252 dsos = &machine->kernel_dsos;
1571 break; 1253 break;
1572 case PERF_RECORD_MISC_USER: 1254 case PERF_RECORD_MISC_USER:
1573 case PERF_RECORD_MISC_GUEST_USER: 1255 case PERF_RECORD_MISC_GUEST_USER:
1574 dso_type = DSO_TYPE_USER; 1256 dso_type = DSO_TYPE_USER;
1575 head = &machine->user_dsos; 1257 dsos = &machine->user_dsos;
1576 break; 1258 break;
1577 default: 1259 default:
1578 goto out; 1260 goto out;
1579 } 1261 }
1580 1262
1581 dso = __dsos__findnew(head, filename); 1263 dso = __dsos__findnew(dsos, filename);
1582 if (dso != NULL) { 1264 if (dso != NULL) {
1583 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1265 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
1584 1266
1585 dso__set_build_id(dso, &bev->build_id); 1267 dso__set_build_id(dso, &bev->build_id);
1586 1268
1587 if (filename[0] == '[') 1269 if (!is_kernel_module(filename, NULL))
1588 dso->kernel = dso_type; 1270 dso->kernel = dso_type;
1589 1271
1590 build_id__sprintf(dso->build_id, sizeof(dso->build_id), 1272 build_id__sprintf(dso->build_id, sizeof(dso->build_id),
@@ -2458,6 +2140,7 @@ static const int attr_file_abi_sizes[] = {
2458 [1] = PERF_ATTR_SIZE_VER1, 2140 [1] = PERF_ATTR_SIZE_VER1,
2459 [2] = PERF_ATTR_SIZE_VER2, 2141 [2] = PERF_ATTR_SIZE_VER2,
2460 [3] = PERF_ATTR_SIZE_VER3, 2142 [3] = PERF_ATTR_SIZE_VER3,
2143 [4] = PERF_ATTR_SIZE_VER4,
2461 0, 2144 0,
2462}; 2145};
2463 2146
@@ -3105,8 +2788,3 @@ int perf_event__process_build_id(struct perf_tool *tool __maybe_unused,
3105 session); 2788 session);
3106 return 0; 2789 return 0;
3107} 2790}
3108
3109void disable_buildid_cache(void)
3110{
3111 no_buildid_cache = true;
3112}
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 8f5cbaea64a5..3bb90ac172a1 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -122,10 +122,6 @@ int perf_header__process_sections(struct perf_header *header, int fd,
122 122
123int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); 123int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full);
124 124
125int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
126 const char *name, bool is_kallsyms, bool is_vdso);
127int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
128
129int perf_event__synthesize_attr(struct perf_tool *tool, 125int perf_event__synthesize_attr(struct perf_tool *tool,
130 struct perf_event_attr *attr, u32 ids, u64 *id, 126 struct perf_event_attr *attr, u32 ids, u64 *id,
131 perf_event__handler_t process); 127 perf_event__handler_t process);
@@ -151,7 +147,9 @@ int perf_event__process_build_id(struct perf_tool *tool,
151 struct perf_session *session); 147 struct perf_session *session);
152bool is_perf_magic(u64 magic); 148bool is_perf_magic(u64 magic);
153 149
154int dsos__hit_all(struct perf_session *session); 150#define NAME_ALIGN 64
151
152int write_padded(int fd, const void *bf, size_t count, size_t count_aligned);
155 153
156/* 154/*
157 * arch specific callback 155 * arch specific callback
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 30df6187ee02..182395546ddc 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -3,8 +3,10 @@
3#include "hist.h" 3#include "hist.h"
4#include "session.h" 4#include "session.h"
5#include "sort.h" 5#include "sort.h"
6#include "evlist.h"
6#include "evsel.h" 7#include "evsel.h"
7#include "annotate.h" 8#include "annotate.h"
9#include "ui/progress.h"
8#include <math.h> 10#include <math.h>
9 11
10static bool hists__filter_entry_by_dso(struct hists *hists, 12static bool hists__filter_entry_by_dso(struct hists *hists,
@@ -14,13 +16,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
14static bool hists__filter_entry_by_symbol(struct hists *hists, 16static bool hists__filter_entry_by_symbol(struct hists *hists,
15 struct hist_entry *he); 17 struct hist_entry *he);
16 18
17struct callchain_param callchain_param = {
18 .mode = CHAIN_GRAPH_REL,
19 .min_percent = 0.5,
20 .order = ORDER_CALLEE,
21 .key = CCKEY_FUNCTION
22};
23
24u16 hists__col_len(struct hists *hists, enum hist_column col) 19u16 hists__col_len(struct hists *hists, enum hist_column col)
25{ 20{
26 return hists->col_len[col]; 21 return hists->col_len[col];
@@ -277,6 +272,28 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
277 } 272 }
278} 273}
279 274
275void hists__delete_entries(struct hists *hists)
276{
277 struct rb_node *next = rb_first(&hists->entries);
278 struct hist_entry *n;
279
280 while (next) {
281 n = rb_entry(next, struct hist_entry, rb_node);
282 next = rb_next(&n->rb_node);
283
284 rb_erase(&n->rb_node, &hists->entries);
285
286 if (sort__need_collapse)
287 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
288
289 --hists->nr_entries;
290 if (!n->filtered)
291 --hists->nr_non_filtered_entries;
292
293 hist_entry__free(n);
294 }
295}
296
280/* 297/*
281 * histogram, sorted on item, collects periods 298 * histogram, sorted on item, collects periods
282 */ 299 */
@@ -287,7 +304,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
287 size_t callchain_size = 0; 304 size_t callchain_size = 0;
288 struct hist_entry *he; 305 struct hist_entry *he;
289 306
290 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) 307 if (symbol_conf.use_callchain)
291 callchain_size = sizeof(struct callchain_root); 308 callchain_size = sizeof(struct callchain_root);
292 309
293 he = zalloc(sizeof(*he) + callchain_size); 310 he = zalloc(sizeof(*he) + callchain_size);
@@ -494,6 +511,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
494{ 511{
495 u64 cost; 512 u64 cost;
496 struct mem_info *mi = iter->priv; 513 struct mem_info *mi = iter->priv;
514 struct hists *hists = evsel__hists(iter->evsel);
497 struct hist_entry *he; 515 struct hist_entry *he;
498 516
499 if (mi == NULL) 517 if (mi == NULL)
@@ -510,7 +528,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
510 * and this is indirectly achieved by passing period=weight here 528 * and this is indirectly achieved by passing period=weight here
511 * and the he_stat__add_period() function. 529 * and the he_stat__add_period() function.
512 */ 530 */
513 he = __hists__add_entry(&iter->evsel->hists, al, iter->parent, NULL, mi, 531 he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
514 cost, cost, 0, true); 532 cost, cost, 0, true);
515 if (!he) 533 if (!he)
516 return -ENOMEM; 534 return -ENOMEM;
@@ -524,13 +542,14 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
524 struct addr_location *al __maybe_unused) 542 struct addr_location *al __maybe_unused)
525{ 543{
526 struct perf_evsel *evsel = iter->evsel; 544 struct perf_evsel *evsel = iter->evsel;
545 struct hists *hists = evsel__hists(evsel);
527 struct hist_entry *he = iter->he; 546 struct hist_entry *he = iter->he;
528 int err = -EINVAL; 547 int err = -EINVAL;
529 548
530 if (he == NULL) 549 if (he == NULL)
531 goto out; 550 goto out;
532 551
533 hists__inc_nr_samples(&evsel->hists, he->filtered); 552 hists__inc_nr_samples(hists, he->filtered);
534 553
535 err = hist_entry__append_callchain(he, iter->sample); 554 err = hist_entry__append_callchain(he, iter->sample);
536 555
@@ -596,6 +615,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
596{ 615{
597 struct branch_info *bi; 616 struct branch_info *bi;
598 struct perf_evsel *evsel = iter->evsel; 617 struct perf_evsel *evsel = iter->evsel;
618 struct hists *hists = evsel__hists(evsel);
599 struct hist_entry *he = NULL; 619 struct hist_entry *he = NULL;
600 int i = iter->curr; 620 int i = iter->curr;
601 int err = 0; 621 int err = 0;
@@ -609,12 +629,12 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
609 * The report shows the percentage of total branches captured 629 * The report shows the percentage of total branches captured
610 * and not events sampled. Thus we use a pseudo period of 1. 630 * and not events sampled. Thus we use a pseudo period of 1.
611 */ 631 */
612 he = __hists__add_entry(&evsel->hists, al, iter->parent, &bi[i], NULL, 632 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
613 1, 1, 0, true); 633 1, 1, 0, true);
614 if (he == NULL) 634 if (he == NULL)
615 return -ENOMEM; 635 return -ENOMEM;
616 636
617 hists__inc_nr_samples(&evsel->hists, he->filtered); 637 hists__inc_nr_samples(hists, he->filtered);
618 638
619out: 639out:
620 iter->he = he; 640 iter->he = he;
@@ -646,7 +666,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
646 struct perf_sample *sample = iter->sample; 666 struct perf_sample *sample = iter->sample;
647 struct hist_entry *he; 667 struct hist_entry *he;
648 668
649 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 669 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
650 sample->period, sample->weight, 670 sample->period, sample->weight,
651 sample->transaction, true); 671 sample->transaction, true);
652 if (he == NULL) 672 if (he == NULL)
@@ -669,7 +689,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
669 689
670 iter->he = NULL; 690 iter->he = NULL;
671 691
672 hists__inc_nr_samples(&evsel->hists, he->filtered); 692 hists__inc_nr_samples(evsel__hists(evsel), he->filtered);
673 693
674 return hist_entry__append_callchain(he, sample); 694 return hist_entry__append_callchain(he, sample);
675} 695}
@@ -702,12 +722,13 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
702 struct addr_location *al) 722 struct addr_location *al)
703{ 723{
704 struct perf_evsel *evsel = iter->evsel; 724 struct perf_evsel *evsel = iter->evsel;
725 struct hists *hists = evsel__hists(evsel);
705 struct perf_sample *sample = iter->sample; 726 struct perf_sample *sample = iter->sample;
706 struct hist_entry **he_cache = iter->priv; 727 struct hist_entry **he_cache = iter->priv;
707 struct hist_entry *he; 728 struct hist_entry *he;
708 int err = 0; 729 int err = 0;
709 730
710 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 731 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
711 sample->period, sample->weight, 732 sample->period, sample->weight,
712 sample->transaction, true); 733 sample->transaction, true);
713 if (he == NULL) 734 if (he == NULL)
@@ -716,7 +737,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
716 iter->he = he; 737 iter->he = he;
717 he_cache[iter->curr++] = he; 738 he_cache[iter->curr++] = he;
718 739
719 callchain_append(he->callchain, &callchain_cursor, sample->period); 740 hist_entry__append_callchain(he, sample);
720 741
721 /* 742 /*
722 * We need to re-initialize the cursor since callchain_append() 743 * We need to re-initialize the cursor since callchain_append()
@@ -724,7 +745,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
724 */ 745 */
725 callchain_cursor_commit(&callchain_cursor); 746 callchain_cursor_commit(&callchain_cursor);
726 747
727 hists__inc_nr_samples(&evsel->hists, he->filtered); 748 hists__inc_nr_samples(hists, he->filtered);
728 749
729 return err; 750 return err;
730} 751}
@@ -780,7 +801,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
780 } 801 }
781 } 802 }
782 803
783 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 804 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
784 sample->period, sample->weight, 805 sample->period, sample->weight,
785 sample->transaction, false); 806 sample->transaction, false);
786 if (he == NULL) 807 if (he == NULL)
@@ -789,7 +810,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
789 iter->he = he; 810 iter->he = he;
790 he_cache[iter->curr++] = he; 811 he_cache[iter->curr++] = he;
791 812
792 callchain_append(he->callchain, &cursor, sample->period); 813 if (symbol_conf.use_callchain)
814 callchain_append(he->callchain, &cursor, sample->period);
793 return 0; 815 return 0;
794} 816}
795 817
@@ -925,6 +947,7 @@ void hist_entry__free(struct hist_entry *he)
925 zfree(&he->mem_info); 947 zfree(&he->mem_info);
926 zfree(&he->stat_acc); 948 zfree(&he->stat_acc);
927 free_srcline(he->srcline); 949 free_srcline(he->srcline);
950 free_callchain(he->callchain);
928 free(he); 951 free(he);
929} 952}
930 953
@@ -967,6 +990,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
967 else 990 else
968 p = &(*p)->rb_right; 991 p = &(*p)->rb_right;
969 } 992 }
993 hists->nr_entries++;
970 994
971 rb_link_node(&he->rb_node_in, parent, p); 995 rb_link_node(&he->rb_node_in, parent, p);
972 rb_insert_color(&he->rb_node_in, root); 996 rb_insert_color(&he->rb_node_in, root);
@@ -1004,7 +1028,10 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
1004 if (!sort__need_collapse) 1028 if (!sort__need_collapse)
1005 return; 1029 return;
1006 1030
1031 hists->nr_entries = 0;
1032
1007 root = hists__get_rotate_entries_in(hists); 1033 root = hists__get_rotate_entries_in(hists);
1034
1008 next = rb_first(root); 1035 next = rb_first(root);
1009 1036
1010 while (next) { 1037 while (next) {
@@ -1099,7 +1126,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
1099 rb_insert_color(&he->rb_node, entries); 1126 rb_insert_color(&he->rb_node, entries);
1100} 1127}
1101 1128
1102void hists__output_resort(struct hists *hists) 1129void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1103{ 1130{
1104 struct rb_root *root; 1131 struct rb_root *root;
1105 struct rb_node *next; 1132 struct rb_node *next;
@@ -1128,6 +1155,9 @@ void hists__output_resort(struct hists *hists)
1128 1155
1129 if (!n->filtered) 1156 if (!n->filtered)
1130 hists__calc_col_len(hists, n); 1157 hists__calc_col_len(hists, n);
1158
1159 if (prog)
1160 ui_progress__update(prog, 1);
1131 } 1161 }
1132} 1162}
1133 1163
@@ -1386,6 +1416,21 @@ int hists__link(struct hists *leader, struct hists *other)
1386 return 0; 1416 return 0;
1387} 1417}
1388 1418
1419
1420size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
1421{
1422 struct perf_evsel *pos;
1423 size_t ret = 0;
1424
1425 evlist__for_each(evlist, pos) {
1426 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1427 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
1428 }
1429
1430 return ret;
1431}
1432
1433
1389u64 hists__total_period(struct hists *hists) 1434u64 hists__total_period(struct hists *hists)
1390{ 1435{
1391 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period : 1436 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
@@ -1412,3 +1457,31 @@ int perf_hist_config(const char *var, const char *value)
1412 1457
1413 return 0; 1458 return 0;
1414} 1459}
1460
1461static int hists_evsel__init(struct perf_evsel *evsel)
1462{
1463 struct hists *hists = evsel__hists(evsel);
1464
1465 memset(hists, 0, sizeof(*hists));
1466 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1467 hists->entries_in = &hists->entries_in_array[0];
1468 hists->entries_collapsed = RB_ROOT;
1469 hists->entries = RB_ROOT;
1470 pthread_mutex_init(&hists->lock, NULL);
1471 return 0;
1472}
1473
1474/*
1475 * XXX We probably need a hists_evsel__exit() to free the hist_entries
1476 * stored in the rbtree...
1477 */
1478
1479int hists__init(void)
1480{
1481 int err = perf_evsel__object_config(sizeof(struct hists_evsel),
1482 hists_evsel__init, NULL);
1483 if (err)
1484 fputs("FATAL ERROR: Couldn't setup hists class\n", stderr);
1485
1486 return err;
1487}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 742f49a85725..46bd50344f85 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -4,12 +4,11 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <pthread.h> 5#include <pthread.h>
6#include "callchain.h" 6#include "callchain.h"
7#include "evsel.h"
7#include "header.h" 8#include "header.h"
8#include "color.h" 9#include "color.h"
9#include "ui/progress.h" 10#include "ui/progress.h"
10 11
11extern struct callchain_param callchain_param;
12
13struct hist_entry; 12struct hist_entry;
14struct addr_location; 13struct addr_location;
15struct symbol; 14struct symbol;
@@ -23,32 +22,6 @@ enum hist_filter {
23 HIST_FILTER__HOST, 22 HIST_FILTER__HOST,
24}; 23};
25 24
26/*
27 * The kernel collects the number of events it couldn't send in a stretch and
28 * when possible sends this number in a PERF_RECORD_LOST event. The number of
29 * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
30 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
31 * the sum of all struct lost_event.lost fields reported.
32 *
33 * The total_period is needed because by default auto-freq is used, so
34 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
35 * the total number of low level events, it is necessary to to sum all struct
36 * sample_event.period and stash the result in total_period.
37 */
38struct events_stats {
39 u64 total_period;
40 u64 total_non_filtered_period;
41 u64 total_lost;
42 u64 total_invalid_chains;
43 u32 nr_events[PERF_RECORD_HEADER_MAX];
44 u32 nr_non_filtered_samples;
45 u32 nr_lost_warned;
46 u32 nr_unknown_events;
47 u32 nr_invalid_chains;
48 u32 nr_unknown_id;
49 u32 nr_unprocessable_samples;
50};
51
52enum hist_column { 25enum hist_column {
53 HISTC_SYMBOL, 26 HISTC_SYMBOL,
54 HISTC_DSO, 27 HISTC_DSO,
@@ -148,10 +121,11 @@ int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
148 struct hists *hists); 121 struct hists *hists);
149void hist_entry__free(struct hist_entry *); 122void hist_entry__free(struct hist_entry *);
150 123
151void hists__output_resort(struct hists *hists); 124void hists__output_resort(struct hists *hists, struct ui_progress *prog);
152void hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 125void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
153 126
154void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 127void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
128void hists__delete_entries(struct hists *hists);
155void hists__output_recalc_col_len(struct hists *hists, int max_rows); 129void hists__output_recalc_col_len(struct hists *hists, int max_rows);
156 130
157u64 hists__total_period(struct hists *hists); 131u64 hists__total_period(struct hists *hists);
@@ -164,6 +138,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
164 138
165size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 139size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
166 int max_cols, float min_pcnt, FILE *fp); 140 int max_cols, float min_pcnt, FILE *fp);
141size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp);
167 142
168void hists__filter_by_dso(struct hists *hists); 143void hists__filter_by_dso(struct hists *hists);
169void hists__filter_by_thread(struct hists *hists); 144void hists__filter_by_thread(struct hists *hists);
@@ -184,6 +159,25 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
184void hists__match(struct hists *leader, struct hists *other); 159void hists__match(struct hists *leader, struct hists *other);
185int hists__link(struct hists *leader, struct hists *other); 160int hists__link(struct hists *leader, struct hists *other);
186 161
162struct hists_evsel {
163 struct perf_evsel evsel;
164 struct hists hists;
165};
166
167static inline struct perf_evsel *hists_to_evsel(struct hists *hists)
168{
169 struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists);
170 return &hevsel->evsel;
171}
172
173static inline struct hists *evsel__hists(struct perf_evsel *evsel)
174{
175 struct hists_evsel *hevsel = (struct hists_evsel *)evsel;
176 return &hevsel->hists;
177}
178
179int hists__init(void);
180
187struct perf_hpp { 181struct perf_hpp {
188 char *buf; 182 char *buf;
189 size_t size; 183 size_t size;
@@ -192,6 +186,7 @@ struct perf_hpp {
192}; 186};
193 187
194struct perf_hpp_fmt { 188struct perf_hpp_fmt {
189 const char *name;
195 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 190 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
196 struct perf_evsel *evsel); 191 struct perf_evsel *evsel);
197 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 192 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -207,6 +202,8 @@ struct perf_hpp_fmt {
207 struct list_head list; 202 struct list_head list;
208 struct list_head sort_list; 203 struct list_head sort_list;
209 bool elide; 204 bool elide;
205 int len;
206 int user_len;
210}; 207};
211 208
212extern struct list_head perf_hpp__list; 209extern struct list_head perf_hpp__list;
@@ -261,17 +258,19 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format)
261} 258}
262 259
263void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 260void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
261void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
262void perf_hpp__set_user_width(const char *width_list_str);
264 263
265typedef u64 (*hpp_field_fn)(struct hist_entry *he); 264typedef u64 (*hpp_field_fn)(struct hist_entry *he);
266typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 265typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
267typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...); 266typedef int (*hpp_snprint_fn)(struct perf_hpp *hpp, const char *fmt, ...);
268 267
269int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he, 268int hpp__fmt(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
270 hpp_field_fn get_field, const char *fmt, 269 struct hist_entry *he, hpp_field_fn get_field,
271 hpp_snprint_fn print_fn, bool fmt_percent); 270 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
272int __hpp__fmt_acc(struct perf_hpp *hpp, struct hist_entry *he, 271int hpp__fmt_acc(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
273 hpp_field_fn get_field, const char *fmt, 272 struct hist_entry *he, hpp_field_fn get_field,
274 hpp_snprint_fn print_fn, bool fmt_percent); 273 const char *fmtstr, hpp_snprint_fn print_fn, bool fmt_percent);
275 274
276static inline void advance_hpp(struct perf_hpp *hpp, int inc) 275static inline void advance_hpp(struct perf_hpp *hpp, int inc)
277{ 276{
diff --git a/tools/perf/util/include/asm/hash.h b/tools/perf/util/include/asm/hash.h
deleted file mode 100644
index d82b170bb216..000000000000
--- a/tools/perf/util/include/asm/hash.h
+++ /dev/null
@@ -1,6 +0,0 @@
1#ifndef __ASM_GENERIC_HASH_H
2#define __ASM_GENERIC_HASH_H
3
4/* Stub */
5
6#endif /* __ASM_GENERIC_HASH_H */
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index 01ffd12dc791..40bd21488032 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -46,4 +46,21 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
46 __bitmap_or(dst, src1, src2, nbits); 46 __bitmap_or(dst, src1, src2, nbits);
47} 47}
48 48
49/**
50 * test_and_set_bit - Set a bit and return its old value
51 * @nr: Bit to set
52 * @addr: Address to count from
53 */
54static inline int test_and_set_bit(int nr, unsigned long *addr)
55{
56 unsigned long mask = BIT_MASK(nr);
57 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
58 unsigned long old;
59
60 old = *p;
61 *p = old | mask;
62
63 return (old & mask) != 0;
64}
65
49#endif /* _PERF_BITOPS_H */ 66#endif /* _PERF_BITOPS_H */
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
deleted file mode 100644
index dadfa7e54287..000000000000
--- a/tools/perf/util/include/linux/bitops.h
+++ /dev/null
@@ -1,160 +0,0 @@
1#ifndef _PERF_LINUX_BITOPS_H_
2#define _PERF_LINUX_BITOPS_H_
3
4#include <linux/kernel.h>
5#include <linux/compiler.h>
6#include <asm/hweight.h>
7
8#ifndef __WORDSIZE
9#define __WORDSIZE (__SIZEOF_LONG__ * 8)
10#endif
11
12#define BITS_PER_LONG __WORDSIZE
13#define BITS_PER_BYTE 8
14#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
15#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
16#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
17#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
18
19#define for_each_set_bit(bit, addr, size) \
20 for ((bit) = find_first_bit((addr), (size)); \
21 (bit) < (size); \
22 (bit) = find_next_bit((addr), (size), (bit) + 1))
23
24/* same as for_each_set_bit() but use bit as value to start with */
25#define for_each_set_bit_from(bit, addr, size) \
26 for ((bit) = find_next_bit((addr), (size), (bit)); \
27 (bit) < (size); \
28 (bit) = find_next_bit((addr), (size), (bit) + 1))
29
30static inline void set_bit(int nr, unsigned long *addr)
31{
32 addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
33}
34
35static inline void clear_bit(int nr, unsigned long *addr)
36{
37 addr[nr / BITS_PER_LONG] &= ~(1UL << (nr % BITS_PER_LONG));
38}
39
40static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
41{
42 return ((1UL << (nr % BITS_PER_LONG)) &
43 (((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
44}
45
46static inline unsigned long hweight_long(unsigned long w)
47{
48 return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
49}
50
51#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
52
53/**
54 * __ffs - find first bit in word.
55 * @word: The word to search
56 *
57 * Undefined if no bit exists, so code should check against 0 first.
58 */
59static __always_inline unsigned long __ffs(unsigned long word)
60{
61 int num = 0;
62
63#if BITS_PER_LONG == 64
64 if ((word & 0xffffffff) == 0) {
65 num += 32;
66 word >>= 32;
67 }
68#endif
69 if ((word & 0xffff) == 0) {
70 num += 16;
71 word >>= 16;
72 }
73 if ((word & 0xff) == 0) {
74 num += 8;
75 word >>= 8;
76 }
77 if ((word & 0xf) == 0) {
78 num += 4;
79 word >>= 4;
80 }
81 if ((word & 0x3) == 0) {
82 num += 2;
83 word >>= 2;
84 }
85 if ((word & 0x1) == 0)
86 num += 1;
87 return num;
88}
89
90typedef const unsigned long __attribute__((__may_alias__)) long_alias_t;
91
92/*
93 * Find the first set bit in a memory region.
94 */
95static inline unsigned long
96find_first_bit(const unsigned long *addr, unsigned long size)
97{
98 long_alias_t *p = (long_alias_t *) addr;
99 unsigned long result = 0;
100 unsigned long tmp;
101
102 while (size & ~(BITS_PER_LONG-1)) {
103 if ((tmp = *(p++)))
104 goto found;
105 result += BITS_PER_LONG;
106 size -= BITS_PER_LONG;
107 }
108 if (!size)
109 return result;
110
111 tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
112 if (tmp == 0UL) /* Are any bits set? */
113 return result + size; /* Nope. */
114found:
115 return result + __ffs(tmp);
116}
117
118/*
119 * Find the next set bit in a memory region.
120 */
121static inline unsigned long
122find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
123{
124 const unsigned long *p = addr + BITOP_WORD(offset);
125 unsigned long result = offset & ~(BITS_PER_LONG-1);
126 unsigned long tmp;
127
128 if (offset >= size)
129 return size;
130 size -= result;
131 offset %= BITS_PER_LONG;
132 if (offset) {
133 tmp = *(p++);
134 tmp &= (~0UL << offset);
135 if (size < BITS_PER_LONG)
136 goto found_first;
137 if (tmp)
138 goto found_middle;
139 size -= BITS_PER_LONG;
140 result += BITS_PER_LONG;
141 }
142 while (size & ~(BITS_PER_LONG-1)) {
143 if ((tmp = *(p++)))
144 goto found_middle;
145 result += BITS_PER_LONG;
146 size -= BITS_PER_LONG;
147 }
148 if (!size)
149 return result;
150 tmp = *p;
151
152found_first:
153 tmp &= (~0UL >> (BITS_PER_LONG - size));
154 if (tmp == 0UL) /* Are any bits set? */
155 return result + size; /* Nope. */
156found_middle:
157 return result + __ffs(tmp);
158}
159
160#endif
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
index 97a800738226..6f19c548ecc0 100644
--- a/tools/perf/util/include/linux/string.h
+++ b/tools/perf/util/include/linux/string.h
@@ -1,4 +1,3 @@
1#include <string.h> 1#include <string.h>
2 2
3void *memdup(const void *src, size_t len); 3void *memdup(const void *src, size_t len);
4int str_append(char **s, int *len, const char *a);
diff --git a/tools/perf/util/kvm-stat.h b/tools/perf/util/kvm-stat.h
index 0b5a8cd2ee79..cf1d7913783b 100644
--- a/tools/perf/util/kvm-stat.h
+++ b/tools/perf/util/kvm-stat.h
@@ -92,7 +92,6 @@ struct perf_kvm_stat {
92 u64 lost_events; 92 u64 lost_events;
93 u64 duration; 93 u64 duration;
94 94
95 const char *pid_str;
96 struct intlist *pid_list; 95 struct intlist *pid_list;
97 96
98 struct rb_root result; 97 struct rb_root result;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 16bba9fff2c8..94de3e48b490 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -12,13 +12,20 @@
12#include <stdbool.h> 12#include <stdbool.h>
13#include <symbol/kallsyms.h> 13#include <symbol/kallsyms.h>
14#include "unwind.h" 14#include "unwind.h"
15#include "linux/hash.h"
16
17static void dsos__init(struct dsos *dsos)
18{
19 INIT_LIST_HEAD(&dsos->head);
20 dsos->root = RB_ROOT;
21}
15 22
16int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 23int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
17{ 24{
18 map_groups__init(&machine->kmaps); 25 map_groups__init(&machine->kmaps, machine);
19 RB_CLEAR_NODE(&machine->rb_node); 26 RB_CLEAR_NODE(&machine->rb_node);
20 INIT_LIST_HEAD(&machine->user_dsos); 27 dsos__init(&machine->user_dsos);
21 INIT_LIST_HEAD(&machine->kernel_dsos); 28 dsos__init(&machine->kernel_dsos);
22 29
23 machine->threads = RB_ROOT; 30 machine->threads = RB_ROOT;
24 INIT_LIST_HEAD(&machine->dead_threads); 31 INIT_LIST_HEAD(&machine->dead_threads);
@@ -26,11 +33,12 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
26 33
27 machine->vdso_info = NULL; 34 machine->vdso_info = NULL;
28 35
29 machine->kmaps.machine = machine;
30 machine->pid = pid; 36 machine->pid = pid;
31 37
32 machine->symbol_filter = NULL; 38 machine->symbol_filter = NULL;
33 machine->id_hdr_size = 0; 39 machine->id_hdr_size = 0;
40 machine->comm_exec = false;
41 machine->kernel_start = 0;
34 42
35 machine->root_dir = strdup(root_dir); 43 machine->root_dir = strdup(root_dir);
36 if (machine->root_dir == NULL) 44 if (machine->root_dir == NULL)
@@ -70,11 +78,12 @@ out_delete:
70 return NULL; 78 return NULL;
71} 79}
72 80
73static void dsos__delete(struct list_head *dsos) 81static void dsos__delete(struct dsos *dsos)
74{ 82{
75 struct dso *pos, *n; 83 struct dso *pos, *n;
76 84
77 list_for_each_entry_safe(pos, n, dsos, node) { 85 list_for_each_entry_safe(pos, n, &dsos->head, node) {
86 RB_CLEAR_NODE(&pos->rb_node);
78 list_del(&pos->node); 87 list_del(&pos->node);
79 dso__delete(pos); 88 dso__delete(pos);
80 } 89 }
@@ -179,6 +188,19 @@ void machines__set_symbol_filter(struct machines *machines,
179 } 188 }
180} 189}
181 190
191void machines__set_comm_exec(struct machines *machines, bool comm_exec)
192{
193 struct rb_node *nd;
194
195 machines->host.comm_exec = comm_exec;
196
197 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
198 struct machine *machine = rb_entry(nd, struct machine, rb_node);
199
200 machine->comm_exec = comm_exec;
201 }
202}
203
182struct machine *machines__find(struct machines *machines, pid_t pid) 204struct machine *machines__find(struct machines *machines, pid_t pid)
183{ 205{
184 struct rb_node **p = &machines->guests.rb_node; 206 struct rb_node **p = &machines->guests.rb_node;
@@ -297,7 +319,7 @@ static void machine__update_thread_pid(struct machine *machine,
297 goto out_err; 319 goto out_err;
298 320
299 if (!leader->mg) 321 if (!leader->mg)
300 leader->mg = map_groups__new(); 322 leader->mg = map_groups__new(machine);
301 323
302 if (!leader->mg) 324 if (!leader->mg)
303 goto out_err; 325 goto out_err;
@@ -398,17 +420,31 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid,
398 return __machine__findnew_thread(machine, pid, tid, false); 420 return __machine__findnew_thread(machine, pid, tid, false);
399} 421}
400 422
423struct comm *machine__thread_exec_comm(struct machine *machine,
424 struct thread *thread)
425{
426 if (machine->comm_exec)
427 return thread__exec_comm(thread);
428 else
429 return thread__comm(thread);
430}
431
401int machine__process_comm_event(struct machine *machine, union perf_event *event, 432int machine__process_comm_event(struct machine *machine, union perf_event *event,
402 struct perf_sample *sample) 433 struct perf_sample *sample)
403{ 434{
404 struct thread *thread = machine__findnew_thread(machine, 435 struct thread *thread = machine__findnew_thread(machine,
405 event->comm.pid, 436 event->comm.pid,
406 event->comm.tid); 437 event->comm.tid);
438 bool exec = event->header.misc & PERF_RECORD_MISC_COMM_EXEC;
439
440 if (exec)
441 machine->comm_exec = true;
407 442
408 if (dump_trace) 443 if (dump_trace)
409 perf_event__fprintf_comm(event, stdout); 444 perf_event__fprintf_comm(event, stdout);
410 445
411 if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) { 446 if (thread == NULL ||
447 __thread__set_comm(thread, event->comm.comm, sample->time, exec)) {
412 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 448 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
413 return -1; 449 return -1;
414 } 450 }
@@ -429,6 +465,7 @@ struct map *machine__new_module(struct machine *machine, u64 start,
429{ 465{
430 struct map *map; 466 struct map *map;
431 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); 467 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
468 bool compressed;
432 469
433 if (dso == NULL) 470 if (dso == NULL)
434 return NULL; 471 return NULL;
@@ -441,6 +478,11 @@ struct map *machine__new_module(struct machine *machine, u64 start,
441 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 478 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
442 else 479 else
443 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; 480 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
481
482 /* _KMODULE_COMP should be next to _KMODULE */
483 if (is_kernel_module(filename, &compressed) && compressed)
484 dso->symtab_type++;
485
444 map_groups__insert(&machine->kmaps, map); 486 map_groups__insert(&machine->kmaps, map);
445 return map; 487 return map;
446} 488}
@@ -448,23 +490,23 @@ struct map *machine__new_module(struct machine *machine, u64 start,
448size_t machines__fprintf_dsos(struct machines *machines, FILE *fp) 490size_t machines__fprintf_dsos(struct machines *machines, FILE *fp)
449{ 491{
450 struct rb_node *nd; 492 struct rb_node *nd;
451 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos, fp) + 493 size_t ret = __dsos__fprintf(&machines->host.kernel_dsos.head, fp) +
452 __dsos__fprintf(&machines->host.user_dsos, fp); 494 __dsos__fprintf(&machines->host.user_dsos.head, fp);
453 495
454 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) { 496 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
455 struct machine *pos = rb_entry(nd, struct machine, rb_node); 497 struct machine *pos = rb_entry(nd, struct machine, rb_node);
456 ret += __dsos__fprintf(&pos->kernel_dsos, fp); 498 ret += __dsos__fprintf(&pos->kernel_dsos.head, fp);
457 ret += __dsos__fprintf(&pos->user_dsos, fp); 499 ret += __dsos__fprintf(&pos->user_dsos.head, fp);
458 } 500 }
459 501
460 return ret; 502 return ret;
461} 503}
462 504
463size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 505size_t machine__fprintf_dsos_buildid(struct machine *m, FILE *fp,
464 bool (skip)(struct dso *dso, int parm), int parm) 506 bool (skip)(struct dso *dso, int parm), int parm)
465{ 507{
466 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) + 508 return __dsos__fprintf_buildid(&m->kernel_dsos.head, fp, skip, parm) +
467 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm); 509 __dsos__fprintf_buildid(&m->user_dsos.head, fp, skip, parm);
468} 510}
469 511
470size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp, 512size_t machines__fprintf_dsos_buildid(struct machines *machines, FILE *fp,
@@ -565,8 +607,8 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
565 * Returns the name of the start symbol in *symbol_name. Pass in NULL as 607 * Returns the name of the start symbol in *symbol_name. Pass in NULL as
566 * symbol_name if it's not that important. 608 * symbol_name if it's not that important.
567 */ 609 */
568static u64 machine__get_kernel_start_addr(struct machine *machine, 610static u64 machine__get_running_kernel_start(struct machine *machine,
569 const char **symbol_name) 611 const char **symbol_name)
570{ 612{
571 char filename[PATH_MAX]; 613 char filename[PATH_MAX];
572 int i; 614 int i;
@@ -593,7 +635,7 @@ static u64 machine__get_kernel_start_addr(struct machine *machine,
593int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 635int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
594{ 636{
595 enum map_type type; 637 enum map_type type;
596 u64 start = machine__get_kernel_start_addr(machine, NULL); 638 u64 start = machine__get_running_kernel_start(machine, NULL);
597 639
598 for (type = 0; type < MAP__NR_TYPES; ++type) { 640 for (type = 0; type < MAP__NR_TYPES; ++type) {
599 struct kmap *kmap; 641 struct kmap *kmap;
@@ -826,8 +868,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
826 struct map *map; 868 struct map *map;
827 char *long_name; 869 char *long_name;
828 870
829 if (dot == NULL || strcmp(dot, ".ko")) 871 if (dot == NULL)
830 continue; 872 continue;
873
874 /* On some system, modules are compressed like .ko.gz */
875 if (is_supported_compression(dot + 1) &&
876 is_kmodule_extension(dot - 2))
877 dot -= 3;
878
831 snprintf(dso_name, sizeof(dso_name), "[%.*s]", 879 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
832 (int)(dot - dent->d_name), dent->d_name); 880 (int)(dot - dent->d_name), dent->d_name);
833 881
@@ -912,7 +960,7 @@ int machine__create_kernel_maps(struct machine *machine)
912{ 960{
913 struct dso *kernel = machine__get_kernel(machine); 961 struct dso *kernel = machine__get_kernel(machine);
914 const char *name; 962 const char *name;
915 u64 addr = machine__get_kernel_start_addr(machine, &name); 963 u64 addr = machine__get_running_kernel_start(machine, &name);
916 if (!addr) 964 if (!addr)
917 return -1; 965 return -1;
918 966
@@ -965,7 +1013,7 @@ static bool machine__uses_kcore(struct machine *machine)
965{ 1013{
966 struct dso *dso; 1014 struct dso *dso;
967 1015
968 list_for_each_entry(dso, &machine->kernel_dsos, node) { 1016 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
969 if (dso__is_kcore(dso)) 1017 if (dso__is_kcore(dso))
970 return true; 1018 return true;
971 } 1019 }
@@ -1009,6 +1057,11 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1009 dot = strrchr(name, '.'); 1057 dot = strrchr(name, '.');
1010 if (dot == NULL) 1058 if (dot == NULL)
1011 goto out_problem; 1059 goto out_problem;
1060 /* On some system, modules are compressed like .ko.gz */
1061 if (is_supported_compression(dot + 1))
1062 dot -= 3;
1063 if (!is_kmodule_extension(dot + 1))
1064 goto out_problem;
1012 snprintf(short_module_name, sizeof(short_module_name), 1065 snprintf(short_module_name, sizeof(short_module_name),
1013 "[%.*s]", (int)(dot - name), name); 1066 "[%.*s]", (int)(dot - name), name);
1014 strxfrchar(short_module_name, '-', '_'); 1067 strxfrchar(short_module_name, '-', '_');
@@ -1033,8 +1086,20 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1033 * Should be there already, from the build-id table in 1086 * Should be there already, from the build-id table in
1034 * the header. 1087 * the header.
1035 */ 1088 */
1036 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, 1089 struct dso *kernel = NULL;
1037 kmmap_prefix); 1090 struct dso *dso;
1091
1092 list_for_each_entry(dso, &machine->kernel_dsos.head, node) {
1093 if (is_kernel_module(dso->long_name, NULL))
1094 continue;
1095
1096 kernel = dso;
1097 break;
1098 }
1099
1100 if (kernel == NULL)
1101 kernel = __dsos__findnew(&machine->kernel_dsos,
1102 kmmap_prefix);
1038 if (kernel == NULL) 1103 if (kernel == NULL)
1039 goto out_problem; 1104 goto out_problem;
1040 1105
@@ -1042,6 +1107,9 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1042 if (__machine__create_kernel_maps(machine, kernel) < 0) 1107 if (__machine__create_kernel_maps(machine, kernel) < 0)
1043 goto out_problem; 1108 goto out_problem;
1044 1109
1110 if (strstr(kernel->long_name, "vmlinux"))
1111 dso__set_short_name(kernel, "[kernel.vmlinux]", false);
1112
1045 machine__set_kernel_mmap_len(machine, event); 1113 machine__set_kernel_mmap_len(machine, event);
1046 1114
1047 /* 1115 /*
@@ -1254,7 +1322,7 @@ static bool symbol__match_regex(struct symbol *sym, regex_t *regex)
1254 return 0; 1322 return 0;
1255} 1323}
1256 1324
1257static void ip__resolve_ams(struct machine *machine, struct thread *thread, 1325static void ip__resolve_ams(struct thread *thread,
1258 struct addr_map_symbol *ams, 1326 struct addr_map_symbol *ams,
1259 u64 ip) 1327 u64 ip)
1260{ 1328{
@@ -1268,7 +1336,7 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1268 * Thus, we have to try consecutively until we find a match 1336 * Thus, we have to try consecutively until we find a match
1269 * or else, the symbol is unknown 1337 * or else, the symbol is unknown
1270 */ 1338 */
1271 thread__find_cpumode_addr_location(thread, machine, MAP__FUNCTION, ip, &al); 1339 thread__find_cpumode_addr_location(thread, MAP__FUNCTION, ip, &al);
1272 1340
1273 ams->addr = ip; 1341 ams->addr = ip;
1274 ams->al_addr = al.addr; 1342 ams->al_addr = al.addr;
@@ -1276,15 +1344,23 @@ static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1276 ams->map = al.map; 1344 ams->map = al.map;
1277} 1345}
1278 1346
1279static void ip__resolve_data(struct machine *machine, struct thread *thread, 1347static void ip__resolve_data(struct thread *thread,
1280 u8 m, struct addr_map_symbol *ams, u64 addr) 1348 u8 m, struct addr_map_symbol *ams, u64 addr)
1281{ 1349{
1282 struct addr_location al; 1350 struct addr_location al;
1283 1351
1284 memset(&al, 0, sizeof(al)); 1352 memset(&al, 0, sizeof(al));
1285 1353
1286 thread__find_addr_location(thread, machine, m, MAP__VARIABLE, addr, 1354 thread__find_addr_location(thread, m, MAP__VARIABLE, addr, &al);
1287 &al); 1355 if (al.map == NULL) {
1356 /*
1357 * some shared data regions have execute bit set which puts
1358 * their mapping in the MAP__FUNCTION type array.
1359 * Check there as a fallback option before dropping the sample.
1360 */
1361 thread__find_addr_location(thread, m, MAP__FUNCTION, addr, &al);
1362 }
1363
1288 ams->addr = addr; 1364 ams->addr = addr;
1289 ams->al_addr = al.addr; 1365 ams->al_addr = al.addr;
1290 ams->sym = al.sym; 1366 ams->sym = al.sym;
@@ -1299,14 +1375,72 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1299 if (!mi) 1375 if (!mi)
1300 return NULL; 1376 return NULL;
1301 1377
1302 ip__resolve_ams(al->machine, al->thread, &mi->iaddr, sample->ip); 1378 ip__resolve_ams(al->thread, &mi->iaddr, sample->ip);
1303 ip__resolve_data(al->machine, al->thread, al->cpumode, 1379 ip__resolve_data(al->thread, al->cpumode, &mi->daddr, sample->addr);
1304 &mi->daddr, sample->addr);
1305 mi->data_src.val = sample->data_src; 1380 mi->data_src.val = sample->data_src;
1306 1381
1307 return mi; 1382 return mi;
1308} 1383}
1309 1384
1385static int add_callchain_ip(struct thread *thread,
1386 struct symbol **parent,
1387 struct addr_location *root_al,
1388 bool branch_history,
1389 u64 ip)
1390{
1391 struct addr_location al;
1392
1393 al.filtered = 0;
1394 al.sym = NULL;
1395 if (branch_history)
1396 thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
1397 ip, &al);
1398 else {
1399 u8 cpumode = PERF_RECORD_MISC_USER;
1400
1401 if (ip >= PERF_CONTEXT_MAX) {
1402 switch (ip) {
1403 case PERF_CONTEXT_HV:
1404 cpumode = PERF_RECORD_MISC_HYPERVISOR;
1405 break;
1406 case PERF_CONTEXT_KERNEL:
1407 cpumode = PERF_RECORD_MISC_KERNEL;
1408 break;
1409 case PERF_CONTEXT_USER:
1410 cpumode = PERF_RECORD_MISC_USER;
1411 break;
1412 default:
1413 pr_debug("invalid callchain context: "
1414 "%"PRId64"\n", (s64) ip);
1415 /*
1416 * It seems the callchain is corrupted.
1417 * Discard all.
1418 */
1419 callchain_cursor_reset(&callchain_cursor);
1420 return 1;
1421 }
1422 return 0;
1423 }
1424 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
1425 ip, &al);
1426 }
1427
1428 if (al.sym != NULL) {
1429 if (sort__has_parent && !*parent &&
1430 symbol__match_regex(al.sym, &parent_regex))
1431 *parent = al.sym;
1432 else if (have_ignore_callees && root_al &&
1433 symbol__match_regex(al.sym, &ignore_callees_regex)) {
1434 /* Treat this symbol as the root,
1435 forgetting its callees. */
1436 *root_al = al;
1437 callchain_cursor_reset(&callchain_cursor);
1438 }
1439 }
1440
1441 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);
1442}
1443
1310struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1444struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1311 struct addr_location *al) 1445 struct addr_location *al)
1312{ 1446{
@@ -1318,43 +1452,140 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
1318 return NULL; 1452 return NULL;
1319 1453
1320 for (i = 0; i < bs->nr; i++) { 1454 for (i = 0; i < bs->nr; i++) {
1321 ip__resolve_ams(al->machine, al->thread, &bi[i].to, bs->entries[i].to); 1455 ip__resolve_ams(al->thread, &bi[i].to, bs->entries[i].to);
1322 ip__resolve_ams(al->machine, al->thread, &bi[i].from, bs->entries[i].from); 1456 ip__resolve_ams(al->thread, &bi[i].from, bs->entries[i].from);
1323 bi[i].flags = bs->entries[i].flags; 1457 bi[i].flags = bs->entries[i].flags;
1324 } 1458 }
1325 return bi; 1459 return bi;
1326} 1460}
1327 1461
1328static int machine__resolve_callchain_sample(struct machine *machine, 1462#define CHASHSZ 127
1329 struct thread *thread, 1463#define CHASHBITS 7
1464#define NO_ENTRY 0xff
1465
1466#define PERF_MAX_BRANCH_DEPTH 127
1467
1468/* Remove loops. */
1469static int remove_loops(struct branch_entry *l, int nr)
1470{
1471 int i, j, off;
1472 unsigned char chash[CHASHSZ];
1473
1474 memset(chash, NO_ENTRY, sizeof(chash));
1475
1476 BUG_ON(PERF_MAX_BRANCH_DEPTH > 255);
1477
1478 for (i = 0; i < nr; i++) {
1479 int h = hash_64(l[i].from, CHASHBITS) % CHASHSZ;
1480
1481 /* no collision handling for now */
1482 if (chash[h] == NO_ENTRY) {
1483 chash[h] = i;
1484 } else if (l[chash[h]].from == l[i].from) {
1485 bool is_loop = true;
1486 /* check if it is a real loop */
1487 off = 0;
1488 for (j = chash[h]; j < i && i + off < nr; j++, off++)
1489 if (l[j].from != l[i + off].from) {
1490 is_loop = false;
1491 break;
1492 }
1493 if (is_loop) {
1494 memmove(l + i, l + i + off,
1495 (nr - (i + off)) * sizeof(*l));
1496 nr -= off;
1497 }
1498 }
1499 }
1500 return nr;
1501}
1502
1503static int thread__resolve_callchain_sample(struct thread *thread,
1330 struct ip_callchain *chain, 1504 struct ip_callchain *chain,
1505 struct branch_stack *branch,
1331 struct symbol **parent, 1506 struct symbol **parent,
1332 struct addr_location *root_al, 1507 struct addr_location *root_al,
1333 int max_stack) 1508 int max_stack)
1334{ 1509{
1335 u8 cpumode = PERF_RECORD_MISC_USER;
1336 int chain_nr = min(max_stack, (int)chain->nr); 1510 int chain_nr = min(max_stack, (int)chain->nr);
1337 int i; 1511 int i, j, err;
1338 int j; 1512 int skip_idx = -1;
1339 int err; 1513 int first_call = 0;
1340 int skip_idx __maybe_unused; 1514
1515 /*
1516 * Based on DWARF debug information, some architectures skip
1517 * a callchain entry saved by the kernel.
1518 */
1519 if (chain->nr < PERF_MAX_STACK_DEPTH)
1520 skip_idx = arch_skip_callchain_idx(thread, chain);
1341 1521
1342 callchain_cursor_reset(&callchain_cursor); 1522 callchain_cursor_reset(&callchain_cursor);
1343 1523
1524 /*
1525 * Add branches to call stack for easier browsing. This gives
1526 * more context for a sample than just the callers.
1527 *
1528 * This uses individual histograms of paths compared to the
1529 * aggregated histograms the normal LBR mode uses.
1530 *
1531 * Limitations for now:
1532 * - No extra filters
1533 * - No annotations (should annotate somehow)
1534 */
1535
1536 if (branch && callchain_param.branch_callstack) {
1537 int nr = min(max_stack, (int)branch->nr);
1538 struct branch_entry be[nr];
1539
1540 if (branch->nr > PERF_MAX_BRANCH_DEPTH) {
1541 pr_warning("corrupted branch chain. skipping...\n");
1542 goto check_calls;
1543 }
1544
1545 for (i = 0; i < nr; i++) {
1546 if (callchain_param.order == ORDER_CALLEE) {
1547 be[i] = branch->entries[i];
1548 /*
1549 * Check for overlap into the callchain.
1550 * The return address is one off compared to
1551 * the branch entry. To adjust for this
1552 * assume the calling instruction is not longer
1553 * than 8 bytes.
1554 */
1555 if (i == skip_idx ||
1556 chain->ips[first_call] >= PERF_CONTEXT_MAX)
1557 first_call++;
1558 else if (be[i].from < chain->ips[first_call] &&
1559 be[i].from >= chain->ips[first_call] - 8)
1560 first_call++;
1561 } else
1562 be[i] = branch->entries[branch->nr - i - 1];
1563 }
1564
1565 nr = remove_loops(be, nr);
1566
1567 for (i = 0; i < nr; i++) {
1568 err = add_callchain_ip(thread, parent, root_al,
1569 true, be[i].to);
1570 if (!err)
1571 err = add_callchain_ip(thread, parent, root_al,
1572 true, be[i].from);
1573 if (err == -EINVAL)
1574 break;
1575 if (err)
1576 return err;
1577 }
1578 chain_nr -= nr;
1579 }
1580
1581check_calls:
1344 if (chain->nr > PERF_MAX_STACK_DEPTH) { 1582 if (chain->nr > PERF_MAX_STACK_DEPTH) {
1345 pr_warning("corrupted callchain. skipping...\n"); 1583 pr_warning("corrupted callchain. skipping...\n");
1346 return 0; 1584 return 0;
1347 } 1585 }
1348 1586
1349 /* 1587 for (i = first_call; i < chain_nr; i++) {
1350 * Based on DWARF debug information, some architectures skip
1351 * a callchain entry saved by the kernel.
1352 */
1353 skip_idx = arch_skip_callchain_idx(machine, thread, chain);
1354
1355 for (i = 0; i < chain_nr; i++) {
1356 u64 ip; 1588 u64 ip;
1357 struct addr_location al;
1358 1589
1359 if (callchain_param.order == ORDER_CALLEE) 1590 if (callchain_param.order == ORDER_CALLEE)
1360 j = i; 1591 j = i;
@@ -1367,50 +1598,10 @@ static int machine__resolve_callchain_sample(struct machine *machine,
1367#endif 1598#endif
1368 ip = chain->ips[j]; 1599 ip = chain->ips[j];
1369 1600
1370 if (ip >= PERF_CONTEXT_MAX) { 1601 err = add_callchain_ip(thread, parent, root_al, false, ip);
1371 switch (ip) {
1372 case PERF_CONTEXT_HV:
1373 cpumode = PERF_RECORD_MISC_HYPERVISOR;
1374 break;
1375 case PERF_CONTEXT_KERNEL:
1376 cpumode = PERF_RECORD_MISC_KERNEL;
1377 break;
1378 case PERF_CONTEXT_USER:
1379 cpumode = PERF_RECORD_MISC_USER;
1380 break;
1381 default:
1382 pr_debug("invalid callchain context: "
1383 "%"PRId64"\n", (s64) ip);
1384 /*
1385 * It seems the callchain is corrupted.
1386 * Discard all.
1387 */
1388 callchain_cursor_reset(&callchain_cursor);
1389 return 0;
1390 }
1391 continue;
1392 }
1393
1394 al.filtered = 0;
1395 thread__find_addr_location(thread, machine, cpumode,
1396 MAP__FUNCTION, ip, &al);
1397 if (al.sym != NULL) {
1398 if (sort__has_parent && !*parent &&
1399 symbol__match_regex(al.sym, &parent_regex))
1400 *parent = al.sym;
1401 else if (have_ignore_callees && root_al &&
1402 symbol__match_regex(al.sym, &ignore_callees_regex)) {
1403 /* Treat this symbol as the root,
1404 forgetting its callees. */
1405 *root_al = al;
1406 callchain_cursor_reset(&callchain_cursor);
1407 }
1408 }
1409 1602
1410 err = callchain_cursor_append(&callchain_cursor,
1411 ip, al.map, al.sym);
1412 if (err) 1603 if (err)
1413 return err; 1604 return (err < 0) ? err : 0;
1414 } 1605 }
1415 1606
1416 return 0; 1607 return 0;
@@ -1423,19 +1614,16 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1423 entry->map, entry->sym); 1614 entry->map, entry->sym);
1424} 1615}
1425 1616
1426int machine__resolve_callchain(struct machine *machine, 1617int thread__resolve_callchain(struct thread *thread,
1427 struct perf_evsel *evsel, 1618 struct perf_evsel *evsel,
1428 struct thread *thread, 1619 struct perf_sample *sample,
1429 struct perf_sample *sample, 1620 struct symbol **parent,
1430 struct symbol **parent, 1621 struct addr_location *root_al,
1431 struct addr_location *root_al, 1622 int max_stack)
1432 int max_stack)
1433{ 1623{
1434 int ret; 1624 int ret = thread__resolve_callchain_sample(thread, sample->callchain,
1435 1625 sample->branch_stack,
1436 ret = machine__resolve_callchain_sample(machine, thread, 1626 parent, root_al, max_stack);
1437 sample->callchain, parent,
1438 root_al, max_stack);
1439 if (ret) 1627 if (ret)
1440 return ret; 1628 return ret;
1441 1629
@@ -1449,7 +1637,7 @@ int machine__resolve_callchain(struct machine *machine,
1449 (!sample->user_stack.size)) 1637 (!sample->user_stack.size))
1450 return 0; 1638 return 0;
1451 1639
1452 return unwind__get_entries(unwind_entry, &callchain_cursor, machine, 1640 return unwind__get_entries(unwind_entry, &callchain_cursor,
1453 thread, sample, max_stack); 1641 thread, sample, max_stack);
1454 1642
1455} 1643}
@@ -1531,3 +1719,25 @@ int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1531 1719
1532 return 0; 1720 return 0;
1533} 1721}
1722
1723int machine__get_kernel_start(struct machine *machine)
1724{
1725 struct map *map = machine__kernel_map(machine, MAP__FUNCTION);
1726 int err = 0;
1727
1728 /*
1729 * The only addresses above 2^63 are kernel addresses of a 64-bit
1730 * kernel. Note that addresses are unsigned so that on a 32-bit system
1731 * all addresses including kernel addresses are less than 2^32. In
1732 * that case (32-bit system), if the kernel mapping is unknown, all
1733 * addresses will be assumed to be in user space - see
1734 * machine__kernel_ip().
1735 */
1736 machine->kernel_start = 1ULL << 63;
1737 if (map) {
1738 err = map__load(map, machine->symbol_filter);
1739 if (map->start)
1740 machine->kernel_start = map->start;
1741 }
1742 return err;
1743}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index b972824e6294..e8b7779a0a3f 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -4,6 +4,7 @@
4#include <sys/types.h> 4#include <sys/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include "map.h" 6#include "map.h"
7#include "dso.h"
7#include "event.h" 8#include "event.h"
8 9
9struct addr_location; 10struct addr_location;
@@ -26,17 +27,23 @@ struct machine {
26 struct rb_node rb_node; 27 struct rb_node rb_node;
27 pid_t pid; 28 pid_t pid;
28 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec;
29 char *root_dir; 31 char *root_dir;
30 struct rb_root threads; 32 struct rb_root threads;
31 struct list_head dead_threads; 33 struct list_head dead_threads;
32 struct thread *last_match; 34 struct thread *last_match;
33 struct vdso_info *vdso_info; 35 struct vdso_info *vdso_info;
34 struct list_head user_dsos; 36 struct dsos user_dsos;
35 struct list_head kernel_dsos; 37 struct dsos kernel_dsos;
36 struct map_groups kmaps; 38 struct map_groups kmaps;
37 struct map *vmlinux_maps[MAP__NR_TYPES]; 39 struct map *vmlinux_maps[MAP__NR_TYPES];
40 u64 kernel_start;
38 symbol_filter_t symbol_filter; 41 symbol_filter_t symbol_filter;
39 pid_t *current_tid; 42 pid_t *current_tid;
43 union { /* Tool specific area */
44 void *priv;
45 u64 db_id;
46 };
40}; 47};
41 48
42static inline 49static inline
@@ -45,8 +52,26 @@ struct map *machine__kernel_map(struct machine *machine, enum map_type type)
45 return machine->vmlinux_maps[type]; 52 return machine->vmlinux_maps[type];
46} 53}
47 54
55int machine__get_kernel_start(struct machine *machine);
56
57static inline u64 machine__kernel_start(struct machine *machine)
58{
59 if (!machine->kernel_start)
60 machine__get_kernel_start(machine);
61 return machine->kernel_start;
62}
63
64static inline bool machine__kernel_ip(struct machine *machine, u64 ip)
65{
66 u64 kernel_start = machine__kernel_start(machine);
67
68 return ip >= kernel_start;
69}
70
48struct thread *machine__find_thread(struct machine *machine, pid_t pid, 71struct thread *machine__find_thread(struct machine *machine, pid_t pid,
49 pid_t tid); 72 pid_t tid);
73struct comm *machine__thread_exec_comm(struct machine *machine,
74 struct thread *thread);
50 75
51int machine__process_comm_event(struct machine *machine, union perf_event *event, 76int machine__process_comm_event(struct machine *machine, union perf_event *event,
52 struct perf_sample *sample); 77 struct perf_sample *sample);
@@ -88,6 +113,7 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
88 113
89void machines__set_symbol_filter(struct machines *machines, 114void machines__set_symbol_filter(struct machines *machines,
90 symbol_filter_t symbol_filter); 115 symbol_filter_t symbol_filter);
116void machines__set_comm_exec(struct machines *machines, bool comm_exec);
91 117
92struct machine *machine__new_host(void); 118struct machine *machine__new_host(void);
93int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 119int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
@@ -100,13 +126,12 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
100 struct addr_location *al); 126 struct addr_location *al);
101struct mem_info *sample__resolve_mem(struct perf_sample *sample, 127struct mem_info *sample__resolve_mem(struct perf_sample *sample,
102 struct addr_location *al); 128 struct addr_location *al);
103int machine__resolve_callchain(struct machine *machine, 129int thread__resolve_callchain(struct thread *thread,
104 struct perf_evsel *evsel, 130 struct perf_evsel *evsel,
105 struct thread *thread, 131 struct perf_sample *sample,
106 struct perf_sample *sample, 132 struct symbol **parent,
107 struct symbol **parent, 133 struct addr_location *root_al,
108 struct addr_location *root_al, 134 int max_stack);
109 int max_stack);
110 135
111/* 136/*
112 * Default guest kernel is defined by parameter --guestkallsyms 137 * Default guest kernel is defined by parameter --guestkallsyms
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 31b8905dd863..62ca9f2607d5 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -31,6 +31,7 @@ static inline int is_anon_memory(const char *filename)
31static inline int is_no_dso_memory(const char *filename) 31static inline int is_no_dso_memory(const char *filename)
32{ 32{
33 return !strncmp(filename, "[stack", 6) || 33 return !strncmp(filename, "[stack", 6) ||
34 !strncmp(filename, "/SYSV",5) ||
34 !strcmp(filename, "[heap]"); 35 !strcmp(filename, "[heap]");
35} 36}
36 37
@@ -359,7 +360,7 @@ int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
359 360
360 if (map && map->dso) { 361 if (map && map->dso) {
361 srcline = get_srcline(map->dso, 362 srcline = get_srcline(map->dso,
362 map__rip_2objdump(map, addr)); 363 map__rip_2objdump(map, addr), NULL, true);
363 if (srcline != SRCLINE_UNKNOWN) 364 if (srcline != SRCLINE_UNKNOWN)
364 ret = fprintf(fp, "%s%s", prefix, srcline); 365 ret = fprintf(fp, "%s%s", prefix, srcline);
365 free_srcline(srcline); 366 free_srcline(srcline);
@@ -412,14 +413,14 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
412 return ip + map->reloc; 413 return ip + map->reloc;
413} 414}
414 415
415void map_groups__init(struct map_groups *mg) 416void map_groups__init(struct map_groups *mg, struct machine *machine)
416{ 417{
417 int i; 418 int i;
418 for (i = 0; i < MAP__NR_TYPES; ++i) { 419 for (i = 0; i < MAP__NR_TYPES; ++i) {
419 mg->maps[i] = RB_ROOT; 420 mg->maps[i] = RB_ROOT;
420 INIT_LIST_HEAD(&mg->removed_maps[i]); 421 INIT_LIST_HEAD(&mg->removed_maps[i]);
421 } 422 }
422 mg->machine = NULL; 423 mg->machine = machine;
423 mg->refcnt = 1; 424 mg->refcnt = 1;
424} 425}
425 426
@@ -470,12 +471,12 @@ bool map_groups__empty(struct map_groups *mg)
470 return true; 471 return true;
471} 472}
472 473
473struct map_groups *map_groups__new(void) 474struct map_groups *map_groups__new(struct machine *machine)
474{ 475{
475 struct map_groups *mg = malloc(sizeof(*mg)); 476 struct map_groups *mg = malloc(sizeof(*mg));
476 477
477 if (mg != NULL) 478 if (mg != NULL)
478 map_groups__init(mg); 479 map_groups__init(mg, machine);
479 480
480 return mg; 481 return mg;
481} 482}
@@ -555,7 +556,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
555 556
556int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 557int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
557{ 558{
558 if (ams->addr < ams->map->start || ams->addr > ams->map->end) { 559 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
559 if (ams->map->groups == NULL) 560 if (ams->map->groups == NULL)
560 return -1; 561 return -1;
561 ams->map = map_groups__find(ams->map->groups, ams->map->type, 562 ams->map = map_groups__find(ams->map->groups, ams->map->type,
@@ -663,7 +664,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
663 goto move_map; 664 goto move_map;
664 } 665 }
665 666
666 before->end = map->start - 1; 667 before->end = map->start;
667 map_groups__insert(mg, before); 668 map_groups__insert(mg, before);
668 if (verbose >= 2) 669 if (verbose >= 2)
669 map__fprintf(before, fp); 670 map__fprintf(before, fp);
@@ -677,7 +678,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
677 goto move_map; 678 goto move_map;
678 } 679 }
679 680
680 after->start = map->end + 1; 681 after->start = map->end;
681 map_groups__insert(mg, after); 682 map_groups__insert(mg, after);
682 if (verbose >= 2) 683 if (verbose >= 2)
683 map__fprintf(after, fp); 684 map__fprintf(after, fp);
@@ -751,7 +752,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
751 m = rb_entry(parent, struct map, rb_node); 752 m = rb_entry(parent, struct map, rb_node);
752 if (ip < m->start) 753 if (ip < m->start)
753 p = &(*p)->rb_left; 754 p = &(*p)->rb_left;
754 else if (ip > m->end) 755 else if (ip >= m->end)
755 p = &(*p)->rb_right; 756 p = &(*p)->rb_right;
756 else 757 else
757 return m; 758 return m;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 2f83954af050..6951a9d42339 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -64,7 +64,7 @@ struct map_groups {
64 int refcnt; 64 int refcnt;
65}; 65};
66 66
67struct map_groups *map_groups__new(void); 67struct map_groups *map_groups__new(struct machine *machine);
68void map_groups__delete(struct map_groups *mg); 68void map_groups__delete(struct map_groups *mg);
69bool map_groups__empty(struct map_groups *mg); 69bool map_groups__empty(struct map_groups *mg);
70 70
@@ -150,7 +150,7 @@ void maps__remove(struct rb_root *maps, struct map *map);
150struct map *maps__find(struct rb_root *maps, u64 addr); 150struct map *maps__find(struct rb_root *maps, u64 addr);
151struct map *maps__first(struct rb_root *maps); 151struct map *maps__first(struct rb_root *maps);
152struct map *maps__next(struct map *map); 152struct map *maps__next(struct map *map);
153void map_groups__init(struct map_groups *mg); 153void map_groups__init(struct map_groups *mg, struct machine *machine);
154void map_groups__exit(struct map_groups *mg); 154void map_groups__exit(struct map_groups *mg);
155int map_groups__clone(struct map_groups *mg, 155int map_groups__clone(struct map_groups *mg,
156 struct map_groups *parent, enum map_type type); 156 struct map_groups *parent, enum map_type type);
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
new file mode 100644
index 000000000000..fd4be94125fb
--- /dev/null
+++ b/tools/perf/util/ordered-events.c
@@ -0,0 +1,286 @@
1#include <linux/list.h>
2#include <linux/compiler.h>
3#include <linux/string.h>
4#include "ordered-events.h"
5#include "evlist.h"
6#include "session.h"
7#include "asm/bug.h"
8#include "debug.h"
9
10#define pr_N(n, fmt, ...) \
11 eprintf(n, debug_ordered_events, fmt, ##__VA_ARGS__)
12
13#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
14
15static void queue_event(struct ordered_events *oe, struct ordered_event *new)
16{
17 struct ordered_event *last = oe->last;
18 u64 timestamp = new->timestamp;
19 struct list_head *p;
20
21 ++oe->nr_events;
22 oe->last = new;
23
24 pr_oe_time2(timestamp, "queue_event nr_events %u\n", oe->nr_events);
25
26 if (!last) {
27 list_add(&new->list, &oe->events);
28 oe->max_timestamp = timestamp;
29 return;
30 }
31
32 /*
33 * last event might point to some random place in the list as it's
34 * the last queued event. We expect that the new event is close to
35 * this.
36 */
37 if (last->timestamp <= timestamp) {
38 while (last->timestamp <= timestamp) {
39 p = last->list.next;
40 if (p == &oe->events) {
41 list_add_tail(&new->list, &oe->events);
42 oe->max_timestamp = timestamp;
43 return;
44 }
45 last = list_entry(p, struct ordered_event, list);
46 }
47 list_add_tail(&new->list, &last->list);
48 } else {
49 while (last->timestamp > timestamp) {
50 p = last->list.prev;
51 if (p == &oe->events) {
52 list_add(&new->list, &oe->events);
53 return;
54 }
55 last = list_entry(p, struct ordered_event, list);
56 }
57 list_add(&new->list, &last->list);
58 }
59}
60
61static union perf_event *__dup_event(struct ordered_events *oe,
62 union perf_event *event)
63{
64 union perf_event *new_event = NULL;
65
66 if (oe->cur_alloc_size < oe->max_alloc_size) {
67 new_event = memdup(event, event->header.size);
68 if (new_event)
69 oe->cur_alloc_size += event->header.size;
70 }
71
72 return new_event;
73}
74
75static union perf_event *dup_event(struct ordered_events *oe,
76 union perf_event *event)
77{
78 return oe->copy_on_queue ? __dup_event(oe, event) : event;
79}
80
81static void free_dup_event(struct ordered_events *oe, union perf_event *event)
82{
83 if (oe->copy_on_queue) {
84 oe->cur_alloc_size -= event->header.size;
85 free(event);
86 }
87}
88
89#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
90static struct ordered_event *alloc_event(struct ordered_events *oe,
91 union perf_event *event)
92{
93 struct list_head *cache = &oe->cache;
94 struct ordered_event *new = NULL;
95 union perf_event *new_event;
96
97 new_event = dup_event(oe, event);
98 if (!new_event)
99 return NULL;
100
101 if (!list_empty(cache)) {
102 new = list_entry(cache->next, struct ordered_event, list);
103 list_del(&new->list);
104 } else if (oe->buffer) {
105 new = oe->buffer + oe->buffer_idx;
106 if (++oe->buffer_idx == MAX_SAMPLE_BUFFER)
107 oe->buffer = NULL;
108 } else if (oe->cur_alloc_size < oe->max_alloc_size) {
109 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
110
111 oe->buffer = malloc(size);
112 if (!oe->buffer) {
113 free_dup_event(oe, new_event);
114 return NULL;
115 }
116
117 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
118 oe->cur_alloc_size, size, oe->max_alloc_size);
119
120 oe->cur_alloc_size += size;
121 list_add(&oe->buffer->list, &oe->to_free);
122
123 /* First entry is abused to maintain the to_free list. */
124 oe->buffer_idx = 2;
125 new = oe->buffer + 1;
126 } else {
127 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
128 }
129
130 new->event = new_event;
131 return new;
132}
133
134struct ordered_event *
135ordered_events__new(struct ordered_events *oe, u64 timestamp,
136 union perf_event *event)
137{
138 struct ordered_event *new;
139
140 new = alloc_event(oe, event);
141 if (new) {
142 new->timestamp = timestamp;
143 queue_event(oe, new);
144 }
145
146 return new;
147}
148
149void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event)
150{
151 list_move(&event->list, &oe->cache);
152 oe->nr_events--;
153 free_dup_event(oe, event->event);
154}
155
156static int __ordered_events__flush(struct perf_session *s,
157 struct perf_tool *tool)
158{
159 struct ordered_events *oe = &s->ordered_events;
160 struct list_head *head = &oe->events;
161 struct ordered_event *tmp, *iter;
162 struct perf_sample sample;
163 u64 limit = oe->next_flush;
164 u64 last_ts = oe->last ? oe->last->timestamp : 0ULL;
165 bool show_progress = limit == ULLONG_MAX;
166 struct ui_progress prog;
167 int ret;
168
169 if (!tool->ordered_events || !limit)
170 return 0;
171
172 if (show_progress)
173 ui_progress__init(&prog, oe->nr_events, "Processing time ordered events...");
174
175 list_for_each_entry_safe(iter, tmp, head, list) {
176 if (session_done())
177 return 0;
178
179 if (iter->timestamp > limit)
180 break;
181
182 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
183 if (ret)
184 pr_err("Can't parse sample, err = %d\n", ret);
185 else {
186 ret = perf_session__deliver_event(s, iter->event, &sample, tool,
187 iter->file_offset);
188 if (ret)
189 return ret;
190 }
191
192 ordered_events__delete(oe, iter);
193 oe->last_flush = iter->timestamp;
194
195 if (show_progress)
196 ui_progress__update(&prog, 1);
197 }
198
199 if (list_empty(head))
200 oe->last = NULL;
201 else if (last_ts <= limit)
202 oe->last = list_entry(head->prev, struct ordered_event, list);
203
204 return 0;
205}
206
207int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
208 enum oe_flush how)
209{
210 struct ordered_events *oe = &s->ordered_events;
211 static const char * const str[] = {
212 "NONE",
213 "FINAL",
214 "ROUND",
215 "HALF ",
216 };
217 int err;
218
219 switch (how) {
220 case OE_FLUSH__FINAL:
221 oe->next_flush = ULLONG_MAX;
222 break;
223
224 case OE_FLUSH__HALF:
225 {
226 struct ordered_event *first, *last;
227 struct list_head *head = &oe->events;
228
229 first = list_entry(head->next, struct ordered_event, list);
230 last = oe->last;
231
232 /* Warn if we are called before any event got allocated. */
233 if (WARN_ONCE(!last || list_empty(head), "empty queue"))
234 return 0;
235
236 oe->next_flush = first->timestamp;
237 oe->next_flush += (last->timestamp - first->timestamp) / 2;
238 break;
239 }
240
241 case OE_FLUSH__ROUND:
242 case OE_FLUSH__NONE:
243 default:
244 break;
245 };
246
247 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush PRE %s, nr_events %u\n",
248 str[how], oe->nr_events);
249 pr_oe_time(oe->max_timestamp, "max_timestamp\n");
250
251 err = __ordered_events__flush(s, tool);
252
253 if (!err) {
254 if (how == OE_FLUSH__ROUND)
255 oe->next_flush = oe->max_timestamp;
256
257 oe->last_flush_type = how;
258 }
259
260 pr_oe_time(oe->next_flush, "next_flush - ordered_events__flush POST %s, nr_events %u\n",
261 str[how], oe->nr_events);
262 pr_oe_time(oe->last_flush, "last_flush\n");
263
264 return err;
265}
266
267void ordered_events__init(struct ordered_events *oe)
268{
269 INIT_LIST_HEAD(&oe->events);
270 INIT_LIST_HEAD(&oe->cache);
271 INIT_LIST_HEAD(&oe->to_free);
272 oe->max_alloc_size = (u64) -1;
273 oe->cur_alloc_size = 0;
274}
275
276void ordered_events__free(struct ordered_events *oe)
277{
278 while (!list_empty(&oe->to_free)) {
279 struct ordered_event *event;
280
281 event = list_entry(oe->to_free.next, struct ordered_event, list);
282 list_del(&event->list);
283 free_dup_event(oe, event->event);
284 free(event);
285 }
286}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
new file mode 100644
index 000000000000..7b8f9b011f38
--- /dev/null
+++ b/tools/perf/util/ordered-events.h
@@ -0,0 +1,59 @@
1#ifndef __ORDERED_EVENTS_H
2#define __ORDERED_EVENTS_H
3
4#include <linux/types.h>
5#include "tool.h"
6
7struct perf_session;
8
9struct ordered_event {
10 u64 timestamp;
11 u64 file_offset;
12 union perf_event *event;
13 struct list_head list;
14};
15
16enum oe_flush {
17 OE_FLUSH__NONE,
18 OE_FLUSH__FINAL,
19 OE_FLUSH__ROUND,
20 OE_FLUSH__HALF,
21};
22
23struct ordered_events {
24 u64 last_flush;
25 u64 next_flush;
26 u64 max_timestamp;
27 u64 max_alloc_size;
28 u64 cur_alloc_size;
29 struct list_head events;
30 struct list_head cache;
31 struct list_head to_free;
32 struct ordered_event *buffer;
33 struct ordered_event *last;
34 int buffer_idx;
35 unsigned int nr_events;
36 enum oe_flush last_flush_type;
37 bool copy_on_queue;
38};
39
40struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
41 union perf_event *event);
42void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
43int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
44 enum oe_flush how);
45void ordered_events__init(struct ordered_events *oe);
46void ordered_events__free(struct ordered_events *oe);
47
48static inline
49void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
50{
51 oe->max_alloc_size = size;
52}
53
54static inline
55void ordered_events__set_copy_on_queue(struct ordered_events *oe, bool copy)
56{
57 oe->copy_on_queue = copy;
58}
59#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1e15df10a88c..77b43fe43d55 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,10 +6,11 @@
6#include "parse-options.h" 6#include "parse-options.h"
7#include "parse-events.h" 7#include "parse-events.h"
8#include "exec_cmd.h" 8#include "exec_cmd.h"
9#include "linux/string.h" 9#include "string.h"
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
13#include "debug.h"
13#include <api/fs/debugfs.h> 14#include <api/fs/debugfs.h>
14#include "parse-events-bison.h" 15#include "parse-events-bison.h"
15#define YY_EXTRA_TYPE int 16#define YY_EXTRA_TYPE int
@@ -29,6 +30,15 @@ extern int parse_events_debug;
29#endif 30#endif
30int parse_events_parse(void *data, void *scanner); 31int parse_events_parse(void *data, void *scanner);
31 32
33static struct perf_pmu_event_symbol *perf_pmu_events_list;
34/*
35 * The variable indicates the number of supported pmu event symbols.
36 * 0 means not initialized and ready to init
37 * -1 means failed to init, don't try anymore
38 * >0 is the number of supported pmu event symbols
39 */
40static int perf_pmu_events_list_num;
41
32static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 42static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
33 [PERF_COUNT_HW_CPU_CYCLES] = { 43 [PERF_COUNT_HW_CPU_CYCLES] = {
34 .symbol = "cpu-cycles", 44 .symbol = "cpu-cycles",
@@ -633,18 +643,28 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
633 char *name, struct list_head *head_config) 643 char *name, struct list_head *head_config)
634{ 644{
635 struct perf_event_attr attr; 645 struct perf_event_attr attr;
646 struct perf_pmu_info info;
636 struct perf_pmu *pmu; 647 struct perf_pmu *pmu;
637 struct perf_evsel *evsel; 648 struct perf_evsel *evsel;
638 const char *unit;
639 double scale;
640 649
641 pmu = perf_pmu__find(name); 650 pmu = perf_pmu__find(name);
642 if (!pmu) 651 if (!pmu)
643 return -EINVAL; 652 return -EINVAL;
644 653
645 memset(&attr, 0, sizeof(attr)); 654 if (pmu->default_config) {
655 memcpy(&attr, pmu->default_config,
656 sizeof(struct perf_event_attr));
657 } else {
658 memset(&attr, 0, sizeof(attr));
659 }
646 660
647 if (perf_pmu__check_alias(pmu, head_config, &unit, &scale)) 661 if (!head_config) {
662 attr.type = pmu->type;
663 evsel = __add_event(list, idx, &attr, NULL, pmu->cpus);
664 return evsel ? 0 : -ENOMEM;
665 }
666
667 if (perf_pmu__check_alias(pmu, head_config, &info))
648 return -EINVAL; 668 return -EINVAL;
649 669
650 /* 670 /*
@@ -659,8 +679,10 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
659 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config), 679 evsel = __add_event(list, idx, &attr, pmu_event_name(head_config),
660 pmu->cpus); 680 pmu->cpus);
661 if (evsel) { 681 if (evsel) {
662 evsel->unit = unit; 682 evsel->unit = info.unit;
663 evsel->scale = scale; 683 evsel->scale = info.scale;
684 evsel->per_pkg = info.per_pkg;
685 evsel->snapshot = info.snapshot;
664 } 686 }
665 687
666 return evsel ? 0 : -ENOMEM; 688 return evsel ? 0 : -ENOMEM;
@@ -852,30 +874,111 @@ int parse_events_name(struct list_head *list, char *name)
852 return 0; 874 return 0;
853} 875}
854 876
855static int parse_events__scanner(const char *str, void *data, int start_token); 877static int
878comp_pmu(const void *p1, const void *p2)
879{
880 struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1;
881 struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2;
856 882
857static int parse_events_fixup(int ret, const char *str, void *data, 883 return strcmp(pmu1->symbol, pmu2->symbol);
858 int start_token) 884}
885
886static void perf_pmu__parse_cleanup(void)
859{ 887{
860 char *o = strdup(str); 888 if (perf_pmu_events_list_num > 0) {
861 char *s = NULL; 889 struct perf_pmu_event_symbol *p;
862 char *t = o; 890 int i;
863 char *p; 891
892 for (i = 0; i < perf_pmu_events_list_num; i++) {
893 p = perf_pmu_events_list + i;
894 free(p->symbol);
895 }
896 free(perf_pmu_events_list);
897 perf_pmu_events_list = NULL;
898 perf_pmu_events_list_num = 0;
899 }
900}
901
902#define SET_SYMBOL(str, stype) \
903do { \
904 p->symbol = str; \
905 if (!p->symbol) \
906 goto err; \
907 p->type = stype; \
908} while (0)
909
910/*
911 * Read the pmu events list from sysfs
912 * Save it into perf_pmu_events_list
913 */
914static void perf_pmu__parse_init(void)
915{
916
917 struct perf_pmu *pmu = NULL;
918 struct perf_pmu_alias *alias;
864 int len = 0; 919 int len = 0;
865 920
866 if (!o) 921 pmu = perf_pmu__find("cpu");
867 return ret; 922 if ((pmu == NULL) || list_empty(&pmu->aliases)) {
868 while ((p = strsep(&t, ",")) != NULL) { 923 perf_pmu_events_list_num = -1;
869 if (s) 924 return;
870 str_append(&s, &len, ",");
871 str_append(&s, &len, "cpu/");
872 str_append(&s, &len, p);
873 str_append(&s, &len, "/");
874 } 925 }
875 free(o); 926 list_for_each_entry(alias, &pmu->aliases, list) {
876 if (!s) 927 if (strchr(alias->name, '-'))
877 return -ENOMEM; 928 len++;
878 return parse_events__scanner(s, data, start_token); 929 len++;
930 }
931 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
932 if (!perf_pmu_events_list)
933 return;
934 perf_pmu_events_list_num = len;
935
936 len = 0;
937 list_for_each_entry(alias, &pmu->aliases, list) {
938 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
939 char *tmp = strchr(alias->name, '-');
940
941 if (tmp != NULL) {
942 SET_SYMBOL(strndup(alias->name, tmp - alias->name),
943 PMU_EVENT_SYMBOL_PREFIX);
944 p++;
945 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
946 len += 2;
947 } else {
948 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
949 len++;
950 }
951 }
952 qsort(perf_pmu_events_list, len,
953 sizeof(struct perf_pmu_event_symbol), comp_pmu);
954
955 return;
956err:
957 perf_pmu__parse_cleanup();
958}
959
960enum perf_pmu_event_symbol_type
961perf_pmu__parse_check(const char *name)
962{
963 struct perf_pmu_event_symbol p, *r;
964
965 /* scan kernel pmu events from sysfs if needed */
966 if (perf_pmu_events_list_num == 0)
967 perf_pmu__parse_init();
968 /*
969 * name "cpu" could be prefix of cpu-cycles or cpu// events.
970 * cpu-cycles has been handled by hardcode.
971 * So it must be cpu// events, not kernel pmu event.
972 */
973 if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu"))
974 return PMU_EVENT_SYMBOL_ERR;
975
976 p.symbol = strdup(name);
977 r = bsearch(&p, perf_pmu_events_list,
978 (size_t) perf_pmu_events_list_num,
979 sizeof(struct perf_pmu_event_symbol), comp_pmu);
980 free(p.symbol);
981 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
879} 982}
880 983
881static int parse_events__scanner(const char *str, void *data, int start_token) 984static int parse_events__scanner(const char *str, void *data, int start_token)
@@ -898,8 +1001,6 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
898 parse_events__flush_buffer(buffer, scanner); 1001 parse_events__flush_buffer(buffer, scanner);
899 parse_events__delete_buffer(buffer, scanner); 1002 parse_events__delete_buffer(buffer, scanner);
900 parse_events_lex_destroy(scanner); 1003 parse_events_lex_destroy(scanner);
901 if (ret && !strchr(str, '/'))
902 ret = parse_events_fixup(ret, str, data, start_token);
903 return ret; 1004 return ret;
904} 1005}
905 1006
@@ -934,6 +1035,7 @@ int parse_events(struct perf_evlist *evlist, const char *str)
934 int ret; 1035 int ret;
935 1036
936 ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1037 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
1038 perf_pmu__parse_cleanup();
937 if (!ret) { 1039 if (!ret) {
938 int entries = data.idx - evlist->nr_entries; 1040 int entries = data.idx - evlist->nr_entries;
939 perf_evlist__splice_list_tail(evlist, &data.list, entries); 1041 perf_evlist__splice_list_tail(evlist, &data.list, entries);
@@ -973,7 +1075,7 @@ int parse_filter(const struct option *opt, const char *str,
973 1075
974 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) { 1076 if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
975 fprintf(stderr, 1077 fprintf(stderr,
976 "-F option should follow a -e tracepoint option\n"); 1078 "--filter option should follow a -e tracepoint option\n");
977 return -1; 1079 return -1;
978 } 1080 }
979 1081
@@ -1006,9 +1108,11 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
1006 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; 1108 struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
1007 char evt_path[MAXPATHLEN]; 1109 char evt_path[MAXPATHLEN];
1008 char dir_path[MAXPATHLEN]; 1110 char dir_path[MAXPATHLEN];
1111 char sbuf[STRERR_BUFSIZE];
1009 1112
1010 if (debugfs_valid_mountpoint(tracing_events_path)) { 1113 if (debugfs_valid_mountpoint(tracing_events_path)) {
1011 printf(" [ Tracepoints not available: %s ]\n", strerror(errno)); 1114 printf(" [ Tracepoints not available: %s ]\n",
1115 strerror_r(errno, sbuf, sizeof(sbuf)));
1012 return; 1116 return;
1013 } 1117 }
1014 1118
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index df094b4ed5ed..db2cf78ff0f3 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -35,6 +35,18 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
35 35
36#define EVENTS_HELP_MAX (128*1024) 36#define EVENTS_HELP_MAX (128*1024)
37 37
38enum perf_pmu_event_symbol_type {
39 PMU_EVENT_SYMBOL_ERR, /* not a PMU EVENT */
40 PMU_EVENT_SYMBOL, /* normal style PMU event */
41 PMU_EVENT_SYMBOL_PREFIX, /* prefix of pre-suf style event */
42 PMU_EVENT_SYMBOL_SUFFIX, /* suffix of pre-suf style event */
43};
44
45struct perf_pmu_event_symbol {
46 char *symbol;
47 enum perf_pmu_event_symbol_type type;
48};
49
38enum { 50enum {
39 PARSE_EVENTS__TERM_TYPE_NUM, 51 PARSE_EVENTS__TERM_TYPE_NUM,
40 PARSE_EVENTS__TERM_TYPE_STR, 52 PARSE_EVENTS__TERM_TYPE_STR,
@@ -95,6 +107,8 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
95 void *ptr, char *type); 107 void *ptr, char *type);
96int parse_events_add_pmu(struct list_head *list, int *idx, 108int parse_events_add_pmu(struct list_head *list, int *idx,
97 char *pmu , struct list_head *head_config); 109 char *pmu , struct list_head *head_config);
110enum perf_pmu_event_symbol_type
111perf_pmu__parse_check(const char *name);
98void parse_events__set_leader(char *name, struct list_head *list); 112void parse_events__set_leader(char *name, struct list_head *list);
99void parse_events_update_lists(struct list_head *list_event, 113void parse_events_update_lists(struct list_head *list_event,
100 struct list_head *list_all); 114 struct list_head *list_all);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 343299575b30..906630bbf8eb 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -51,6 +51,24 @@ static int str(yyscan_t scanner, int token)
51 return token; 51 return token;
52} 52}
53 53
54static int pmu_str_check(yyscan_t scanner)
55{
56 YYSTYPE *yylval = parse_events_get_lval(scanner);
57 char *text = parse_events_get_text(scanner);
58
59 yylval->str = strdup(text);
60 switch (perf_pmu__parse_check(text)) {
61 case PMU_EVENT_SYMBOL_PREFIX:
62 return PE_PMU_EVENT_PRE;
63 case PMU_EVENT_SYMBOL_SUFFIX:
64 return PE_PMU_EVENT_SUF;
65 case PMU_EVENT_SYMBOL:
66 return PE_KERNEL_PMU_EVENT;
67 default:
68 return PE_NAME;
69 }
70}
71
54static int sym(yyscan_t scanner, int type, int config) 72static int sym(yyscan_t scanner, int type, int config)
55{ 73{
56 YYSTYPE *yylval = parse_events_get_lval(scanner); 74 YYSTYPE *yylval = parse_events_get_lval(scanner);
@@ -178,6 +196,16 @@ alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_AL
178emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 196emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
179dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 197dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
180 198
199 /*
200 * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
201 * Because the prefix cycles is mixed up with cpu-cycles.
202 * loads and stores are mixed up with cache event
203 */
204cycles-ct { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
205cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
206mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
207mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
208
181L1-dcache|l1-d|l1d|L1-data | 209L1-dcache|l1-d|l1d|L1-data |
182L1-icache|l1-i|l1i|L1-instruction | 210L1-icache|l1-i|l1i|L1-instruction |
183LLC|L2 | 211LLC|L2 |
@@ -199,7 +227,7 @@ r{num_raw_hex} { return raw(yyscanner); }
199{num_hex} { return value(yyscanner, 16); } 227{num_hex} { return value(yyscanner, 16); }
200 228
201{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 229{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
202{name} { return str(yyscanner, PE_NAME); } 230{name} { return pmu_str_check(yyscanner); }
203"/" { BEGIN(config); return '/'; } 231"/" { BEGIN(config); return '/'; }
204- { return '-'; } 232- { return '-'; }
205, { BEGIN(event); return ','; } 233, { BEGIN(event); return ','; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 0bc87ba46bf3..93c4c9fbc922 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -47,6 +47,7 @@ static inc_group_count(struct list_head *list,
47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
49%token PE_ERROR 49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
50%type <num> PE_VALUE 51%type <num> PE_VALUE
51%type <num> PE_VALUE_SYM_HW 52%type <num> PE_VALUE_SYM_HW
52%type <num> PE_VALUE_SYM_SW 53%type <num> PE_VALUE_SYM_SW
@@ -58,6 +59,7 @@ static inc_group_count(struct list_head *list,
58%type <str> PE_MODIFIER_EVENT 59%type <str> PE_MODIFIER_EVENT
59%type <str> PE_MODIFIER_BP 60%type <str> PE_MODIFIER_BP
60%type <str> PE_EVENT_NAME 61%type <str> PE_EVENT_NAME
62%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
61%type <num> value_sym 63%type <num> value_sym
62%type <head> event_config 64%type <head> event_config
63%type <term> event_term 65%type <term> event_term
@@ -210,6 +212,54 @@ PE_NAME '/' event_config '/'
210 parse_events__free_terms($3); 212 parse_events__free_terms($3);
211 $$ = list; 213 $$ = list;
212} 214}
215|
216PE_NAME '/' '/'
217{
218 struct parse_events_evlist *data = _data;
219 struct list_head *list;
220
221 ALLOC_LIST(list);
222 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
223 $$ = list;
224}
225|
226PE_KERNEL_PMU_EVENT sep_dc
227{
228 struct parse_events_evlist *data = _data;
229 struct list_head *head;
230 struct parse_events_term *term;
231 struct list_head *list;
232
233 ALLOC_LIST(head);
234 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
235 $1, 1));
236 list_add_tail(&term->list, head);
237
238 ALLOC_LIST(list);
239 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
240 parse_events__free_terms(head);
241 $$ = list;
242}
243|
244PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
245{
246 struct parse_events_evlist *data = _data;
247 struct list_head *head;
248 struct parse_events_term *term;
249 struct list_head *list;
250 char pmu_name[128];
251 snprintf(&pmu_name, 128, "%s-%s", $1, $3);
252
253 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 &pmu_name, 1));
256 list_add_tail(&term->list, head);
257
258 ALLOC_LIST(list);
259 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
260 parse_events__free_terms(head);
261 $$ = list;
262}
213 263
214value_sym: 264value_sym:
215PE_VALUE_SYM_HW 265PE_VALUE_SYM_HW
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c
index bf48092983c6..f62dee7bd924 100644
--- a/tools/perf/util/parse-options.c
+++ b/tools/perf/util/parse-options.c
@@ -42,7 +42,26 @@ static int get_value(struct parse_opt_ctx_t *p,
42 return opterror(opt, "takes no value", flags); 42 return opterror(opt, "takes no value", flags);
43 if (unset && (opt->flags & PARSE_OPT_NONEG)) 43 if (unset && (opt->flags & PARSE_OPT_NONEG))
44 return opterror(opt, "isn't available", flags); 44 return opterror(opt, "isn't available", flags);
45 45 if (opt->flags & PARSE_OPT_DISABLED)
46 return opterror(opt, "is not usable", flags);
47
48 if (opt->flags & PARSE_OPT_EXCLUSIVE) {
49 if (p->excl_opt) {
50 char msg[128];
51
52 if (((flags & OPT_SHORT) && p->excl_opt->short_name) ||
53 p->excl_opt->long_name == NULL) {
54 scnprintf(msg, sizeof(msg), "cannot be used with switch `%c'",
55 p->excl_opt->short_name);
56 } else {
57 scnprintf(msg, sizeof(msg), "cannot be used with %s",
58 p->excl_opt->long_name);
59 }
60 opterror(opt, msg, flags);
61 return -3;
62 }
63 p->excl_opt = opt;
64 }
46 if (!(flags & OPT_SHORT) && p->opt) { 65 if (!(flags & OPT_SHORT) && p->opt) {
47 switch (opt->type) { 66 switch (opt->type) {
48 case OPTION_CALLBACK: 67 case OPTION_CALLBACK:
@@ -343,13 +362,14 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
343 const char * const usagestr[]) 362 const char * const usagestr[])
344{ 363{
345 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP); 364 int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
365 int excl_short_opt = 1;
366 const char *arg;
346 367
347 /* we must reset ->opt, unknown short option leave it dangling */ 368 /* we must reset ->opt, unknown short option leave it dangling */
348 ctx->opt = NULL; 369 ctx->opt = NULL;
349 370
350 for (; ctx->argc; ctx->argc--, ctx->argv++) { 371 for (; ctx->argc; ctx->argc--, ctx->argv++) {
351 const char *arg = ctx->argv[0]; 372 arg = ctx->argv[0];
352
353 if (*arg != '-' || !arg[1]) { 373 if (*arg != '-' || !arg[1]) {
354 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION) 374 if (ctx->flags & PARSE_OPT_STOP_AT_NON_OPTION)
355 break; 375 break;
@@ -358,19 +378,21 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
358 } 378 }
359 379
360 if (arg[1] != '-') { 380 if (arg[1] != '-') {
361 ctx->opt = arg + 1; 381 ctx->opt = ++arg;
362 if (internal_help && *ctx->opt == 'h') 382 if (internal_help && *ctx->opt == 'h')
363 return usage_with_options_internal(usagestr, options, 0); 383 return usage_with_options_internal(usagestr, options, 0);
364 switch (parse_short_opt(ctx, options)) { 384 switch (parse_short_opt(ctx, options)) {
365 case -1: 385 case -1:
366 return parse_options_usage(usagestr, options, arg + 1, 1); 386 return parse_options_usage(usagestr, options, arg, 1);
367 case -2: 387 case -2:
368 goto unknown; 388 goto unknown;
389 case -3:
390 goto exclusive;
369 default: 391 default:
370 break; 392 break;
371 } 393 }
372 if (ctx->opt) 394 if (ctx->opt)
373 check_typos(arg + 1, options); 395 check_typos(arg, options);
374 while (ctx->opt) { 396 while (ctx->opt) {
375 if (internal_help && *ctx->opt == 'h') 397 if (internal_help && *ctx->opt == 'h')
376 return usage_with_options_internal(usagestr, options, 0); 398 return usage_with_options_internal(usagestr, options, 0);
@@ -387,6 +409,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
387 ctx->argv[0] = strdup(ctx->opt - 1); 409 ctx->argv[0] = strdup(ctx->opt - 1);
388 *(char *)ctx->argv[0] = '-'; 410 *(char *)ctx->argv[0] = '-';
389 goto unknown; 411 goto unknown;
412 case -3:
413 goto exclusive;
390 default: 414 default:
391 break; 415 break;
392 } 416 }
@@ -402,19 +426,23 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
402 break; 426 break;
403 } 427 }
404 428
405 if (internal_help && !strcmp(arg + 2, "help-all")) 429 arg += 2;
430 if (internal_help && !strcmp(arg, "help-all"))
406 return usage_with_options_internal(usagestr, options, 1); 431 return usage_with_options_internal(usagestr, options, 1);
407 if (internal_help && !strcmp(arg + 2, "help")) 432 if (internal_help && !strcmp(arg, "help"))
408 return usage_with_options_internal(usagestr, options, 0); 433 return usage_with_options_internal(usagestr, options, 0);
409 if (!strcmp(arg + 2, "list-opts")) 434 if (!strcmp(arg, "list-opts"))
410 return PARSE_OPT_LIST_OPTS; 435 return PARSE_OPT_LIST_OPTS;
411 if (!strcmp(arg + 2, "list-cmds")) 436 if (!strcmp(arg, "list-cmds"))
412 return PARSE_OPT_LIST_SUBCMDS; 437 return PARSE_OPT_LIST_SUBCMDS;
413 switch (parse_long_opt(ctx, arg + 2, options)) { 438 switch (parse_long_opt(ctx, arg, options)) {
414 case -1: 439 case -1:
415 return parse_options_usage(usagestr, options, arg + 2, 0); 440 return parse_options_usage(usagestr, options, arg, 0);
416 case -2: 441 case -2:
417 goto unknown; 442 goto unknown;
443 case -3:
444 excl_short_opt = 0;
445 goto exclusive;
418 default: 446 default:
419 break; 447 break;
420 } 448 }
@@ -426,6 +454,17 @@ unknown:
426 ctx->opt = NULL; 454 ctx->opt = NULL;
427 } 455 }
428 return PARSE_OPT_DONE; 456 return PARSE_OPT_DONE;
457
458exclusive:
459 parse_options_usage(usagestr, options, arg, excl_short_opt);
460 if ((excl_short_opt && ctx->excl_opt->short_name) ||
461 ctx->excl_opt->long_name == NULL) {
462 char opt = ctx->excl_opt->short_name;
463 parse_options_usage(NULL, options, &opt, 1);
464 } else {
465 parse_options_usage(NULL, options, ctx->excl_opt->long_name, 0);
466 }
467 return PARSE_OPT_HELP;
429} 468}
430 469
431int parse_options_end(struct parse_opt_ctx_t *ctx) 470int parse_options_end(struct parse_opt_ctx_t *ctx)
@@ -509,6 +548,8 @@ static void print_option_help(const struct option *opts, int full)
509 } 548 }
510 if (!full && (opts->flags & PARSE_OPT_HIDDEN)) 549 if (!full && (opts->flags & PARSE_OPT_HIDDEN))
511 return; 550 return;
551 if (opts->flags & PARSE_OPT_DISABLED)
552 return;
512 553
513 pos = fprintf(stderr, " "); 554 pos = fprintf(stderr, " ");
514 if (opts->short_name) 555 if (opts->short_name)
@@ -679,3 +720,16 @@ int parse_opt_verbosity_cb(const struct option *opt,
679 } 720 }
680 return 0; 721 return 0;
681} 722}
723
724void set_option_flag(struct option *opts, int shortopt, const char *longopt,
725 int flag)
726{
727 for (; opts->type != OPTION_END; opts++) {
728 if ((shortopt && opts->short_name == shortopt) ||
729 (opts->long_name && longopt &&
730 !strcmp(opts->long_name, longopt))) {
731 opts->flags |= flag;
732 break;
733 }
734 }
735}
diff --git a/tools/perf/util/parse-options.h b/tools/perf/util/parse-options.h
index b59ba858e73d..97b153fb4999 100644
--- a/tools/perf/util/parse-options.h
+++ b/tools/perf/util/parse-options.h
@@ -38,6 +38,8 @@ enum parse_opt_option_flags {
38 PARSE_OPT_NONEG = 4, 38 PARSE_OPT_NONEG = 4,
39 PARSE_OPT_HIDDEN = 8, 39 PARSE_OPT_HIDDEN = 8,
40 PARSE_OPT_LASTARG_DEFAULT = 16, 40 PARSE_OPT_LASTARG_DEFAULT = 16,
41 PARSE_OPT_DISABLED = 32,
42 PARSE_OPT_EXCLUSIVE = 64,
41}; 43};
42 44
43struct option; 45struct option;
@@ -173,6 +175,7 @@ struct parse_opt_ctx_t {
173 const char **out; 175 const char **out;
174 int argc, cpidx; 176 int argc, cpidx;
175 const char *opt; 177 const char *opt;
178 const struct option *excl_opt;
176 int flags; 179 int flags;
177}; 180};
178 181
@@ -211,4 +214,5 @@ extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
211 214
212extern const char *parse_options_fix_filename(const char *prefix, const char *file); 215extern const char *parse_options_fix_filename(const char *prefix, const char *file);
213 216
217void set_option_flag(struct option *opts, int sopt, const char *lopt, int flag);
214#endif /* __PERF_PARSE_OPTIONS_H */ 218#endif /* __PERF_PARSE_OPTIONS_H */
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 7a811eb61f75..5c9c4947cfb4 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -2,6 +2,8 @@
2#include <sys/types.h> 2#include <sys/types.h>
3#include <unistd.h> 3#include <unistd.h>
4#include <stdio.h> 4#include <stdio.h>
5#include <stdbool.h>
6#include <stdarg.h>
5#include <dirent.h> 7#include <dirent.h>
6#include <api/fs/fs.h> 8#include <api/fs/fs.h>
7#include <locale.h> 9#include <locale.h>
@@ -10,16 +12,6 @@
10#include "parse-events.h" 12#include "parse-events.h"
11#include "cpumap.h" 13#include "cpumap.h"
12 14
13#define UNIT_MAX_LEN 31 /* max length for event unit name */
14
15struct perf_pmu_alias {
16 char *name;
17 struct list_head terms;
18 struct list_head list;
19 char unit[UNIT_MAX_LEN+1];
20 double scale;
21};
22
23struct perf_pmu_format { 15struct perf_pmu_format {
24 char *name; 16 char *name;
25 int value; 17 int value;
@@ -171,6 +163,41 @@ error:
171 return -1; 163 return -1;
172} 164}
173 165
166static int
167perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, char *dir, char *name)
168{
169 char path[PATH_MAX];
170 int fd;
171
172 snprintf(path, PATH_MAX, "%s/%s.per-pkg", dir, name);
173
174 fd = open(path, O_RDONLY);
175 if (fd == -1)
176 return -1;
177
178 close(fd);
179
180 alias->per_pkg = true;
181 return 0;
182}
183
184static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
185 char *dir, char *name)
186{
187 char path[PATH_MAX];
188 int fd;
189
190 snprintf(path, PATH_MAX, "%s/%s.snapshot", dir, name);
191
192 fd = open(path, O_RDONLY);
193 if (fd == -1)
194 return -1;
195
196 alias->snapshot = true;
197 close(fd);
198 return 0;
199}
200
174static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file) 201static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
175{ 202{
176 struct perf_pmu_alias *alias; 203 struct perf_pmu_alias *alias;
@@ -189,6 +216,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
189 INIT_LIST_HEAD(&alias->terms); 216 INIT_LIST_HEAD(&alias->terms);
190 alias->scale = 1.0; 217 alias->scale = 1.0;
191 alias->unit[0] = '\0'; 218 alias->unit[0] = '\0';
219 alias->per_pkg = false;
192 220
193 ret = parse_events_terms(&alias->terms, buf); 221 ret = parse_events_terms(&alias->terms, buf);
194 if (ret) { 222 if (ret) {
@@ -202,12 +230,31 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
202 */ 230 */
203 perf_pmu__parse_unit(alias, dir, name); 231 perf_pmu__parse_unit(alias, dir, name);
204 perf_pmu__parse_scale(alias, dir, name); 232 perf_pmu__parse_scale(alias, dir, name);
233 perf_pmu__parse_per_pkg(alias, dir, name);
234 perf_pmu__parse_snapshot(alias, dir, name);
205 235
206 list_add_tail(&alias->list, list); 236 list_add_tail(&alias->list, list);
207 237
208 return 0; 238 return 0;
209} 239}
210 240
241static inline bool pmu_alias_info_file(char *name)
242{
243 size_t len;
244
245 len = strlen(name);
246 if (len > 5 && !strcmp(name + len - 5, ".unit"))
247 return true;
248 if (len > 6 && !strcmp(name + len - 6, ".scale"))
249 return true;
250 if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
251 return true;
252 if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
253 return true;
254
255 return false;
256}
257
211/* 258/*
212 * Process all the sysfs attributes located under the directory 259 * Process all the sysfs attributes located under the directory
213 * specified in 'dir' parameter. 260 * specified in 'dir' parameter.
@@ -216,7 +263,6 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
216{ 263{
217 struct dirent *evt_ent; 264 struct dirent *evt_ent;
218 DIR *event_dir; 265 DIR *event_dir;
219 size_t len;
220 int ret = 0; 266 int ret = 0;
221 267
222 event_dir = opendir(dir); 268 event_dir = opendir(dir);
@@ -232,13 +278,9 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
232 continue; 278 continue;
233 279
234 /* 280 /*
235 * skip .unit and .scale info files 281 * skip info files parsed in perf_pmu__new_alias()
236 * parsed in perf_pmu__new_alias()
237 */ 282 */
238 len = strlen(name); 283 if (pmu_alias_info_file(name))
239 if (len > 5 && !strcmp(name + len - 5, ".unit"))
240 continue;
241 if (len > 6 && !strcmp(name + len - 6, ".scale"))
242 continue; 284 continue;
243 285
244 snprintf(path, PATH_MAX, "%s/%s", dir, name); 286 snprintf(path, PATH_MAX, "%s/%s", dir, name);
@@ -387,6 +429,12 @@ static struct cpu_map *pmu_cpumask(const char *name)
387 return cpus; 429 return cpus;
388} 430}
389 431
432struct perf_event_attr *__attribute__((weak))
433perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
434{
435 return NULL;
436}
437
390static struct perf_pmu *pmu_lookup(const char *name) 438static struct perf_pmu *pmu_lookup(const char *name)
391{ 439{
392 struct perf_pmu *pmu; 440 struct perf_pmu *pmu;
@@ -421,6 +469,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
421 pmu->name = strdup(name); 469 pmu->name = strdup(name);
422 pmu->type = type; 470 pmu->type = type;
423 list_add_tail(&pmu->list, &pmus); 471 list_add_tail(&pmu->list, &pmus);
472
473 pmu->default_config = perf_pmu__get_default_config(pmu);
474
424 return pmu; 475 return pmu;
425} 476}
426 477
@@ -479,28 +530,24 @@ pmu_find_format(struct list_head *formats, char *name)
479} 530}
480 531
481/* 532/*
482 * Returns value based on the format definition (format parameter) 533 * Sets value based on the format definition (format parameter)
483 * and unformated value (value parameter). 534 * and unformated value (value parameter).
484 *
485 * TODO maybe optimize a little ;)
486 */ 535 */
487static __u64 pmu_format_value(unsigned long *format, __u64 value) 536static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
537 bool zero)
488{ 538{
489 unsigned long fbit, vbit; 539 unsigned long fbit, vbit;
490 __u64 v = 0;
491 540
492 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) { 541 for (fbit = 0, vbit = 0; fbit < PERF_PMU_FORMAT_BITS; fbit++) {
493 542
494 if (!test_bit(fbit, format)) 543 if (!test_bit(fbit, format))
495 continue; 544 continue;
496 545
497 if (!(value & (1llu << vbit++))) 546 if (value & (1llu << vbit++))
498 continue; 547 *v |= (1llu << fbit);
499 548 else if (zero)
500 v |= (1llu << fbit); 549 *v &= ~(1llu << fbit);
501 } 550 }
502
503 return v;
504} 551}
505 552
506/* 553/*
@@ -509,7 +556,8 @@ static __u64 pmu_format_value(unsigned long *format, __u64 value)
509 */ 556 */
510static int pmu_config_term(struct list_head *formats, 557static int pmu_config_term(struct list_head *formats,
511 struct perf_event_attr *attr, 558 struct perf_event_attr *attr,
512 struct parse_events_term *term) 559 struct parse_events_term *term,
560 bool zero)
513{ 561{
514 struct perf_pmu_format *format; 562 struct perf_pmu_format *format;
515 __u64 *vp; 563 __u64 *vp;
@@ -548,18 +596,19 @@ static int pmu_config_term(struct list_head *formats,
548 * non-hardcoded terms, here's the place to translate 596 * non-hardcoded terms, here's the place to translate
549 * them into value. 597 * them into value.
550 */ 598 */
551 *vp |= pmu_format_value(format->bits, term->val.num); 599 pmu_format_value(format->bits, term->val.num, vp, zero);
552 return 0; 600 return 0;
553} 601}
554 602
555int perf_pmu__config_terms(struct list_head *formats, 603int perf_pmu__config_terms(struct list_head *formats,
556 struct perf_event_attr *attr, 604 struct perf_event_attr *attr,
557 struct list_head *head_terms) 605 struct list_head *head_terms,
606 bool zero)
558{ 607{
559 struct parse_events_term *term; 608 struct parse_events_term *term;
560 609
561 list_for_each_entry(term, head_terms, list) 610 list_for_each_entry(term, head_terms, list)
562 if (pmu_config_term(formats, attr, term)) 611 if (pmu_config_term(formats, attr, term, zero))
563 return -EINVAL; 612 return -EINVAL;
564 613
565 return 0; 614 return 0;
@@ -573,8 +622,10 @@ int perf_pmu__config_terms(struct list_head *formats,
573int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 622int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
574 struct list_head *head_terms) 623 struct list_head *head_terms)
575{ 624{
625 bool zero = !!pmu->default_config;
626
576 attr->type = pmu->type; 627 attr->type = pmu->type;
577 return perf_pmu__config_terms(&pmu->format, attr, head_terms); 628 return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
578} 629}
579 630
580static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu, 631static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
@@ -608,23 +659,27 @@ static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
608} 659}
609 660
610 661
611static int check_unit_scale(struct perf_pmu_alias *alias, 662static int check_info_data(struct perf_pmu_alias *alias,
612 const char **unit, double *scale) 663 struct perf_pmu_info *info)
613{ 664{
614 /* 665 /*
615 * Only one term in event definition can 666 * Only one term in event definition can
616 * define unit and scale, fail if there's 667 * define unit, scale and snapshot, fail
617 * more than one. 668 * if there's more than one.
618 */ 669 */
619 if ((*unit && alias->unit) || 670 if ((info->unit && alias->unit) ||
620 (*scale && alias->scale)) 671 (info->scale && alias->scale) ||
672 (info->snapshot && alias->snapshot))
621 return -EINVAL; 673 return -EINVAL;
622 674
623 if (alias->unit) 675 if (alias->unit)
624 *unit = alias->unit; 676 info->unit = alias->unit;
625 677
626 if (alias->scale) 678 if (alias->scale)
627 *scale = alias->scale; 679 info->scale = alias->scale;
680
681 if (alias->snapshot)
682 info->snapshot = alias->snapshot;
628 683
629 return 0; 684 return 0;
630} 685}
@@ -634,18 +689,21 @@ static int check_unit_scale(struct perf_pmu_alias *alias,
634 * defined for the alias 689 * defined for the alias
635 */ 690 */
636int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 691int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
637 const char **unit, double *scale) 692 struct perf_pmu_info *info)
638{ 693{
639 struct parse_events_term *term, *h; 694 struct parse_events_term *term, *h;
640 struct perf_pmu_alias *alias; 695 struct perf_pmu_alias *alias;
641 int ret; 696 int ret;
642 697
698 info->per_pkg = false;
699
643 /* 700 /*
644 * Mark unit and scale as not set 701 * Mark unit and scale as not set
645 * (different from default values, see below) 702 * (different from default values, see below)
646 */ 703 */
647 *unit = NULL; 704 info->unit = NULL;
648 *scale = 0.0; 705 info->scale = 0.0;
706 info->snapshot = false;
649 707
650 list_for_each_entry_safe(term, h, head_terms, list) { 708 list_for_each_entry_safe(term, h, head_terms, list) {
651 alias = pmu_find_alias(pmu, term); 709 alias = pmu_find_alias(pmu, term);
@@ -655,10 +713,13 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
655 if (ret) 713 if (ret)
656 return ret; 714 return ret;
657 715
658 ret = check_unit_scale(alias, unit, scale); 716 ret = check_info_data(alias, info);
659 if (ret) 717 if (ret)
660 return ret; 718 return ret;
661 719
720 if (alias->per_pkg)
721 info->per_pkg = true;
722
662 list_del(&term->list); 723 list_del(&term->list);
663 free(term); 724 free(term);
664 } 725 }
@@ -668,11 +729,11 @@ int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
668 * set defaults as for evsel 729 * set defaults as for evsel
669 * unit cannot left to NULL 730 * unit cannot left to NULL
670 */ 731 */
671 if (*unit == NULL) 732 if (info->unit == NULL)
672 *unit = ""; 733 info->unit = "";
673 734
674 if (*scale == 0.0) 735 if (info->scale == 0.0)
675 *scale = 1.0; 736 info->scale = 1.0;
676 737
677 return 0; 738 return 0;
678} 739}
@@ -738,15 +799,18 @@ void print_pmu_events(const char *event_glob, bool name_only)
738 799
739 pmu = NULL; 800 pmu = NULL;
740 len = 0; 801 len = 0;
741 while ((pmu = perf_pmu__scan(pmu)) != NULL) 802 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
742 list_for_each_entry(alias, &pmu->aliases, list) 803 list_for_each_entry(alias, &pmu->aliases, list)
743 len++; 804 len++;
744 aliases = malloc(sizeof(char *) * len); 805 if (pmu->selectable)
806 len++;
807 }
808 aliases = zalloc(sizeof(char *) * len);
745 if (!aliases) 809 if (!aliases)
746 return; 810 goto out_enomem;
747 pmu = NULL; 811 pmu = NULL;
748 j = 0; 812 j = 0;
749 while ((pmu = perf_pmu__scan(pmu)) != NULL) 813 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
750 list_for_each_entry(alias, &pmu->aliases, list) { 814 list_for_each_entry(alias, &pmu->aliases, list) {
751 char *name = format_alias(buf, sizeof(buf), pmu, alias); 815 char *name = format_alias(buf, sizeof(buf), pmu, alias);
752 bool is_cpu = !strcmp(pmu->name, "cpu"); 816 bool is_cpu = !strcmp(pmu->name, "cpu");
@@ -756,13 +820,23 @@ void print_pmu_events(const char *event_glob, bool name_only)
756 (!is_cpu && strglobmatch(alias->name, 820 (!is_cpu && strglobmatch(alias->name,
757 event_glob)))) 821 event_glob))))
758 continue; 822 continue;
759 aliases[j] = name; 823
760 if (is_cpu && !name_only) 824 if (is_cpu && !name_only)
761 aliases[j] = format_alias_or(buf, sizeof(buf), 825 name = format_alias_or(buf, sizeof(buf), pmu, alias);
762 pmu, alias); 826
763 aliases[j] = strdup(aliases[j]); 827 aliases[j] = strdup(name);
828 if (aliases[j] == NULL)
829 goto out_enomem;
764 j++; 830 j++;
765 } 831 }
832 if (pmu->selectable) {
833 char *s;
834 if (asprintf(&s, "%s//", pmu->name) < 0)
835 goto out_enomem;
836 aliases[j] = s;
837 j++;
838 }
839 }
766 len = j; 840 len = j;
767 qsort(aliases, len, sizeof(char *), cmp_string); 841 qsort(aliases, len, sizeof(char *), cmp_string);
768 for (j = 0; j < len; j++) { 842 for (j = 0; j < len; j++) {
@@ -771,12 +845,20 @@ void print_pmu_events(const char *event_glob, bool name_only)
771 continue; 845 continue;
772 } 846 }
773 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 847 printf(" %-50s [Kernel PMU event]\n", aliases[j]);
774 zfree(&aliases[j]);
775 printed++; 848 printed++;
776 } 849 }
777 if (printed) 850 if (printed)
778 printf("\n"); 851 printf("\n");
779 free(aliases); 852out_free:
853 for (j = 0; j < len; j++)
854 zfree(&aliases[j]);
855 zfree(&aliases);
856 return;
857
858out_enomem:
859 printf("FATAL: not enough memory to print PMU events\n");
860 if (aliases)
861 goto out_free;
780} 862}
781 863
782bool pmu_have_event(const char *pname, const char *name) 864bool pmu_have_event(const char *pname, const char *name)
@@ -794,3 +876,39 @@ bool pmu_have_event(const char *pname, const char *name)
794 } 876 }
795 return false; 877 return false;
796} 878}
879
880static FILE *perf_pmu__open_file(struct perf_pmu *pmu, const char *name)
881{
882 struct stat st;
883 char path[PATH_MAX];
884 const char *sysfs;
885
886 sysfs = sysfs__mountpoint();
887 if (!sysfs)
888 return NULL;
889
890 snprintf(path, PATH_MAX,
891 "%s" EVENT_SOURCE_DEVICE_PATH "%s/%s", sysfs, pmu->name, name);
892
893 if (stat(path, &st) < 0)
894 return NULL;
895
896 return fopen(path, "r");
897}
898
899int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
900 ...)
901{
902 va_list args;
903 FILE *file;
904 int ret = EOF;
905
906 va_start(args, fmt);
907 file = perf_pmu__open_file(pmu, name);
908 if (file) {
909 ret = vfscanf(file, fmt, args);
910 fclose(file);
911 }
912 va_end(args);
913 return ret;
914}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index c14a543ce1f3..6b1249fbdb5f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -13,13 +13,36 @@ enum {
13 13
14#define PERF_PMU_FORMAT_BITS 64 14#define PERF_PMU_FORMAT_BITS 64
15 15
16struct perf_event_attr;
17
16struct perf_pmu { 18struct perf_pmu {
17 char *name; 19 char *name;
18 __u32 type; 20 __u32 type;
21 bool selectable;
22 struct perf_event_attr *default_config;
19 struct cpu_map *cpus; 23 struct cpu_map *cpus;
20 struct list_head format; 24 struct list_head format; /* HEAD struct perf_pmu_format -> list */
21 struct list_head aliases; 25 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
22 struct list_head list; 26 struct list_head list; /* ELEM */
27};
28
29struct perf_pmu_info {
30 const char *unit;
31 double scale;
32 bool per_pkg;
33 bool snapshot;
34};
35
36#define UNIT_MAX_LEN 31 /* max length for event unit name */
37
38struct perf_pmu_alias {
39 char *name;
40 struct list_head terms; /* HEAD struct parse_events_term -> list */
41 struct list_head list; /* ELEM */
42 char unit[UNIT_MAX_LEN+1];
43 double scale;
44 bool per_pkg;
45 bool snapshot;
23}; 46};
24 47
25struct perf_pmu *perf_pmu__find(const char *name); 48struct perf_pmu *perf_pmu__find(const char *name);
@@ -27,9 +50,10 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
27 struct list_head *head_terms); 50 struct list_head *head_terms);
28int perf_pmu__config_terms(struct list_head *formats, 51int perf_pmu__config_terms(struct list_head *formats,
29 struct perf_event_attr *attr, 52 struct perf_event_attr *attr,
30 struct list_head *head_terms); 53 struct list_head *head_terms,
54 bool zero);
31int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms, 55int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
32 const char **unit, double *scale); 56 struct perf_pmu_info *info);
33struct list_head *perf_pmu__alias(struct perf_pmu *pmu, 57struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
34 struct list_head *head_terms); 58 struct list_head *head_terms);
35int perf_pmu_wrap(void); 59int perf_pmu_wrap(void);
@@ -45,5 +69,11 @@ struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
45void print_pmu_events(const char *event_glob, bool name_only); 69void print_pmu_events(const char *event_glob, bool name_only);
46bool pmu_have_event(const char *pname, const char *name); 70bool pmu_have_event(const char *pname, const char *name);
47 71
72int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
73 ...) __attribute__((format(scanf, 3, 4)));
74
48int perf_pmu__test(void); 75int perf_pmu__test(void);
76
77struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
78
49#endif /* __PMU_H */ 79#endif /* __PMU_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 9a0a1839a377..7f9b8632e433 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -79,7 +79,7 @@ static int init_symbol_maps(bool user_only)
79 int ret; 79 int ret;
80 80
81 symbol_conf.sort_by_name = true; 81 symbol_conf.sort_by_name = true;
82 ret = symbol__init(); 82 ret = symbol__init(NULL);
83 if (ret < 0) { 83 if (ret < 0) {
84 pr_debug("Failed to init symbol map.\n"); 84 pr_debug("Failed to init symbol map.\n");
85 goto out; 85 goto out;
@@ -184,7 +184,8 @@ static struct dso *kernel_get_module_dso(const char *module)
184 const char *vmlinux_name; 184 const char *vmlinux_name;
185 185
186 if (module) { 186 if (module) {
187 list_for_each_entry(dso, &host_machine->kernel_dsos, node) { 187 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
188 node) {
188 if (strncmp(dso->short_name + 1, module, 189 if (strncmp(dso->short_name + 1, module,
189 dso->short_name_len - 2) == 0) 190 dso->short_name_len - 2) == 0)
190 goto found; 191 goto found;
@@ -258,21 +259,33 @@ static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
258#ifdef HAVE_DWARF_SUPPORT 259#ifdef HAVE_DWARF_SUPPORT
259 260
260/* Open new debuginfo of given module */ 261/* Open new debuginfo of given module */
261static struct debuginfo *open_debuginfo(const char *module) 262static struct debuginfo *open_debuginfo(const char *module, bool silent)
262{ 263{
263 const char *path = module; 264 const char *path = module;
265 struct debuginfo *ret;
264 266
265 if (!module || !strchr(module, '/')) { 267 if (!module || !strchr(module, '/')) {
266 path = kernel_get_module_path(module); 268 path = kernel_get_module_path(module);
267 if (!path) { 269 if (!path) {
268 pr_err("Failed to find path of %s module.\n", 270 if (!silent)
269 module ?: "kernel"); 271 pr_err("Failed to find path of %s module.\n",
272 module ?: "kernel");
270 return NULL; 273 return NULL;
271 } 274 }
272 } 275 }
273 return debuginfo__new(path); 276 ret = debuginfo__new(path);
277 if (!ret && !silent) {
278 pr_warning("The %s file has no debug information.\n", path);
279 if (!module || !strtailcmp(path, ".ko"))
280 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
281 else
282 pr_warning("Rebuild with -g, ");
283 pr_warning("or install an appropriate debuginfo package.\n");
284 }
285 return ret;
274} 286}
275 287
288
276static int get_text_start_address(const char *exec, unsigned long *address) 289static int get_text_start_address(const char *exec, unsigned long *address)
277{ 290{
278 Elf *elf; 291 Elf *elf;
@@ -333,15 +346,13 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
333 pr_debug("try to find information at %" PRIx64 " in %s\n", addr, 346 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
334 tp->module ? : "kernel"); 347 tp->module ? : "kernel");
335 348
336 dinfo = open_debuginfo(tp->module); 349 dinfo = open_debuginfo(tp->module, verbose == 0);
337 if (dinfo) { 350 if (dinfo) {
338 ret = debuginfo__find_probe_point(dinfo, 351 ret = debuginfo__find_probe_point(dinfo,
339 (unsigned long)addr, pp); 352 (unsigned long)addr, pp);
340 debuginfo__delete(dinfo); 353 debuginfo__delete(dinfo);
341 } else { 354 } else
342 pr_debug("Failed to open debuginfo at 0x%" PRIx64 "\n", addr);
343 ret = -ENOENT; 355 ret = -ENOENT;
344 }
345 356
346 if (ret > 0) { 357 if (ret > 0) {
347 pp->retprobe = tp->retprobe; 358 pp->retprobe = tp->retprobe;
@@ -457,13 +468,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
457 struct debuginfo *dinfo; 468 struct debuginfo *dinfo;
458 int ntevs, ret = 0; 469 int ntevs, ret = 0;
459 470
460 dinfo = open_debuginfo(target); 471 dinfo = open_debuginfo(target, !need_dwarf);
461 472
462 if (!dinfo) { 473 if (!dinfo) {
463 if (need_dwarf) { 474 if (need_dwarf)
464 pr_warning("Failed to open debuginfo file.\n");
465 return -ENOENT; 475 return -ENOENT;
466 }
467 pr_debug("Could not open debuginfo. Try to use symbols.\n"); 476 pr_debug("Could not open debuginfo. Try to use symbols.\n");
468 return 0; 477 return 0;
469 } 478 }
@@ -486,9 +495,11 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
486 } 495 }
487 496
488 if (ntevs == 0) { /* No error but failed to find probe point. */ 497 if (ntevs == 0) { /* No error but failed to find probe point. */
489 pr_warning("Probe point '%s' not found.\n", 498 pr_warning("Probe point '%s' not found in debuginfo.\n",
490 synthesize_perf_probe_point(&pev->point)); 499 synthesize_perf_probe_point(&pev->point));
491 return -ENOENT; 500 if (need_dwarf)
501 return -ENOENT;
502 return 0;
492 } 503 }
493 /* Error path : ntevs < 0 */ 504 /* Error path : ntevs < 0 */
494 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 505 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
@@ -565,7 +576,7 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
565 576
566static int __show_one_line(FILE *fp, int l, bool skip, bool show_num) 577static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
567{ 578{
568 char buf[LINEBUF_SIZE]; 579 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
569 const char *color = show_num ? "" : PERF_COLOR_BLUE; 580 const char *color = show_num ? "" : PERF_COLOR_BLUE;
570 const char *prefix = NULL; 581 const char *prefix = NULL;
571 582
@@ -585,7 +596,8 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
585 return 1; 596 return 1;
586error: 597error:
587 if (ferror(fp)) { 598 if (ferror(fp)) {
588 pr_warning("File read error: %s\n", strerror(errno)); 599 pr_warning("File read error: %s\n",
600 strerror_r(errno, sbuf, sizeof(sbuf)));
589 return -1; 601 return -1;
590 } 602 }
591 return 0; 603 return 0;
@@ -618,13 +630,12 @@ static int __show_line_range(struct line_range *lr, const char *module)
618 FILE *fp; 630 FILE *fp;
619 int ret; 631 int ret;
620 char *tmp; 632 char *tmp;
633 char sbuf[STRERR_BUFSIZE];
621 634
622 /* Search a line range */ 635 /* Search a line range */
623 dinfo = open_debuginfo(module); 636 dinfo = open_debuginfo(module, false);
624 if (!dinfo) { 637 if (!dinfo)
625 pr_warning("Failed to open debuginfo file.\n");
626 return -ENOENT; 638 return -ENOENT;
627 }
628 639
629 ret = debuginfo__find_line_range(dinfo, lr); 640 ret = debuginfo__find_line_range(dinfo, lr);
630 debuginfo__delete(dinfo); 641 debuginfo__delete(dinfo);
@@ -656,7 +667,7 @@ static int __show_line_range(struct line_range *lr, const char *module)
656 fp = fopen(lr->path, "r"); 667 fp = fopen(lr->path, "r");
657 if (fp == NULL) { 668 if (fp == NULL) {
658 pr_warning("Failed to open %s: %s\n", lr->path, 669 pr_warning("Failed to open %s: %s\n", lr->path,
659 strerror(errno)); 670 strerror_r(errno, sbuf, sizeof(sbuf)));
660 return -errno; 671 return -errno;
661 } 672 }
662 /* Skip to starting line number */ 673 /* Skip to starting line number */
@@ -689,11 +700,11 @@ end:
689 return ret; 700 return ret;
690} 701}
691 702
692int show_line_range(struct line_range *lr, const char *module) 703int show_line_range(struct line_range *lr, const char *module, bool user)
693{ 704{
694 int ret; 705 int ret;
695 706
696 ret = init_symbol_maps(false); 707 ret = init_symbol_maps(user);
697 if (ret < 0) 708 if (ret < 0)
698 return ret; 709 return ret;
699 ret = __show_line_range(lr, module); 710 ret = __show_line_range(lr, module);
@@ -768,13 +779,12 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
768 int i, ret = 0; 779 int i, ret = 0;
769 struct debuginfo *dinfo; 780 struct debuginfo *dinfo;
770 781
771 ret = init_symbol_maps(false); 782 ret = init_symbol_maps(pevs->uprobes);
772 if (ret < 0) 783 if (ret < 0)
773 return ret; 784 return ret;
774 785
775 dinfo = open_debuginfo(module); 786 dinfo = open_debuginfo(module, false);
776 if (!dinfo) { 787 if (!dinfo) {
777 pr_warning("Failed to open debuginfo file.\n");
778 ret = -ENOENT; 788 ret = -ENOENT;
779 goto out; 789 goto out;
780 } 790 }
@@ -815,7 +825,8 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
815} 825}
816 826
817int show_line_range(struct line_range *lr __maybe_unused, 827int show_line_range(struct line_range *lr __maybe_unused,
818 const char *module __maybe_unused) 828 const char *module __maybe_unused,
829 bool user __maybe_unused)
819{ 830{
820 pr_warning("Debuginfo-analysis is not supported.\n"); 831 pr_warning("Debuginfo-analysis is not supported.\n");
821 return -ENOSYS; 832 return -ENOSYS;
@@ -1405,8 +1416,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1405 1416
1406 return tmp - buf; 1417 return tmp - buf;
1407error: 1418error:
1408 pr_debug("Failed to synthesize perf probe argument: %s\n", 1419 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
1409 strerror(-ret));
1410 return ret; 1420 return ret;
1411} 1421}
1412 1422
@@ -1455,8 +1465,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1455 1465
1456 return buf; 1466 return buf;
1457error: 1467error:
1458 pr_debug("Failed to synthesize perf probe point: %s\n", 1468 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1459 strerror(-ret));
1460 free(buf); 1469 free(buf);
1461 return NULL; 1470 return NULL;
1462} 1471}
@@ -1780,10 +1789,11 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
1780 memset(tev, 0, sizeof(*tev)); 1789 memset(tev, 0, sizeof(*tev));
1781} 1790}
1782 1791
1783static void print_warn_msg(const char *file, bool is_kprobe) 1792static void print_open_warning(int err, bool is_kprobe)
1784{ 1793{
1794 char sbuf[STRERR_BUFSIZE];
1785 1795
1786 if (errno == ENOENT) { 1796 if (err == -ENOENT) {
1787 const char *config; 1797 const char *config;
1788 1798
1789 if (!is_kprobe) 1799 if (!is_kprobe)
@@ -1791,25 +1801,43 @@ static void print_warn_msg(const char *file, bool is_kprobe)
1791 else 1801 else
1792 config = "CONFIG_KPROBE_EVENTS"; 1802 config = "CONFIG_KPROBE_EVENTS";
1793 1803
1794 pr_warning("%s file does not exist - please rebuild kernel" 1804 pr_warning("%cprobe_events file does not exist"
1795 " with %s.\n", file, config); 1805 " - please rebuild kernel with %s.\n",
1796 } else 1806 is_kprobe ? 'k' : 'u', config);
1797 pr_warning("Failed to open %s file: %s\n", file, 1807 } else if (err == -ENOTSUP)
1798 strerror(errno)); 1808 pr_warning("Debugfs is not mounted.\n");
1809 else
1810 pr_warning("Failed to open %cprobe_events: %s\n",
1811 is_kprobe ? 'k' : 'u',
1812 strerror_r(-err, sbuf, sizeof(sbuf)));
1813}
1814
1815static void print_both_open_warning(int kerr, int uerr)
1816{
1817 /* Both kprobes and uprobes are disabled, warn it. */
1818 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
1819 pr_warning("Debugfs is not mounted.\n");
1820 else if (kerr == -ENOENT && uerr == -ENOENT)
1821 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1822 "or/and CONFIG_UPROBE_EVENTS.\n");
1823 else {
1824 char sbuf[STRERR_BUFSIZE];
1825 pr_warning("Failed to open kprobe events: %s.\n",
1826 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1827 pr_warning("Failed to open uprobe events: %s.\n",
1828 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1829 }
1799} 1830}
1800 1831
1801static int open_probe_events(const char *trace_file, bool readwrite, 1832static int open_probe_events(const char *trace_file, bool readwrite)
1802 bool is_kprobe)
1803{ 1833{
1804 char buf[PATH_MAX]; 1834 char buf[PATH_MAX];
1805 const char *__debugfs; 1835 const char *__debugfs;
1806 int ret; 1836 int ret;
1807 1837
1808 __debugfs = debugfs_find_mountpoint(); 1838 __debugfs = debugfs_find_mountpoint();
1809 if (__debugfs == NULL) { 1839 if (__debugfs == NULL)
1810 pr_warning("Debugfs is not mounted.\n"); 1840 return -ENOTSUP;
1811 return -ENOENT;
1812 }
1813 1841
1814 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file); 1842 ret = e_snprintf(buf, PATH_MAX, "%s/%s", __debugfs, trace_file);
1815 if (ret >= 0) { 1843 if (ret >= 0) {
@@ -1820,19 +1848,19 @@ static int open_probe_events(const char *trace_file, bool readwrite,
1820 ret = open(buf, O_RDONLY, 0); 1848 ret = open(buf, O_RDONLY, 0);
1821 1849
1822 if (ret < 0) 1850 if (ret < 0)
1823 print_warn_msg(buf, is_kprobe); 1851 ret = -errno;
1824 } 1852 }
1825 return ret; 1853 return ret;
1826} 1854}
1827 1855
1828static int open_kprobe_events(bool readwrite) 1856static int open_kprobe_events(bool readwrite)
1829{ 1857{
1830 return open_probe_events("tracing/kprobe_events", readwrite, true); 1858 return open_probe_events("tracing/kprobe_events", readwrite);
1831} 1859}
1832 1860
1833static int open_uprobe_events(bool readwrite) 1861static int open_uprobe_events(bool readwrite)
1834{ 1862{
1835 return open_probe_events("tracing/uprobe_events", readwrite, false); 1863 return open_probe_events("tracing/uprobe_events", readwrite);
1836} 1864}
1837 1865
1838/* Get raw string list of current kprobe_events or uprobe_events */ 1866/* Get raw string list of current kprobe_events or uprobe_events */
@@ -1857,7 +1885,7 @@ static struct strlist *get_probe_trace_command_rawlist(int fd)
1857 p[idx] = '\0'; 1885 p[idx] = '\0';
1858 ret = strlist__add(sl, buf); 1886 ret = strlist__add(sl, buf);
1859 if (ret < 0) { 1887 if (ret < 0) {
1860 pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1888 pr_debug("strlist__add failed (%d)\n", ret);
1861 strlist__delete(sl); 1889 strlist__delete(sl);
1862 return NULL; 1890 return NULL;
1863 } 1891 }
@@ -1884,21 +1912,21 @@ static int show_perf_probe_event(struct perf_probe_event *pev,
1884 if (ret < 0) 1912 if (ret < 0)
1885 return ret; 1913 return ret;
1886 1914
1887 printf(" %-20s (on %s", buf, place); 1915 pr_info(" %-20s (on %s", buf, place);
1888 if (module) 1916 if (module)
1889 printf(" in %s", module); 1917 pr_info(" in %s", module);
1890 1918
1891 if (pev->nargs > 0) { 1919 if (pev->nargs > 0) {
1892 printf(" with"); 1920 pr_info(" with");
1893 for (i = 0; i < pev->nargs; i++) { 1921 for (i = 0; i < pev->nargs; i++) {
1894 ret = synthesize_perf_probe_arg(&pev->args[i], 1922 ret = synthesize_perf_probe_arg(&pev->args[i],
1895 buf, 128); 1923 buf, 128);
1896 if (ret < 0) 1924 if (ret < 0)
1897 break; 1925 break;
1898 printf(" %s", buf); 1926 pr_info(" %s", buf);
1899 } 1927 }
1900 } 1928 }
1901 printf(")\n"); 1929 pr_info(")\n");
1902 free(place); 1930 free(place);
1903 return ret; 1931 return ret;
1904} 1932}
@@ -1916,7 +1944,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1916 1944
1917 rawlist = get_probe_trace_command_rawlist(fd); 1945 rawlist = get_probe_trace_command_rawlist(fd);
1918 if (!rawlist) 1946 if (!rawlist)
1919 return -ENOENT; 1947 return -ENOMEM;
1920 1948
1921 strlist__for_each(ent, rawlist) { 1949 strlist__for_each(ent, rawlist) {
1922 ret = parse_probe_trace_command(ent->s, &tev); 1950 ret = parse_probe_trace_command(ent->s, &tev);
@@ -1940,27 +1968,34 @@ static int __show_perf_probe_events(int fd, bool is_kprobe)
1940/* List up current perf-probe events */ 1968/* List up current perf-probe events */
1941int show_perf_probe_events(void) 1969int show_perf_probe_events(void)
1942{ 1970{
1943 int fd, ret; 1971 int kp_fd, up_fd, ret;
1944 1972
1945 setup_pager(); 1973 setup_pager();
1946 fd = open_kprobe_events(false);
1947
1948 if (fd < 0)
1949 return fd;
1950 1974
1951 ret = init_symbol_maps(false); 1975 ret = init_symbol_maps(false);
1952 if (ret < 0) 1976 if (ret < 0)
1953 return ret; 1977 return ret;
1954 1978
1955 ret = __show_perf_probe_events(fd, true); 1979 kp_fd = open_kprobe_events(false);
1956 close(fd); 1980 if (kp_fd >= 0) {
1981 ret = __show_perf_probe_events(kp_fd, true);
1982 close(kp_fd);
1983 if (ret < 0)
1984 goto out;
1985 }
1957 1986
1958 fd = open_uprobe_events(false); 1987 up_fd = open_uprobe_events(false);
1959 if (fd >= 0) { 1988 if (kp_fd < 0 && up_fd < 0) {
1960 ret = __show_perf_probe_events(fd, false); 1989 print_both_open_warning(kp_fd, up_fd);
1961 close(fd); 1990 ret = kp_fd;
1991 goto out;
1962 } 1992 }
1963 1993
1994 if (up_fd >= 0) {
1995 ret = __show_perf_probe_events(up_fd, false);
1996 close(up_fd);
1997 }
1998out:
1964 exit_symbol_maps(); 1999 exit_symbol_maps();
1965 return ret; 2000 return ret;
1966} 2001}
@@ -1976,6 +2011,8 @@ static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
1976 2011
1977 memset(&tev, 0, sizeof(tev)); 2012 memset(&tev, 0, sizeof(tev));
1978 rawlist = get_probe_trace_command_rawlist(fd); 2013 rawlist = get_probe_trace_command_rawlist(fd);
2014 if (!rawlist)
2015 return NULL;
1979 sl = strlist__new(true, NULL); 2016 sl = strlist__new(true, NULL);
1980 strlist__for_each(ent, rawlist) { 2017 strlist__for_each(ent, rawlist) {
1981 ret = parse_probe_trace_command(ent->s, &tev); 2018 ret = parse_probe_trace_command(ent->s, &tev);
@@ -2005,6 +2042,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2005{ 2042{
2006 int ret = 0; 2043 int ret = 0;
2007 char *buf = synthesize_probe_trace_command(tev); 2044 char *buf = synthesize_probe_trace_command(tev);
2045 char sbuf[STRERR_BUFSIZE];
2008 2046
2009 if (!buf) { 2047 if (!buf) {
2010 pr_debug("Failed to synthesize probe trace event.\n"); 2048 pr_debug("Failed to synthesize probe trace event.\n");
@@ -2016,7 +2054,7 @@ static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
2016 ret = write(fd, buf, strlen(buf)); 2054 ret = write(fd, buf, strlen(buf));
2017 if (ret <= 0) 2055 if (ret <= 0)
2018 pr_warning("Failed to write event: %s\n", 2056 pr_warning("Failed to write event: %s\n",
2019 strerror(errno)); 2057 strerror_r(errno, sbuf, sizeof(sbuf)));
2020 } 2058 }
2021 free(buf); 2059 free(buf);
2022 return ret; 2060 return ret;
@@ -2030,7 +2068,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2030 /* Try no suffix */ 2068 /* Try no suffix */
2031 ret = e_snprintf(buf, len, "%s", base); 2069 ret = e_snprintf(buf, len, "%s", base);
2032 if (ret < 0) { 2070 if (ret < 0) {
2033 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2071 pr_debug("snprintf() failed: %d\n", ret);
2034 return ret; 2072 return ret;
2035 } 2073 }
2036 if (!strlist__has_entry(namelist, buf)) 2074 if (!strlist__has_entry(namelist, buf))
@@ -2046,7 +2084,7 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
2046 for (i = 1; i < MAX_EVENT_INDEX; i++) { 2084 for (i = 1; i < MAX_EVENT_INDEX; i++) {
2047 ret = e_snprintf(buf, len, "%s_%d", base, i); 2085 ret = e_snprintf(buf, len, "%s_%d", base, i);
2048 if (ret < 0) { 2086 if (ret < 0) {
2049 pr_debug("snprintf() failed: %s\n", strerror(-ret)); 2087 pr_debug("snprintf() failed: %d\n", ret);
2050 return ret; 2088 return ret;
2051 } 2089 }
2052 if (!strlist__has_entry(namelist, buf)) 2090 if (!strlist__has_entry(namelist, buf))
@@ -2075,8 +2113,11 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2075 else 2113 else
2076 fd = open_kprobe_events(true); 2114 fd = open_kprobe_events(true);
2077 2115
2078 if (fd < 0) 2116 if (fd < 0) {
2117 print_open_warning(fd, !pev->uprobes);
2079 return fd; 2118 return fd;
2119 }
2120
2080 /* Get current event names */ 2121 /* Get current event names */
2081 namelist = get_probe_trace_event_names(fd, false); 2122 namelist = get_probe_trace_event_names(fd, false);
2082 if (!namelist) { 2123 if (!namelist) {
@@ -2085,7 +2126,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2085 } 2126 }
2086 2127
2087 ret = 0; 2128 ret = 0;
2088 printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":"); 2129 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
2089 for (i = 0; i < ntevs; i++) { 2130 for (i = 0; i < ntevs; i++) {
2090 tev = &tevs[i]; 2131 tev = &tevs[i];
2091 if (pev->event) 2132 if (pev->event)
@@ -2140,8 +2181,8 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2140 2181
2141 if (ret >= 0) { 2182 if (ret >= 0) {
2142 /* Show how to use the event. */ 2183 /* Show how to use the event. */
2143 printf("\nYou can now use it in all perf tools, such as:\n\n"); 2184 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2144 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2185 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
2145 tev->event); 2186 tev->event);
2146 } 2187 }
2147 2188
@@ -2405,10 +2446,11 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
2405 goto error; 2446 goto error;
2406 } 2447 }
2407 2448
2408 printf("Removed event: %s\n", ent->s); 2449 pr_info("Removed event: %s\n", ent->s);
2409 return 0; 2450 return 0;
2410error: 2451error:
2411 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 2452 pr_warning("Failed to delete event: %s\n",
2453 strerror_r(-ret, buf, sizeof(buf)));
2412 return ret; 2454 return ret;
2413} 2455}
2414 2456
@@ -2449,15 +2491,18 @@ int del_perf_probe_events(struct strlist *dellist)
2449 2491
2450 /* Get current event names */ 2492 /* Get current event names */
2451 kfd = open_kprobe_events(true); 2493 kfd = open_kprobe_events(true);
2452 if (kfd < 0) 2494 if (kfd >= 0)
2453 return kfd; 2495 namelist = get_probe_trace_event_names(kfd, true);
2454 2496
2455 namelist = get_probe_trace_event_names(kfd, true);
2456 ufd = open_uprobe_events(true); 2497 ufd = open_uprobe_events(true);
2457
2458 if (ufd >= 0) 2498 if (ufd >= 0)
2459 unamelist = get_probe_trace_event_names(ufd, true); 2499 unamelist = get_probe_trace_event_names(ufd, true);
2460 2500
2501 if (kfd < 0 && ufd < 0) {
2502 print_both_open_warning(kfd, ufd);
2503 goto error;
2504 }
2505
2461 if (namelist == NULL && unamelist == NULL) 2506 if (namelist == NULL && unamelist == NULL)
2462 goto error; 2507 goto error;
2463 2508
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 776c9347a3b6..e01e9943139f 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -128,7 +128,8 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
128 bool force_add); 128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module); 131extern int show_line_range(struct line_range *lr, const char *module,
132 bool user);
132extern int show_available_vars(struct perf_probe_event *pevs, int npevs, 133extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
133 int max_probe_points, const char *module, 134 int max_probe_points, const char *module,
134 struct strfilter *filter, bool externs); 135 struct strfilter *filter, bool externs);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index dca9145d704c..b5247d777f0e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -281,6 +281,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 281 struct probe_trace_arg_ref **ref_ptr = &tvar->ref;
282 Dwarf_Die type; 282 Dwarf_Die type;
283 char buf[16]; 283 char buf[16];
284 char sbuf[STRERR_BUFSIZE];
284 int bsize, boffs, total; 285 int bsize, boffs, total;
285 int ret; 286 int ret;
286 287
@@ -367,7 +368,7 @@ formatted:
367 if (ret >= 16) 368 if (ret >= 16)
368 ret = -E2BIG; 369 ret = -E2BIG;
369 pr_warning("Failed to convert variable type: %s\n", 370 pr_warning("Failed to convert variable type: %s\n",
370 strerror(-ret)); 371 strerror_r(-ret, sbuf, sizeof(sbuf)));
371 return ret; 372 return ret;
372 } 373 }
373 tvar->type = strdup(buf); 374 tvar->type = strdup(buf);
@@ -608,14 +609,18 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod,
608 return -EINVAL; 609 return -EINVAL;
609 } 610 }
610 611
611 /* Get an appropriate symbol from symtab */ 612 symbol = dwarf_diename(sp_die);
612 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
613 if (!symbol) { 613 if (!symbol) {
614 pr_warning("Failed to find symbol at 0x%lx\n", 614 /* Try to get the symbol name from symtab */
615 (unsigned long)paddr); 615 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL);
616 return -ENOENT; 616 if (!symbol) {
617 pr_warning("Failed to find symbol at 0x%lx\n",
618 (unsigned long)paddr);
619 return -ENOENT;
620 }
621 eaddr = sym.st_value;
617 } 622 }
618 tp->offset = (unsigned long)(paddr - sym.st_value); 623 tp->offset = (unsigned long)(paddr - eaddr);
619 tp->address = (unsigned long)paddr; 624 tp->address = (unsigned long)paddr;
620 tp->symbol = strdup(symbol); 625 tp->symbol = strdup(symbol);
621 if (!tp->symbol) 626 if (!tp->symbol)
@@ -779,10 +784,12 @@ static int find_lazy_match_lines(struct intlist *list,
779 size_t line_len; 784 size_t line_len;
780 ssize_t len; 785 ssize_t len;
781 int count = 0, linenum = 1; 786 int count = 0, linenum = 1;
787 char sbuf[STRERR_BUFSIZE];
782 788
783 fp = fopen(fname, "r"); 789 fp = fopen(fname, "r");
784 if (!fp) { 790 if (!fp) {
785 pr_warning("Failed to open %s: %s\n", fname, strerror(errno)); 791 pr_warning("Failed to open %s: %s\n", fname,
792 strerror_r(errno, sbuf, sizeof(sbuf)));
786 return -errno; 793 return -errno;
787 } 794 }
788 795
@@ -982,8 +989,24 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
982 int ret = 0; 989 int ret = 0;
983 990
984#if _ELFUTILS_PREREQ(0, 142) 991#if _ELFUTILS_PREREQ(0, 142)
992 Elf *elf;
993 GElf_Ehdr ehdr;
994 GElf_Shdr shdr;
995
985 /* Get the call frame information from this dwarf */ 996 /* Get the call frame information from this dwarf */
986 pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg)); 997 elf = dwarf_getelf(dbg->dbg);
998 if (elf == NULL)
999 return -EINVAL;
1000
1001 if (gelf_getehdr(elf, &ehdr) == NULL)
1002 return -EINVAL;
1003
1004 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1005 shdr.sh_type == SHT_PROGBITS) {
1006 pf->cfi = dwarf_getcfi_elf(elf);
1007 } else {
1008 pf->cfi = dwarf_getcfi(dbg->dbg);
1009 }
987#endif 1010#endif
988 1011
989 off = 0; 1012 off = 0;
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 12aa9b0d0ba1..3dda85ca50c1 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -736,7 +736,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
737 return NULL; 737 return NULL;
738 738
739 n = poll(evlist->pollfd, evlist->nr_fds, timeout); 739 n = perf_evlist__poll(evlist, timeout);
740 if (n < 0) { 740 if (n < 0) {
741 PyErr_SetFromErrno(PyExc_OSError); 741 PyErr_SetFromErrno(PyExc_OSError);
742 return NULL; 742 return NULL;
@@ -753,9 +753,9 @@ static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
753 PyObject *list = PyList_New(0); 753 PyObject *list = PyList_New(0);
754 int i; 754 int i;
755 755
756 for (i = 0; i < evlist->nr_fds; ++i) { 756 for (i = 0; i < evlist->pollfd.nr; ++i) {
757 PyObject *file; 757 PyObject *file;
758 FILE *fp = fdopen(evlist->pollfd[i].fd, "r"); 758 FILE *fp = fdopen(evlist->pollfd.entries[i].fd, "r");
759 759
760 if (fp == NULL) 760 if (fp == NULL)
761 goto free_list; 761 goto free_list;
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index fe8079edbdc1..8acd0df88b5c 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -14,6 +14,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
14 struct perf_evsel *evsel; 14 struct perf_evsel *evsel;
15 unsigned long flags = perf_event_open_cloexec_flag(); 15 unsigned long flags = perf_event_open_cloexec_flag();
16 int err = -EAGAIN, fd; 16 int err = -EAGAIN, fd;
17 static pid_t pid = -1;
17 18
18 evlist = perf_evlist__new(); 19 evlist = perf_evlist__new();
19 if (!evlist) 20 if (!evlist)
@@ -24,14 +25,22 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str)
24 25
25 evsel = perf_evlist__first(evlist); 26 evsel = perf_evlist__first(evlist);
26 27
27 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 28 while (1) {
28 if (fd < 0) 29 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
29 goto out_delete; 30 if (fd < 0) {
31 if (pid == -1 && errno == EACCES) {
32 pid = 0;
33 continue;
34 }
35 goto out_delete;
36 }
37 break;
38 }
30 close(fd); 39 close(fd);
31 40
32 fn(evsel); 41 fn(evsel);
33 42
34 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); 43 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1, flags);
35 if (fd < 0) { 44 if (fd < 0) {
36 if (errno == EINVAL) 45 if (errno == EINVAL)
37 err = -EINVAL; 46 err = -EINVAL;
@@ -47,7 +56,7 @@ out_delete:
47 56
48static bool perf_probe_api(setup_probe_fn_t fn) 57static bool perf_probe_api(setup_probe_fn_t fn)
49{ 58{
50 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; 59 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock:u", NULL};
51 struct cpu_map *cpus; 60 struct cpu_map *cpus;
52 int cpu, ret, i = 0; 61 int cpu, ret, i = 0;
53 62
@@ -106,7 +115,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
106 115
107 evlist__for_each(evlist, evsel) { 116 evlist__for_each(evlist, evsel) {
108 perf_evsel__config(evsel, opts); 117 perf_evsel__config(evsel, opts);
109 if (!evsel->idx && use_comm_exec) 118 if (evsel->tracking && use_comm_exec)
110 evsel->attr.comm_exec = 1; 119 evsel->attr.comm_exec = 1;
111 } 120 }
112 121
@@ -128,16 +137,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
128 137
129static int get_max_rate(unsigned int *rate) 138static int get_max_rate(unsigned int *rate)
130{ 139{
131 char path[PATH_MAX]; 140 return sysctl__read_int("kernel/perf_event_max_sample_rate", (int *)rate);
132 const char *procfs = procfs__mountpoint();
133
134 if (!procfs)
135 return -1;
136
137 snprintf(path, PATH_MAX,
138 "%s/sys/kernel/perf_event_max_sample_rate", procfs);
139
140 return filename__read_int(path, (int *) rate);
141} 141}
142 142
143static int record_opts__config_freq(struct record_opts *opts) 143static int record_opts__config_freq(struct record_opts *opts)
@@ -201,6 +201,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
201 struct perf_evsel *evsel; 201 struct perf_evsel *evsel;
202 int err, fd, cpu; 202 int err, fd, cpu;
203 bool ret = false; 203 bool ret = false;
204 pid_t pid = -1;
204 205
205 temp_evlist = perf_evlist__new(); 206 temp_evlist = perf_evlist__new();
206 if (!temp_evlist) 207 if (!temp_evlist)
@@ -221,12 +222,20 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
221 cpu = evlist->cpus->map[0]; 222 cpu = evlist->cpus->map[0];
222 } 223 }
223 224
224 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 225 while (1) {
225 perf_event_open_cloexec_flag()); 226 fd = sys_perf_event_open(&evsel->attr, pid, cpu, -1,
226 if (fd >= 0) { 227 perf_event_open_cloexec_flag());
227 close(fd); 228 if (fd < 0) {
228 ret = true; 229 if (pid == -1 && errno == EACCES) {
230 pid = 0;
231 continue;
232 }
233 goto out_delete;
234 }
235 break;
229 } 236 }
237 close(fd);
238 ret = true;
230 239
231out_delete: 240out_delete:
232 perf_evlist__delete(temp_evlist); 241 perf_evlist__delete(temp_evlist);
diff --git a/tools/perf/util/run-command.c b/tools/perf/util/run-command.c
index da8e9b285f51..34622b53e733 100644
--- a/tools/perf/util/run-command.c
+++ b/tools/perf/util/run-command.c
@@ -1,6 +1,7 @@
1#include "cache.h" 1#include "cache.h"
2#include "run-command.h" 2#include "run-command.h"
3#include "exec_cmd.h" 3#include "exec_cmd.h"
4#include "debug.h"
4 5
5static inline void close_pair(int fd[2]) 6static inline void close_pair(int fd[2])
6{ 7{
@@ -19,6 +20,7 @@ int start_command(struct child_process *cmd)
19{ 20{
20 int need_in, need_out, need_err; 21 int need_in, need_out, need_err;
21 int fdin[2], fdout[2], fderr[2]; 22 int fdin[2], fdout[2], fderr[2];
23 char sbuf[STRERR_BUFSIZE];
22 24
23 /* 25 /*
24 * In case of errors we must keep the promise to close FDs 26 * In case of errors we must keep the promise to close FDs
@@ -99,7 +101,7 @@ int start_command(struct child_process *cmd)
99 101
100 if (cmd->dir && chdir(cmd->dir)) 102 if (cmd->dir && chdir(cmd->dir))
101 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 103 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
102 cmd->dir, strerror(errno)); 104 cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
103 if (cmd->env) { 105 if (cmd->env) {
104 for (; *cmd->env; cmd->env++) { 106 for (; *cmd->env; cmd->env++) {
105 if (strchr(*cmd->env, '=')) 107 if (strchr(*cmd->env, '='))
@@ -153,6 +155,8 @@ int start_command(struct child_process *cmd)
153 155
154static int wait_or_whine(pid_t pid) 156static int wait_or_whine(pid_t pid)
155{ 157{
158 char sbuf[STRERR_BUFSIZE];
159
156 for (;;) { 160 for (;;) {
157 int status, code; 161 int status, code;
158 pid_t waiting = waitpid(pid, &status, 0); 162 pid_t waiting = waitpid(pid, &status, 0);
@@ -160,7 +164,8 @@ static int wait_or_whine(pid_t pid)
160 if (waiting < 0) { 164 if (waiting < 0) {
161 if (errno == EINTR) 165 if (errno == EINTR)
162 continue; 166 continue;
163 error("waitpid failed (%s)", strerror(errno)); 167 error("waitpid failed (%s)",
168 strerror_r(errno, sbuf, sizeof(sbuf)));
164 return -ERR_RUN_COMMAND_WAITPID; 169 return -ERR_RUN_COMMAND_WAITPID;
165 } 170 }
166 if (waiting != pid) 171 if (waiting != pid)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b2dba9c0a3a1..22ebc46226e7 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -24,6 +24,7 @@
24#include <string.h> 24#include <string.h>
25#include <ctype.h> 25#include <ctype.h>
26#include <errno.h> 26#include <errno.h>
27#include <linux/bitmap.h>
27 28
28#include "../util.h" 29#include "../util.h"
29#include <EXTERN.h> 30#include <EXTERN.h>
@@ -57,7 +58,7 @@ INTERP my_perl;
57#define FTRACE_MAX_EVENT \ 58#define FTRACE_MAX_EVENT \
58 ((1 << (sizeof(unsigned short) * 8)) - 1) 59 ((1 << (sizeof(unsigned short) * 8)) - 1)
59 60
60struct event_format *events[FTRACE_MAX_EVENT]; 61static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
61 62
62extern struct scripting_context *scripting_context; 63extern struct scripting_context *scripting_context;
63 64
@@ -238,35 +239,15 @@ static void define_event_symbols(struct event_format *event,
238 define_event_symbols(event, ev_name, args->next); 239 define_event_symbols(event, ev_name, args->next);
239} 240}
240 241
241static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
242{
243 static char ev_name[256];
244 struct event_format *event;
245 int type = evsel->attr.config;
246
247 if (events[type])
248 return events[type];
249
250 events[type] = event = evsel->tp_format;
251 if (!event)
252 return NULL;
253
254 sprintf(ev_name, "%s::%s", event->system, event->name);
255
256 define_event_symbols(event, ev_name, event->print_fmt.args);
257
258 return event;
259}
260
261static void perl_process_tracepoint(struct perf_sample *sample, 242static void perl_process_tracepoint(struct perf_sample *sample,
262 struct perf_evsel *evsel, 243 struct perf_evsel *evsel,
263 struct thread *thread) 244 struct thread *thread)
264{ 245{
246 struct event_format *event = evsel->tp_format;
265 struct format_field *field; 247 struct format_field *field;
266 static char handler[256]; 248 static char handler[256];
267 unsigned long long val; 249 unsigned long long val;
268 unsigned long s, ns; 250 unsigned long s, ns;
269 struct event_format *event;
270 int pid; 251 int pid;
271 int cpu = sample->cpu; 252 int cpu = sample->cpu;
272 void *data = sample->raw_data; 253 void *data = sample->raw_data;
@@ -278,7 +259,6 @@ static void perl_process_tracepoint(struct perf_sample *sample,
278 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 259 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
279 return; 260 return;
280 261
281 event = find_cache_event(evsel);
282 if (!event) 262 if (!event)
283 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config); 263 die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
284 264
@@ -286,6 +266,9 @@ static void perl_process_tracepoint(struct perf_sample *sample,
286 266
287 sprintf(handler, "%s::%s", event->system, event->name); 267 sprintf(handler, "%s::%s", event->system, event->name);
288 268
269 if (!test_and_set_bit(event->id, events_defined))
270 define_event_symbols(event, handler, event->print_fmt.args);
271
289 s = nsecs / NSECS_PER_SEC; 272 s = nsecs / NSECS_PER_SEC;
290 ns = nsecs - s * NSECS_PER_SEC; 273 ns = nsecs - s * NSECS_PER_SEC;
291 274
@@ -432,6 +415,11 @@ error:
432 return err; 415 return err;
433} 416}
434 417
418static int perl_flush_script(void)
419{
420 return 0;
421}
422
435/* 423/*
436 * Stop trace script 424 * Stop trace script
437 */ 425 */
@@ -633,6 +621,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
633struct scripting_ops perl_scripting_ops = { 621struct scripting_ops perl_scripting_ops = {
634 .name = "Perl", 622 .name = "Perl",
635 .start_script = perl_start_script, 623 .start_script = perl_start_script,
624 .flush_script = perl_flush_script,
636 .stop_script = perl_stop_script, 625 .stop_script = perl_stop_script,
637 .process_event = perl_process_event, 626 .process_event = perl_process_event,
638 .generate_script = perl_generate_script, 627 .generate_script = perl_generate_script,
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cbce2545da45..d808a328f4dc 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -24,14 +24,21 @@
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <stdbool.h>
27#include <errno.h> 28#include <errno.h>
29#include <linux/bitmap.h>
28 30
29#include "../../perf.h" 31#include "../../perf.h"
30#include "../debug.h" 32#include "../debug.h"
33#include "../callchain.h"
31#include "../evsel.h" 34#include "../evsel.h"
32#include "../util.h" 35#include "../util.h"
33#include "../event.h" 36#include "../event.h"
34#include "../thread.h" 37#include "../thread.h"
38#include "../comm.h"
39#include "../machine.h"
40#include "../db-export.h"
41#include "../thread-stack.h"
35#include "../trace-event.h" 42#include "../trace-event.h"
36#include "../machine.h" 43#include "../machine.h"
37 44
@@ -40,7 +47,7 @@ PyMODINIT_FUNC initperf_trace_context(void);
40#define FTRACE_MAX_EVENT \ 47#define FTRACE_MAX_EVENT \
41 ((1 << (sizeof(unsigned short) * 8)) - 1) 48 ((1 << (sizeof(unsigned short) * 8)) - 1)
42 49
43struct event_format *events[FTRACE_MAX_EVENT]; 50static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
44 51
45#define MAX_FIELDS 64 52#define MAX_FIELDS 64
46#define N_COMMON_FIELDS 7 53#define N_COMMON_FIELDS 7
@@ -52,6 +59,24 @@ static int zero_flag_atom;
52 59
53static PyObject *main_module, *main_dict; 60static PyObject *main_module, *main_dict;
54 61
62struct tables {
63 struct db_export dbe;
64 PyObject *evsel_handler;
65 PyObject *machine_handler;
66 PyObject *thread_handler;
67 PyObject *comm_handler;
68 PyObject *comm_thread_handler;
69 PyObject *dso_handler;
70 PyObject *symbol_handler;
71 PyObject *branch_type_handler;
72 PyObject *sample_handler;
73 PyObject *call_path_handler;
74 PyObject *call_return_handler;
75 bool db_export_mode;
76};
77
78static struct tables tables_global;
79
55static void handler_call_die(const char *handler_name) NORETURN; 80static void handler_call_die(const char *handler_name) NORETURN;
56static void handler_call_die(const char *handler_name) 81static void handler_call_die(const char *handler_name)
57{ 82{
@@ -73,6 +98,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj
73 Py_DECREF(val); 98 Py_DECREF(val);
74} 99}
75 100
101static PyObject *get_handler(const char *handler_name)
102{
103 PyObject *handler;
104
105 handler = PyDict_GetItemString(main_dict, handler_name);
106 if (handler && !PyCallable_Check(handler))
107 return NULL;
108 return handler;
109}
110
111static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
112{
113 PyObject *retval;
114
115 retval = PyObject_CallObject(handler, args);
116 if (retval == NULL)
117 handler_call_die(die_msg);
118 Py_DECREF(retval);
119}
120
121static void try_call_object(const char *handler_name, PyObject *args)
122{
123 PyObject *handler;
124
125 handler = get_handler(handler_name);
126 if (handler)
127 call_object(handler, args, handler_name);
128}
129
76static void define_value(enum print_arg_type field_type, 130static void define_value(enum print_arg_type field_type,
77 const char *ev_name, 131 const char *ev_name,
78 const char *field_name, 132 const char *field_name,
@@ -80,7 +134,7 @@ static void define_value(enum print_arg_type field_type,
80 const char *field_str) 134 const char *field_str)
81{ 135{
82 const char *handler_name = "define_flag_value"; 136 const char *handler_name = "define_flag_value";
83 PyObject *handler, *t, *retval; 137 PyObject *t;
84 unsigned long long value; 138 unsigned long long value;
85 unsigned n = 0; 139 unsigned n = 0;
86 140
@@ -98,13 +152,7 @@ static void define_value(enum print_arg_type field_type,
98 PyTuple_SetItem(t, n++, PyInt_FromLong(value)); 152 PyTuple_SetItem(t, n++, PyInt_FromLong(value));
99 PyTuple_SetItem(t, n++, PyString_FromString(field_str)); 153 PyTuple_SetItem(t, n++, PyString_FromString(field_str));
100 154
101 handler = PyDict_GetItemString(main_dict, handler_name); 155 try_call_object(handler_name, t);
102 if (handler && PyCallable_Check(handler)) {
103 retval = PyObject_CallObject(handler, t);
104 if (retval == NULL)
105 handler_call_die(handler_name);
106 Py_DECREF(retval);
107 }
108 156
109 Py_DECREF(t); 157 Py_DECREF(t);
110} 158}
@@ -127,7 +175,7 @@ static void define_field(enum print_arg_type field_type,
127 const char *delim) 175 const char *delim)
128{ 176{
129 const char *handler_name = "define_flag_field"; 177 const char *handler_name = "define_flag_field";
130 PyObject *handler, *t, *retval; 178 PyObject *t;
131 unsigned n = 0; 179 unsigned n = 0;
132 180
133 if (field_type == PRINT_SYMBOL) 181 if (field_type == PRINT_SYMBOL)
@@ -145,13 +193,7 @@ static void define_field(enum print_arg_type field_type,
145 if (field_type == PRINT_FLAGS) 193 if (field_type == PRINT_FLAGS)
146 PyTuple_SetItem(t, n++, PyString_FromString(delim)); 194 PyTuple_SetItem(t, n++, PyString_FromString(delim));
147 195
148 handler = PyDict_GetItemString(main_dict, handler_name); 196 try_call_object(handler_name, t);
149 if (handler && PyCallable_Check(handler)) {
150 retval = PyObject_CallObject(handler, t);
151 if (retval == NULL)
152 handler_call_die(handler_name);
153 Py_DECREF(retval);
154 }
155 197
156 Py_DECREF(t); 198 Py_DECREF(t);
157} 199}
@@ -214,31 +256,6 @@ static void define_event_symbols(struct event_format *event,
214 define_event_symbols(event, ev_name, args->next); 256 define_event_symbols(event, ev_name, args->next);
215} 257}
216 258
217static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
218{
219 static char ev_name[256];
220 struct event_format *event;
221 int type = evsel->attr.config;
222
223 /*
224 * XXX: Do we really need to cache this since now we have evsel->tp_format
225 * cached already? Need to re-read this "cache" routine that as well calls
226 * define_event_symbols() :-\
227 */
228 if (events[type])
229 return events[type];
230
231 events[type] = event = evsel->tp_format;
232 if (!event)
233 return NULL;
234
235 sprintf(ev_name, "%s__%s", event->system, event->name);
236
237 define_event_symbols(event, ev_name, event->print_fmt.args);
238
239 return event;
240}
241
242static PyObject *get_field_numeric_entry(struct event_format *event, 259static PyObject *get_field_numeric_entry(struct event_format *event,
243 struct format_field *field, void *data) 260 struct format_field *field, void *data)
244{ 261{
@@ -294,9 +311,9 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
294 if (!symbol_conf.use_callchain || !sample->callchain) 311 if (!symbol_conf.use_callchain || !sample->callchain)
295 goto exit; 312 goto exit;
296 313
297 if (machine__resolve_callchain(al->machine, evsel, al->thread, 314 if (thread__resolve_callchain(al->thread, evsel,
298 sample, NULL, NULL, 315 sample, NULL, NULL,
299 PERF_MAX_STACK_DEPTH) != 0) { 316 PERF_MAX_STACK_DEPTH) != 0) {
300 pr_err("Failed to resolve callchain. Skipping\n"); 317 pr_err("Failed to resolve callchain. Skipping\n");
301 goto exit; 318 goto exit;
302 } 319 }
@@ -362,12 +379,12 @@ static void python_process_tracepoint(struct perf_sample *sample,
362 struct thread *thread, 379 struct thread *thread,
363 struct addr_location *al) 380 struct addr_location *al)
364{ 381{
365 PyObject *handler, *retval, *context, *t, *obj, *callchain; 382 struct event_format *event = evsel->tp_format;
383 PyObject *handler, *context, *t, *obj, *callchain;
366 PyObject *dict = NULL; 384 PyObject *dict = NULL;
367 static char handler_name[256]; 385 static char handler_name[256];
368 struct format_field *field; 386 struct format_field *field;
369 unsigned long s, ns; 387 unsigned long s, ns;
370 struct event_format *event;
371 unsigned n = 0; 388 unsigned n = 0;
372 int pid; 389 int pid;
373 int cpu = sample->cpu; 390 int cpu = sample->cpu;
@@ -379,7 +396,6 @@ static void python_process_tracepoint(struct perf_sample *sample,
379 if (!t) 396 if (!t)
380 Py_FatalError("couldn't create Python tuple"); 397 Py_FatalError("couldn't create Python tuple");
381 398
382 event = find_cache_event(evsel);
383 if (!event) 399 if (!event)
384 die("ug! no event found for type %d", (int)evsel->attr.config); 400 die("ug! no event found for type %d", (int)evsel->attr.config);
385 401
@@ -387,9 +403,10 @@ static void python_process_tracepoint(struct perf_sample *sample,
387 403
388 sprintf(handler_name, "%s__%s", event->system, event->name); 404 sprintf(handler_name, "%s__%s", event->system, event->name);
389 405
390 handler = PyDict_GetItemString(main_dict, handler_name); 406 if (!test_and_set_bit(event->id, events_defined))
391 if (handler && !PyCallable_Check(handler)) 407 define_event_symbols(event, handler_name, event->print_fmt.args);
392 handler = NULL; 408
409 handler = get_handler(handler_name);
393 if (!handler) { 410 if (!handler) {
394 dict = PyDict_New(); 411 dict = PyDict_New();
395 if (!dict) 412 if (!dict)
@@ -450,31 +467,304 @@ static void python_process_tracepoint(struct perf_sample *sample,
450 Py_FatalError("error resizing Python tuple"); 467 Py_FatalError("error resizing Python tuple");
451 468
452 if (handler) { 469 if (handler) {
453 retval = PyObject_CallObject(handler, t); 470 call_object(handler, t, handler_name);
454 if (retval == NULL)
455 handler_call_die(handler_name);
456 Py_DECREF(retval);
457 } else { 471 } else {
458 handler = PyDict_GetItemString(main_dict, "trace_unhandled"); 472 try_call_object("trace_unhandled", t);
459 if (handler && PyCallable_Check(handler)) {
460
461 retval = PyObject_CallObject(handler, t);
462 if (retval == NULL)
463 handler_call_die("trace_unhandled");
464 Py_DECREF(retval);
465 }
466 Py_DECREF(dict); 473 Py_DECREF(dict);
467 } 474 }
468 475
469 Py_DECREF(t); 476 Py_DECREF(t);
470} 477}
471 478
479static PyObject *tuple_new(unsigned int sz)
480{
481 PyObject *t;
482
483 t = PyTuple_New(sz);
484 if (!t)
485 Py_FatalError("couldn't create Python tuple");
486 return t;
487}
488
489static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val)
490{
491#if BITS_PER_LONG == 64
492 return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
493#endif
494#if BITS_PER_LONG == 32
495 return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val));
496#endif
497}
498
499static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val)
500{
501 return PyTuple_SetItem(t, pos, PyInt_FromLong(val));
502}
503
504static int tuple_set_string(PyObject *t, unsigned int pos, const char *s)
505{
506 return PyTuple_SetItem(t, pos, PyString_FromString(s));
507}
508
509static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel)
510{
511 struct tables *tables = container_of(dbe, struct tables, dbe);
512 PyObject *t;
513
514 t = tuple_new(2);
515
516 tuple_set_u64(t, 0, evsel->db_id);
517 tuple_set_string(t, 1, perf_evsel__name(evsel));
518
519 call_object(tables->evsel_handler, t, "evsel_table");
520
521 Py_DECREF(t);
522
523 return 0;
524}
525
526static int python_export_machine(struct db_export *dbe,
527 struct machine *machine)
528{
529 struct tables *tables = container_of(dbe, struct tables, dbe);
530 PyObject *t;
531
532 t = tuple_new(3);
533
534 tuple_set_u64(t, 0, machine->db_id);
535 tuple_set_s32(t, 1, machine->pid);
536 tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : "");
537
538 call_object(tables->machine_handler, t, "machine_table");
539
540 Py_DECREF(t);
541
542 return 0;
543}
544
545static int python_export_thread(struct db_export *dbe, struct thread *thread,
546 u64 main_thread_db_id, struct machine *machine)
547{
548 struct tables *tables = container_of(dbe, struct tables, dbe);
549 PyObject *t;
550
551 t = tuple_new(5);
552
553 tuple_set_u64(t, 0, thread->db_id);
554 tuple_set_u64(t, 1, machine->db_id);
555 tuple_set_u64(t, 2, main_thread_db_id);
556 tuple_set_s32(t, 3, thread->pid_);
557 tuple_set_s32(t, 4, thread->tid);
558
559 call_object(tables->thread_handler, t, "thread_table");
560
561 Py_DECREF(t);
562
563 return 0;
564}
565
566static int python_export_comm(struct db_export *dbe, struct comm *comm)
567{
568 struct tables *tables = container_of(dbe, struct tables, dbe);
569 PyObject *t;
570
571 t = tuple_new(2);
572
573 tuple_set_u64(t, 0, comm->db_id);
574 tuple_set_string(t, 1, comm__str(comm));
575
576 call_object(tables->comm_handler, t, "comm_table");
577
578 Py_DECREF(t);
579
580 return 0;
581}
582
583static int python_export_comm_thread(struct db_export *dbe, u64 db_id,
584 struct comm *comm, struct thread *thread)
585{
586 struct tables *tables = container_of(dbe, struct tables, dbe);
587 PyObject *t;
588
589 t = tuple_new(3);
590
591 tuple_set_u64(t, 0, db_id);
592 tuple_set_u64(t, 1, comm->db_id);
593 tuple_set_u64(t, 2, thread->db_id);
594
595 call_object(tables->comm_thread_handler, t, "comm_thread_table");
596
597 Py_DECREF(t);
598
599 return 0;
600}
601
602static int python_export_dso(struct db_export *dbe, struct dso *dso,
603 struct machine *machine)
604{
605 struct tables *tables = container_of(dbe, struct tables, dbe);
606 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
607 PyObject *t;
608
609 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
610
611 t = tuple_new(5);
612
613 tuple_set_u64(t, 0, dso->db_id);
614 tuple_set_u64(t, 1, machine->db_id);
615 tuple_set_string(t, 2, dso->short_name);
616 tuple_set_string(t, 3, dso->long_name);
617 tuple_set_string(t, 4, sbuild_id);
618
619 call_object(tables->dso_handler, t, "dso_table");
620
621 Py_DECREF(t);
622
623 return 0;
624}
625
626static int python_export_symbol(struct db_export *dbe, struct symbol *sym,
627 struct dso *dso)
628{
629 struct tables *tables = container_of(dbe, struct tables, dbe);
630 u64 *sym_db_id = symbol__priv(sym);
631 PyObject *t;
632
633 t = tuple_new(6);
634
635 tuple_set_u64(t, 0, *sym_db_id);
636 tuple_set_u64(t, 1, dso->db_id);
637 tuple_set_u64(t, 2, sym->start);
638 tuple_set_u64(t, 3, sym->end);
639 tuple_set_s32(t, 4, sym->binding);
640 tuple_set_string(t, 5, sym->name);
641
642 call_object(tables->symbol_handler, t, "symbol_table");
643
644 Py_DECREF(t);
645
646 return 0;
647}
648
649static int python_export_branch_type(struct db_export *dbe, u32 branch_type,
650 const char *name)
651{
652 struct tables *tables = container_of(dbe, struct tables, dbe);
653 PyObject *t;
654
655 t = tuple_new(2);
656
657 tuple_set_s32(t, 0, branch_type);
658 tuple_set_string(t, 1, name);
659
660 call_object(tables->branch_type_handler, t, "branch_type_table");
661
662 Py_DECREF(t);
663
664 return 0;
665}
666
667static int python_export_sample(struct db_export *dbe,
668 struct export_sample *es)
669{
670 struct tables *tables = container_of(dbe, struct tables, dbe);
671 PyObject *t;
672
673 t = tuple_new(21);
674
675 tuple_set_u64(t, 0, es->db_id);
676 tuple_set_u64(t, 1, es->evsel->db_id);
677 tuple_set_u64(t, 2, es->al->machine->db_id);
678 tuple_set_u64(t, 3, es->thread->db_id);
679 tuple_set_u64(t, 4, es->comm_db_id);
680 tuple_set_u64(t, 5, es->dso_db_id);
681 tuple_set_u64(t, 6, es->sym_db_id);
682 tuple_set_u64(t, 7, es->offset);
683 tuple_set_u64(t, 8, es->sample->ip);
684 tuple_set_u64(t, 9, es->sample->time);
685 tuple_set_s32(t, 10, es->sample->cpu);
686 tuple_set_u64(t, 11, es->addr_dso_db_id);
687 tuple_set_u64(t, 12, es->addr_sym_db_id);
688 tuple_set_u64(t, 13, es->addr_offset);
689 tuple_set_u64(t, 14, es->sample->addr);
690 tuple_set_u64(t, 15, es->sample->period);
691 tuple_set_u64(t, 16, es->sample->weight);
692 tuple_set_u64(t, 17, es->sample->transaction);
693 tuple_set_u64(t, 18, es->sample->data_src);
694 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
695 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
696
697 call_object(tables->sample_handler, t, "sample_table");
698
699 Py_DECREF(t);
700
701 return 0;
702}
703
704static int python_export_call_path(struct db_export *dbe, struct call_path *cp)
705{
706 struct tables *tables = container_of(dbe, struct tables, dbe);
707 PyObject *t;
708 u64 parent_db_id, sym_db_id;
709
710 parent_db_id = cp->parent ? cp->parent->db_id : 0;
711 sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0;
712
713 t = tuple_new(4);
714
715 tuple_set_u64(t, 0, cp->db_id);
716 tuple_set_u64(t, 1, parent_db_id);
717 tuple_set_u64(t, 2, sym_db_id);
718 tuple_set_u64(t, 3, cp->ip);
719
720 call_object(tables->call_path_handler, t, "call_path_table");
721
722 Py_DECREF(t);
723
724 return 0;
725}
726
727static int python_export_call_return(struct db_export *dbe,
728 struct call_return *cr)
729{
730 struct tables *tables = container_of(dbe, struct tables, dbe);
731 u64 comm_db_id = cr->comm ? cr->comm->db_id : 0;
732 PyObject *t;
733
734 t = tuple_new(11);
735
736 tuple_set_u64(t, 0, cr->db_id);
737 tuple_set_u64(t, 1, cr->thread->db_id);
738 tuple_set_u64(t, 2, comm_db_id);
739 tuple_set_u64(t, 3, cr->cp->db_id);
740 tuple_set_u64(t, 4, cr->call_time);
741 tuple_set_u64(t, 5, cr->return_time);
742 tuple_set_u64(t, 6, cr->branch_count);
743 tuple_set_u64(t, 7, cr->call_ref);
744 tuple_set_u64(t, 8, cr->return_ref);
745 tuple_set_u64(t, 9, cr->cp->parent->db_id);
746 tuple_set_s32(t, 10, cr->flags);
747
748 call_object(tables->call_return_handler, t, "call_return_table");
749
750 Py_DECREF(t);
751
752 return 0;
753}
754
755static int python_process_call_return(struct call_return *cr, void *data)
756{
757 struct db_export *dbe = data;
758
759 return db_export__call_return(dbe, cr);
760}
761
472static void python_process_general_event(struct perf_sample *sample, 762static void python_process_general_event(struct perf_sample *sample,
473 struct perf_evsel *evsel, 763 struct perf_evsel *evsel,
474 struct thread *thread, 764 struct thread *thread,
475 struct addr_location *al) 765 struct addr_location *al)
476{ 766{
477 PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; 767 PyObject *handler, *t, *dict, *callchain, *dict_sample;
478 static char handler_name[64]; 768 static char handler_name[64];
479 unsigned n = 0; 769 unsigned n = 0;
480 770
@@ -496,8 +786,8 @@ static void python_process_general_event(struct perf_sample *sample,
496 786
497 snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); 787 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
498 788
499 handler = PyDict_GetItemString(main_dict, handler_name); 789 handler = get_handler(handler_name);
500 if (!handler || !PyCallable_Check(handler)) 790 if (!handler)
501 goto exit; 791 goto exit;
502 792
503 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); 793 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
@@ -539,63 +829,121 @@ static void python_process_general_event(struct perf_sample *sample,
539 if (_PyTuple_Resize(&t, n) == -1) 829 if (_PyTuple_Resize(&t, n) == -1)
540 Py_FatalError("error resizing Python tuple"); 830 Py_FatalError("error resizing Python tuple");
541 831
542 retval = PyObject_CallObject(handler, t); 832 call_object(handler, t, handler_name);
543 if (retval == NULL)
544 handler_call_die(handler_name);
545 Py_DECREF(retval);
546exit: 833exit:
547 Py_DECREF(dict); 834 Py_DECREF(dict);
548 Py_DECREF(t); 835 Py_DECREF(t);
549} 836}
550 837
551static void python_process_event(union perf_event *event __maybe_unused, 838static void python_process_event(union perf_event *event,
552 struct perf_sample *sample, 839 struct perf_sample *sample,
553 struct perf_evsel *evsel, 840 struct perf_evsel *evsel,
554 struct thread *thread, 841 struct thread *thread,
555 struct addr_location *al) 842 struct addr_location *al)
556{ 843{
844 struct tables *tables = &tables_global;
845
557 switch (evsel->attr.type) { 846 switch (evsel->attr.type) {
558 case PERF_TYPE_TRACEPOINT: 847 case PERF_TYPE_TRACEPOINT:
559 python_process_tracepoint(sample, evsel, thread, al); 848 python_process_tracepoint(sample, evsel, thread, al);
560 break; 849 break;
561 /* Reserve for future process_hw/sw/raw APIs */ 850 /* Reserve for future process_hw/sw/raw APIs */
562 default: 851 default:
563 python_process_general_event(sample, evsel, thread, al); 852 if (tables->db_export_mode)
853 db_export__sample(&tables->dbe, event, sample, evsel,
854 thread, al);
855 else
856 python_process_general_event(sample, evsel, thread, al);
564 } 857 }
565} 858}
566 859
567static int run_start_sub(void) 860static int run_start_sub(void)
568{ 861{
569 PyObject *handler, *retval;
570 int err = 0;
571
572 main_module = PyImport_AddModule("__main__"); 862 main_module = PyImport_AddModule("__main__");
573 if (main_module == NULL) 863 if (main_module == NULL)
574 return -1; 864 return -1;
575 Py_INCREF(main_module); 865 Py_INCREF(main_module);
576 866
577 main_dict = PyModule_GetDict(main_module); 867 main_dict = PyModule_GetDict(main_module);
578 if (main_dict == NULL) { 868 if (main_dict == NULL)
579 err = -1;
580 goto error; 869 goto error;
581 }
582 Py_INCREF(main_dict); 870 Py_INCREF(main_dict);
583 871
584 handler = PyDict_GetItemString(main_dict, "trace_begin"); 872 try_call_object("trace_begin", NULL);
585 if (handler == NULL || !PyCallable_Check(handler))
586 goto out;
587 873
588 retval = PyObject_CallObject(handler, NULL); 874 return 0;
589 if (retval == NULL)
590 handler_call_die("trace_begin");
591 875
592 Py_DECREF(retval);
593 return err;
594error: 876error:
595 Py_XDECREF(main_dict); 877 Py_XDECREF(main_dict);
596 Py_XDECREF(main_module); 878 Py_XDECREF(main_module);
597out: 879 return -1;
598 return err; 880}
881
882#define SET_TABLE_HANDLER_(name, handler_name, table_name) do { \
883 tables->handler_name = get_handler(#table_name); \
884 if (tables->handler_name) \
885 tables->dbe.export_ ## name = python_export_ ## name; \
886} while (0)
887
888#define SET_TABLE_HANDLER(name) \
889 SET_TABLE_HANDLER_(name, name ## _handler, name ## _table)
890
891static void set_table_handlers(struct tables *tables)
892{
893 const char *perf_db_export_mode = "perf_db_export_mode";
894 const char *perf_db_export_calls = "perf_db_export_calls";
895 PyObject *db_export_mode, *db_export_calls;
896 bool export_calls = false;
897 int ret;
898
899 memset(tables, 0, sizeof(struct tables));
900 if (db_export__init(&tables->dbe))
901 Py_FatalError("failed to initialize export");
902
903 db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode);
904 if (!db_export_mode)
905 return;
906
907 ret = PyObject_IsTrue(db_export_mode);
908 if (ret == -1)
909 handler_call_die(perf_db_export_mode);
910 if (!ret)
911 return;
912
913 tables->dbe.crp = NULL;
914 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
915 if (db_export_calls) {
916 ret = PyObject_IsTrue(db_export_calls);
917 if (ret == -1)
918 handler_call_die(perf_db_export_calls);
919 export_calls = !!ret;
920 }
921
922 if (export_calls) {
923 tables->dbe.crp =
924 call_return_processor__new(python_process_call_return,
925 &tables->dbe);
926 if (!tables->dbe.crp)
927 Py_FatalError("failed to create calls processor");
928 }
929
930 tables->db_export_mode = true;
931 /*
932 * Reserve per symbol space for symbol->db_id via symbol__priv()
933 */
934 symbol_conf.priv_size = sizeof(u64);
935
936 SET_TABLE_HANDLER(evsel);
937 SET_TABLE_HANDLER(machine);
938 SET_TABLE_HANDLER(thread);
939 SET_TABLE_HANDLER(comm);
940 SET_TABLE_HANDLER(comm_thread);
941 SET_TABLE_HANDLER(dso);
942 SET_TABLE_HANDLER(symbol);
943 SET_TABLE_HANDLER(branch_type);
944 SET_TABLE_HANDLER(sample);
945 SET_TABLE_HANDLER(call_path);
946 SET_TABLE_HANDLER(call_return);
599} 947}
600 948
601/* 949/*
@@ -603,6 +951,7 @@ out:
603 */ 951 */
604static int python_start_script(const char *script, int argc, const char **argv) 952static int python_start_script(const char *script, int argc, const char **argv)
605{ 953{
954 struct tables *tables = &tables_global;
606 const char **command_line; 955 const char **command_line;
607 char buf[PATH_MAX]; 956 char buf[PATH_MAX];
608 int i, err = 0; 957 int i, err = 0;
@@ -641,6 +990,14 @@ static int python_start_script(const char *script, int argc, const char **argv)
641 990
642 free(command_line); 991 free(command_line);
643 992
993 set_table_handlers(tables);
994
995 if (tables->db_export_mode) {
996 err = db_export__branch_types(&tables->dbe);
997 if (err)
998 goto error;
999 }
1000
644 return err; 1001 return err;
645error: 1002error:
646 Py_Finalize(); 1003 Py_Finalize();
@@ -649,28 +1006,29 @@ error:
649 return err; 1006 return err;
650} 1007}
651 1008
1009static int python_flush_script(void)
1010{
1011 struct tables *tables = &tables_global;
1012
1013 return db_export__flush(&tables->dbe);
1014}
1015
652/* 1016/*
653 * Stop trace script 1017 * Stop trace script
654 */ 1018 */
655static int python_stop_script(void) 1019static int python_stop_script(void)
656{ 1020{
657 PyObject *handler, *retval; 1021 struct tables *tables = &tables_global;
658 int err = 0;
659 1022
660 handler = PyDict_GetItemString(main_dict, "trace_end"); 1023 try_call_object("trace_end", NULL);
661 if (handler == NULL || !PyCallable_Check(handler)) 1024
662 goto out; 1025 db_export__exit(&tables->dbe);
663 1026
664 retval = PyObject_CallObject(handler, NULL);
665 if (retval == NULL)
666 handler_call_die("trace_end");
667 Py_DECREF(retval);
668out:
669 Py_XDECREF(main_dict); 1027 Py_XDECREF(main_dict);
670 Py_XDECREF(main_module); 1028 Py_XDECREF(main_module);
671 Py_Finalize(); 1029 Py_Finalize();
672 1030
673 return err; 1031 return 0;
674} 1032}
675 1033
676static int python_generate_script(struct pevent *pevent, const char *outfile) 1034static int python_generate_script(struct pevent *pevent, const char *outfile)
@@ -843,6 +1201,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
843struct scripting_ops python_scripting_ops = { 1201struct scripting_ops python_scripting_ops = {
844 .name = "Python", 1202 .name = "Python",
845 .start_script = python_start_script, 1203 .start_script = python_start_script,
1204 .flush_script = python_flush_script,
846 .stop_script = python_stop_script, 1205 .stop_script = python_stop_script,
847 .process_event = python_process_event, 1206 .process_event = python_process_event,
848 .generate_script = python_generate_script, 1207 .generate_script = python_generate_script,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 88dfef70c13d..5f0e05a76c05 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,6 +14,7 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "asm/bug.h"
17 18
18static int perf_session__open(struct perf_session *session) 19static int perf_session__open(struct perf_session *session)
19{ 20{
@@ -66,6 +67,25 @@ static void perf_session__destroy_kernel_maps(struct perf_session *session)
66 machines__destroy_kernel_maps(&session->machines); 67 machines__destroy_kernel_maps(&session->machines);
67} 68}
68 69
70static bool perf_session__has_comm_exec(struct perf_session *session)
71{
72 struct perf_evsel *evsel;
73
74 evlist__for_each(session->evlist, evsel) {
75 if (evsel->attr.comm_exec)
76 return true;
77 }
78
79 return false;
80}
81
82static void perf_session__set_comm_exec(struct perf_session *session)
83{
84 bool comm_exec = perf_session__has_comm_exec(session);
85
86 machines__set_comm_exec(&session->machines, comm_exec);
87}
88
69struct perf_session *perf_session__new(struct perf_data_file *file, 89struct perf_session *perf_session__new(struct perf_data_file *file,
70 bool repipe, struct perf_tool *tool) 90 bool repipe, struct perf_tool *tool)
71{ 91{
@@ -75,9 +95,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
75 goto out; 95 goto out;
76 96
77 session->repipe = repipe; 97 session->repipe = repipe;
78 INIT_LIST_HEAD(&session->ordered_samples.samples); 98 ordered_events__init(&session->ordered_events);
79 INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
80 INIT_LIST_HEAD(&session->ordered_samples.to_free);
81 machines__init(&session->machines); 99 machines__init(&session->machines);
82 100
83 if (file) { 101 if (file) {
@@ -91,6 +109,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
91 goto out_close; 109 goto out_close;
92 110
93 perf_session__set_id_hdr_size(session); 111 perf_session__set_id_hdr_size(session);
112 perf_session__set_comm_exec(session);
94 } 113 }
95 } 114 }
96 115
@@ -100,13 +119,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
100 * kernel MMAP event, in perf_event__process_mmap(). 119 * kernel MMAP event, in perf_event__process_mmap().
101 */ 120 */
102 if (perf_session__create_kernel_maps(session) < 0) 121 if (perf_session__create_kernel_maps(session) < 0)
103 goto out_delete; 122 pr_warning("Cannot read kernel map\n");
104 } 123 }
105 124
106 if (tool && tool->ordering_requires_timestamps && 125 if (tool && tool->ordering_requires_timestamps &&
107 tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) { 126 tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) {
108 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 127 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
109 tool->ordered_samples = false; 128 tool->ordered_events = false;
110 } 129 }
111 130
112 return session; 131 return session;
@@ -209,6 +228,15 @@ static int process_finished_round(struct perf_tool *tool,
209 union perf_event *event, 228 union perf_event *event,
210 struct perf_session *session); 229 struct perf_session *session);
211 230
231static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
232 union perf_event *event __maybe_unused,
233 struct perf_session *perf_session
234 __maybe_unused)
235{
236 dump_printf(": unhandled!\n");
237 return 0;
238}
239
212void perf_tool__fill_defaults(struct perf_tool *tool) 240void perf_tool__fill_defaults(struct perf_tool *tool)
213{ 241{
214 if (tool->sample == NULL) 242 if (tool->sample == NULL)
@@ -238,11 +266,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
238 if (tool->build_id == NULL) 266 if (tool->build_id == NULL)
239 tool->build_id = process_finished_round_stub; 267 tool->build_id = process_finished_round_stub;
240 if (tool->finished_round == NULL) { 268 if (tool->finished_round == NULL) {
241 if (tool->ordered_samples) 269 if (tool->ordered_events)
242 tool->finished_round = process_finished_round; 270 tool->finished_round = process_finished_round;
243 else 271 else
244 tool->finished_round = process_finished_round_stub; 272 tool->finished_round = process_finished_round_stub;
245 } 273 }
274 if (tool->id_index == NULL)
275 tool->id_index = process_id_index_stub;
246} 276}
247 277
248static void swap_sample_id_all(union perf_event *event, void *data) 278static void swap_sample_id_all(union perf_event *event, void *data)
@@ -441,90 +471,10 @@ static perf_event__swap_op perf_event__swap_ops[] = {
441 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, 471 [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap,
442 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, 472 [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
443 [PERF_RECORD_HEADER_BUILD_ID] = NULL, 473 [PERF_RECORD_HEADER_BUILD_ID] = NULL,
474 [PERF_RECORD_ID_INDEX] = perf_event__all64_swap,
444 [PERF_RECORD_HEADER_MAX] = NULL, 475 [PERF_RECORD_HEADER_MAX] = NULL,
445}; 476};
446 477
447struct sample_queue {
448 u64 timestamp;
449 u64 file_offset;
450 union perf_event *event;
451 struct list_head list;
452};
453
454static void perf_session_free_sample_buffers(struct perf_session *session)
455{
456 struct ordered_samples *os = &session->ordered_samples;
457
458 while (!list_empty(&os->to_free)) {
459 struct sample_queue *sq;
460
461 sq = list_entry(os->to_free.next, struct sample_queue, list);
462 list_del(&sq->list);
463 free(sq);
464 }
465}
466
467static int perf_session_deliver_event(struct perf_session *session,
468 union perf_event *event,
469 struct perf_sample *sample,
470 struct perf_tool *tool,
471 u64 file_offset);
472
473static int flush_sample_queue(struct perf_session *s,
474 struct perf_tool *tool)
475{
476 struct ordered_samples *os = &s->ordered_samples;
477 struct list_head *head = &os->samples;
478 struct sample_queue *tmp, *iter;
479 struct perf_sample sample;
480 u64 limit = os->next_flush;
481 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
482 bool show_progress = limit == ULLONG_MAX;
483 struct ui_progress prog;
484 int ret;
485
486 if (!tool->ordered_samples || !limit)
487 return 0;
488
489 if (show_progress)
490 ui_progress__init(&prog, os->nr_samples, "Processing time ordered events...");
491
492 list_for_each_entry_safe(iter, tmp, head, list) {
493 if (session_done())
494 return 0;
495
496 if (iter->timestamp > limit)
497 break;
498
499 ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample);
500 if (ret)
501 pr_err("Can't parse sample, err = %d\n", ret);
502 else {
503 ret = perf_session_deliver_event(s, iter->event, &sample, tool,
504 iter->file_offset);
505 if (ret)
506 return ret;
507 }
508
509 os->last_flush = iter->timestamp;
510 list_del(&iter->list);
511 list_add(&iter->list, &os->sample_cache);
512 os->nr_samples--;
513
514 if (show_progress)
515 ui_progress__update(&prog, 1);
516 }
517
518 if (list_empty(head)) {
519 os->last_sample = NULL;
520 } else if (last_ts <= limit) {
521 os->last_sample =
522 list_entry(head->prev, struct sample_queue, list);
523 }
524
525 return 0;
526}
527
528/* 478/*
529 * When perf record finishes a pass on every buffers, it records this pseudo 479 * When perf record finishes a pass on every buffers, it records this pseudo
530 * event. 480 * event.
@@ -568,99 +518,38 @@ static int process_finished_round(struct perf_tool *tool,
568 union perf_event *event __maybe_unused, 518 union perf_event *event __maybe_unused,
569 struct perf_session *session) 519 struct perf_session *session)
570{ 520{
571 int ret = flush_sample_queue(session, tool); 521 return ordered_events__flush(session, tool, OE_FLUSH__ROUND);
572 if (!ret)
573 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
574
575 return ret;
576}
577
578/* The queue is ordered by time */
579static void __queue_event(struct sample_queue *new, struct perf_session *s)
580{
581 struct ordered_samples *os = &s->ordered_samples;
582 struct sample_queue *sample = os->last_sample;
583 u64 timestamp = new->timestamp;
584 struct list_head *p;
585
586 ++os->nr_samples;
587 os->last_sample = new;
588
589 if (!sample) {
590 list_add(&new->list, &os->samples);
591 os->max_timestamp = timestamp;
592 return;
593 }
594
595 /*
596 * last_sample might point to some random place in the list as it's
597 * the last queued event. We expect that the new event is close to
598 * this.
599 */
600 if (sample->timestamp <= timestamp) {
601 while (sample->timestamp <= timestamp) {
602 p = sample->list.next;
603 if (p == &os->samples) {
604 list_add_tail(&new->list, &os->samples);
605 os->max_timestamp = timestamp;
606 return;
607 }
608 sample = list_entry(p, struct sample_queue, list);
609 }
610 list_add_tail(&new->list, &sample->list);
611 } else {
612 while (sample->timestamp > timestamp) {
613 p = sample->list.prev;
614 if (p == &os->samples) {
615 list_add(&new->list, &os->samples);
616 return;
617 }
618 sample = list_entry(p, struct sample_queue, list);
619 }
620 list_add(&new->list, &sample->list);
621 }
622} 522}
623 523
624#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
625
626int perf_session_queue_event(struct perf_session *s, union perf_event *event, 524int perf_session_queue_event(struct perf_session *s, union perf_event *event,
627 struct perf_sample *sample, u64 file_offset) 525 struct perf_tool *tool, struct perf_sample *sample,
526 u64 file_offset)
628{ 527{
629 struct ordered_samples *os = &s->ordered_samples; 528 struct ordered_events *oe = &s->ordered_events;
630 struct list_head *sc = &os->sample_cache;
631 u64 timestamp = sample->time; 529 u64 timestamp = sample->time;
632 struct sample_queue *new; 530 struct ordered_event *new;
633 531
634 if (!timestamp || timestamp == ~0ULL) 532 if (!timestamp || timestamp == ~0ULL)
635 return -ETIME; 533 return -ETIME;
636 534
637 if (timestamp < s->ordered_samples.last_flush) { 535 if (timestamp < oe->last_flush) {
638 printf("Warning: Timestamp below last timeslice flush\n"); 536 pr_oe_time(timestamp, "out of order event\n");
639 return -EINVAL; 537 pr_oe_time(oe->last_flush, "last flush, last_flush_type %d\n",
640 } 538 oe->last_flush_type);
641 539
642 if (!list_empty(sc)) { 540 s->stats.nr_unordered_events++;
643 new = list_entry(sc->next, struct sample_queue, list);
644 list_del(&new->list);
645 } else if (os->sample_buffer) {
646 new = os->sample_buffer + os->sample_buffer_idx;
647 if (++os->sample_buffer_idx == MAX_SAMPLE_BUFFER)
648 os->sample_buffer = NULL;
649 } else {
650 os->sample_buffer = malloc(MAX_SAMPLE_BUFFER * sizeof(*new));
651 if (!os->sample_buffer)
652 return -ENOMEM;
653 list_add(&os->sample_buffer->list, &os->to_free);
654 os->sample_buffer_idx = 2;
655 new = os->sample_buffer + 1;
656 } 541 }
657 542
658 new->timestamp = timestamp; 543 new = ordered_events__new(oe, timestamp, event);
659 new->file_offset = file_offset; 544 if (!new) {
660 new->event = event; 545 ordered_events__flush(s, tool, OE_FLUSH__HALF);
546 new = ordered_events__new(oe, timestamp, event);
547 }
661 548
662 __queue_event(new, s); 549 if (!new)
550 return -ENOMEM;
663 551
552 new->file_offset = file_offset;
664 return 0; 553 return 0;
665} 554}
666 555
@@ -699,15 +588,46 @@ static void regs_dump__printf(u64 mask, u64 *regs)
699 } 588 }
700} 589}
701 590
591static const char *regs_abi[] = {
592 [PERF_SAMPLE_REGS_ABI_NONE] = "none",
593 [PERF_SAMPLE_REGS_ABI_32] = "32-bit",
594 [PERF_SAMPLE_REGS_ABI_64] = "64-bit",
595};
596
597static inline const char *regs_dump_abi(struct regs_dump *d)
598{
599 if (d->abi > PERF_SAMPLE_REGS_ABI_64)
600 return "unknown";
601
602 return regs_abi[d->abi];
603}
604
605static void regs__printf(const char *type, struct regs_dump *regs)
606{
607 u64 mask = regs->mask;
608
609 printf("... %s regs: mask 0x%" PRIx64 " ABI %s\n",
610 type,
611 mask,
612 regs_dump_abi(regs));
613
614 regs_dump__printf(mask, regs->regs);
615}
616
702static void regs_user__printf(struct perf_sample *sample) 617static void regs_user__printf(struct perf_sample *sample)
703{ 618{
704 struct regs_dump *user_regs = &sample->user_regs; 619 struct regs_dump *user_regs = &sample->user_regs;
705 620
706 if (user_regs->regs) { 621 if (user_regs->regs)
707 u64 mask = user_regs->mask; 622 regs__printf("user", user_regs);
708 printf("... user regs: mask 0x%" PRIx64 "\n", mask); 623}
709 regs_dump__printf(mask, user_regs->regs); 624
710 } 625static void regs_intr__printf(struct perf_sample *sample)
626{
627 struct regs_dump *intr_regs = &sample->intr_regs;
628
629 if (intr_regs->regs)
630 regs__printf("intr", intr_regs);
711} 631}
712 632
713static void stack_user__printf(struct stack_dump *dump) 633static void stack_user__printf(struct stack_dump *dump)
@@ -806,6 +726,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
806 if (sample_type & PERF_SAMPLE_REGS_USER) 726 if (sample_type & PERF_SAMPLE_REGS_USER)
807 regs_user__printf(sample); 727 regs_user__printf(sample);
808 728
729 if (sample_type & PERF_SAMPLE_REGS_INTR)
730 regs_intr__printf(sample);
731
809 if (sample_type & PERF_SAMPLE_STACK_USER) 732 if (sample_type & PERF_SAMPLE_STACK_USER)
810 stack_user__printf(&sample->user_stack); 733 stack_user__printf(&sample->user_stack);
811 734
@@ -920,11 +843,10 @@ perf_session__deliver_sample(struct perf_session *session,
920 &sample->read.one, machine); 843 &sample->read.one, machine);
921} 844}
922 845
923static int perf_session_deliver_event(struct perf_session *session, 846int perf_session__deliver_event(struct perf_session *session,
924 union perf_event *event, 847 union perf_event *event,
925 struct perf_sample *sample, 848 struct perf_sample *sample,
926 struct perf_tool *tool, 849 struct perf_tool *tool, u64 file_offset)
927 u64 file_offset)
928{ 850{
929 struct perf_evsel *evsel; 851 struct perf_evsel *evsel;
930 struct machine *machine; 852 struct machine *machine;
@@ -932,22 +854,6 @@ static int perf_session_deliver_event(struct perf_session *session,
932 dump_event(session, event, file_offset, sample); 854 dump_event(session, event, file_offset, sample);
933 855
934 evsel = perf_evlist__id2evsel(session->evlist, sample->id); 856 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
935 if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
936 /*
937 * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
938 * because the tools right now may apply filters, discarding
939 * some of the samples. For consistency, in the future we
940 * should have something like nr_filtered_samples and remove
941 * the sample->period from total_sample_period, etc, KISS for
942 * now tho.
943 *
944 * Also testing against NULL allows us to handle files without
945 * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
946 * future probably it'll be a good idea to restrict event
947 * processing via perf_session to files with both set.
948 */
949 hists__inc_nr_events(&evsel->hists, event->header.type);
950 }
951 857
952 machine = perf_session__find_machine_for_cpumode(session, event, 858 machine = perf_session__find_machine_for_cpumode(session, event,
953 sample); 859 sample);
@@ -1005,8 +911,10 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1005 switch (event->header.type) { 911 switch (event->header.type) {
1006 case PERF_RECORD_HEADER_ATTR: 912 case PERF_RECORD_HEADER_ATTR:
1007 err = tool->attr(tool, event, &session->evlist); 913 err = tool->attr(tool, event, &session->evlist);
1008 if (err == 0) 914 if (err == 0) {
1009 perf_session__set_id_hdr_size(session); 915 perf_session__set_id_hdr_size(session);
916 perf_session__set_comm_exec(session);
917 }
1010 return err; 918 return err;
1011 case PERF_RECORD_HEADER_EVENT_TYPE: 919 case PERF_RECORD_HEADER_EVENT_TYPE:
1012 /* 920 /*
@@ -1022,11 +930,26 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1022 return tool->build_id(tool, event, session); 930 return tool->build_id(tool, event, session);
1023 case PERF_RECORD_FINISHED_ROUND: 931 case PERF_RECORD_FINISHED_ROUND:
1024 return tool->finished_round(tool, event, session); 932 return tool->finished_round(tool, event, session);
933 case PERF_RECORD_ID_INDEX:
934 return tool->id_index(tool, event, session);
1025 default: 935 default:
1026 return -EINVAL; 936 return -EINVAL;
1027 } 937 }
1028} 938}
1029 939
940int perf_session__deliver_synth_event(struct perf_session *session,
941 union perf_event *event,
942 struct perf_sample *sample,
943 struct perf_tool *tool)
944{
945 events_stats__inc(&session->stats, event->header.type);
946
947 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
948 return perf_session__process_user_event(session, event, tool, 0);
949
950 return perf_session__deliver_event(session, event, sample, tool, 0);
951}
952
1030static void event_swap(union perf_event *event, bool sample_id_all) 953static void event_swap(union perf_event *event, bool sample_id_all)
1031{ 954{
1032 perf_event__swap_op swap; 955 perf_event__swap_op swap;
@@ -1036,6 +959,61 @@ static void event_swap(union perf_event *event, bool sample_id_all)
1036 swap(event, sample_id_all); 959 swap(event, sample_id_all);
1037} 960}
1038 961
962int perf_session__peek_event(struct perf_session *session, off_t file_offset,
963 void *buf, size_t buf_sz,
964 union perf_event **event_ptr,
965 struct perf_sample *sample)
966{
967 union perf_event *event;
968 size_t hdr_sz, rest;
969 int fd;
970
971 if (session->one_mmap && !session->header.needs_swap) {
972 event = file_offset - session->one_mmap_offset +
973 session->one_mmap_addr;
974 goto out_parse_sample;
975 }
976
977 if (perf_data_file__is_pipe(session->file))
978 return -1;
979
980 fd = perf_data_file__fd(session->file);
981 hdr_sz = sizeof(struct perf_event_header);
982
983 if (buf_sz < hdr_sz)
984 return -1;
985
986 if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 ||
987 readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz)
988 return -1;
989
990 event = (union perf_event *)buf;
991
992 if (session->header.needs_swap)
993 perf_event_header__bswap(&event->header);
994
995 if (event->header.size < hdr_sz)
996 return -1;
997
998 rest = event->header.size - hdr_sz;
999
1000 if (readn(fd, &buf, rest) != (ssize_t)rest)
1001 return -1;
1002
1003 if (session->header.needs_swap)
1004 event_swap(event, perf_evlist__sample_id_all(session->evlist));
1005
1006out_parse_sample:
1007
1008 if (sample && event->header.type < PERF_RECORD_USER_TYPE_START &&
1009 perf_evlist__parse_sample(session->evlist, event, sample))
1010 return -1;
1011
1012 *event_ptr = event;
1013
1014 return 0;
1015}
1016
1039static s64 perf_session__process_event(struct perf_session *session, 1017static s64 perf_session__process_event(struct perf_session *session,
1040 union perf_event *event, 1018 union perf_event *event,
1041 struct perf_tool *tool, 1019 struct perf_tool *tool,
@@ -1062,15 +1040,15 @@ static s64 perf_session__process_event(struct perf_session *session,
1062 if (ret) 1040 if (ret)
1063 return ret; 1041 return ret;
1064 1042
1065 if (tool->ordered_samples) { 1043 if (tool->ordered_events) {
1066 ret = perf_session_queue_event(session, event, &sample, 1044 ret = perf_session_queue_event(session, event, tool, &sample,
1067 file_offset); 1045 file_offset);
1068 if (ret != -ETIME) 1046 if (ret != -ETIME)
1069 return ret; 1047 return ret;
1070 } 1048 }
1071 1049
1072 return perf_session_deliver_event(session, event, &sample, tool, 1050 return perf_session__deliver_event(session, event, &sample, tool,
1073 file_offset); 1051 file_offset);
1074} 1052}
1075 1053
1076void perf_event_header__bswap(struct perf_event_header *hdr) 1054void perf_event_header__bswap(struct perf_event_header *hdr)
@@ -1136,6 +1114,9 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
1136 "Do you have a KVM guest running and not using 'perf kvm'?\n", 1114 "Do you have a KVM guest running and not using 'perf kvm'?\n",
1137 session->stats.nr_unprocessable_samples); 1115 session->stats.nr_unprocessable_samples);
1138 } 1116 }
1117
1118 if (session->stats.nr_unordered_events != 0)
1119 ui__warning("%u out of order events recorded.\n", session->stats.nr_unordered_events);
1139} 1120}
1140 1121
1141volatile int session_done; 1122volatile int session_done;
@@ -1222,12 +1203,11 @@ more:
1222 goto more; 1203 goto more;
1223done: 1204done:
1224 /* do the final flush for ordered samples */ 1205 /* do the final flush for ordered samples */
1225 session->ordered_samples.next_flush = ULLONG_MAX; 1206 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1226 err = flush_sample_queue(session, tool);
1227out_err: 1207out_err:
1228 free(buf); 1208 free(buf);
1229 perf_session__warn_about_errors(session, tool); 1209 perf_session__warn_about_errors(session, tool);
1230 perf_session_free_sample_buffers(session); 1210 ordered_events__free(&session->ordered_events);
1231 return err; 1211 return err;
1232} 1212}
1233 1213
@@ -1368,12 +1348,11 @@ more:
1368 1348
1369out: 1349out:
1370 /* do the final flush for ordered samples */ 1350 /* do the final flush for ordered samples */
1371 session->ordered_samples.next_flush = ULLONG_MAX; 1351 err = ordered_events__flush(session, tool, OE_FLUSH__FINAL);
1372 err = flush_sample_queue(session, tool);
1373out_err: 1352out_err:
1374 ui_progress__finish(); 1353 ui_progress__finish();
1375 perf_session__warn_about_errors(session, tool); 1354 perf_session__warn_about_errors(session, tool);
1376 perf_session_free_sample_buffers(session); 1355 ordered_events__free(&session->ordered_events);
1377 session->one_mmap = false; 1356 session->one_mmap = false;
1378 return err; 1357 return err;
1379} 1358}
@@ -1455,16 +1434,9 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp
1455 1434
1456size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1435size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1457{ 1436{
1458 struct perf_evsel *pos;
1459 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1437 size_t ret = fprintf(fp, "Aggregated stats:\n");
1460 1438
1461 ret += events_stats__fprintf(&session->stats, fp); 1439 ret += events_stats__fprintf(&session->stats, fp);
1462
1463 evlist__for_each(session->evlist, pos) {
1464 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1465 ret += events_stats__fprintf(&pos->hists.stats, fp);
1466 }
1467
1468 return ret; 1440 return ret;
1469} 1441}
1470 1442
@@ -1505,9 +1477,9 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1505 if (symbol_conf.use_callchain && sample->callchain) { 1477 if (symbol_conf.use_callchain && sample->callchain) {
1506 struct addr_location node_al; 1478 struct addr_location node_al;
1507 1479
1508 if (machine__resolve_callchain(al->machine, evsel, al->thread, 1480 if (thread__resolve_callchain(al->thread, evsel,
1509 sample, NULL, NULL, 1481 sample, NULL, NULL,
1510 PERF_MAX_STACK_DEPTH) != 0) { 1482 PERF_MAX_STACK_DEPTH) != 0) {
1511 if (verbose) 1483 if (verbose)
1512 error("Failed to resolve callchain. Skipping\n"); 1484 error("Failed to resolve callchain. Skipping\n");
1513 return; 1485 return;
@@ -1682,3 +1654,111 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
1682out: 1654out:
1683 return err; 1655 return err;
1684} 1656}
1657
1658int perf_event__process_id_index(struct perf_tool *tool __maybe_unused,
1659 union perf_event *event,
1660 struct perf_session *session)
1661{
1662 struct perf_evlist *evlist = session->evlist;
1663 struct id_index_event *ie = &event->id_index;
1664 size_t i, nr, max_nr;
1665
1666 max_nr = (ie->header.size - sizeof(struct id_index_event)) /
1667 sizeof(struct id_index_entry);
1668 nr = ie->nr;
1669 if (nr > max_nr)
1670 return -EINVAL;
1671
1672 if (dump_trace)
1673 fprintf(stdout, " nr: %zu\n", nr);
1674
1675 for (i = 0; i < nr; i++) {
1676 struct id_index_entry *e = &ie->entries[i];
1677 struct perf_sample_id *sid;
1678
1679 if (dump_trace) {
1680 fprintf(stdout, " ... id: %"PRIu64, e->id);
1681 fprintf(stdout, " idx: %"PRIu64, e->idx);
1682 fprintf(stdout, " cpu: %"PRId64, e->cpu);
1683 fprintf(stdout, " tid: %"PRId64"\n", e->tid);
1684 }
1685
1686 sid = perf_evlist__id2sid(evlist, e->id);
1687 if (!sid)
1688 return -ENOENT;
1689 sid->idx = e->idx;
1690 sid->cpu = e->cpu;
1691 sid->tid = e->tid;
1692 }
1693 return 0;
1694}
1695
1696int perf_event__synthesize_id_index(struct perf_tool *tool,
1697 perf_event__handler_t process,
1698 struct perf_evlist *evlist,
1699 struct machine *machine)
1700{
1701 union perf_event *ev;
1702 struct perf_evsel *evsel;
1703 size_t nr = 0, i = 0, sz, max_nr, n;
1704 int err;
1705
1706 pr_debug2("Synthesizing id index\n");
1707
1708 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
1709 sizeof(struct id_index_entry);
1710
1711 evlist__for_each(evlist, evsel)
1712 nr += evsel->ids;
1713
1714 n = nr > max_nr ? max_nr : nr;
1715 sz = sizeof(struct id_index_event) + n * sizeof(struct id_index_entry);
1716 ev = zalloc(sz);
1717 if (!ev)
1718 return -ENOMEM;
1719
1720 ev->id_index.header.type = PERF_RECORD_ID_INDEX;
1721 ev->id_index.header.size = sz;
1722 ev->id_index.nr = n;
1723
1724 evlist__for_each(evlist, evsel) {
1725 u32 j;
1726
1727 for (j = 0; j < evsel->ids; j++) {
1728 struct id_index_entry *e;
1729 struct perf_sample_id *sid;
1730
1731 if (i >= n) {
1732 err = process(tool, ev, NULL, machine);
1733 if (err)
1734 goto out_err;
1735 nr -= n;
1736 i = 0;
1737 }
1738
1739 e = &ev->id_index.entries[i++];
1740
1741 e->id = evsel->id[j];
1742
1743 sid = perf_evlist__id2sid(evlist, e->id);
1744 if (!sid) {
1745 free(ev);
1746 return -ENOENT;
1747 }
1748
1749 e->idx = sid->idx;
1750 e->cpu = sid->cpu;
1751 e->tid = sid->tid;
1752 }
1753 }
1754
1755 sz = sizeof(struct id_index_event) + nr * sizeof(struct id_index_entry);
1756 ev->id_index.header.size = sz;
1757 ev->id_index.nr = nr;
1758
1759 err = process(tool, ev, NULL, machine);
1760out_err:
1761 free(ev);
1762
1763 return err;
1764}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 0321013bd9fd..dc26ebf60fe4 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -2,33 +2,19 @@
2#define __PERF_SESSION_H 2#define __PERF_SESSION_H
3 3
4#include "trace-event.h" 4#include "trace-event.h"
5#include "hist.h"
6#include "event.h" 5#include "event.h"
7#include "header.h" 6#include "header.h"
8#include "machine.h" 7#include "machine.h"
9#include "symbol.h" 8#include "symbol.h"
10#include "thread.h" 9#include "thread.h"
11#include "data.h" 10#include "data.h"
11#include "ordered-events.h"
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <linux/perf_event.h> 13#include <linux/perf_event.h>
14 14
15struct sample_queue;
16struct ip_callchain; 15struct ip_callchain;
17struct thread; 16struct thread;
18 17
19struct ordered_samples {
20 u64 last_flush;
21 u64 next_flush;
22 u64 max_timestamp;
23 struct list_head samples;
24 struct list_head sample_cache;
25 struct list_head to_free;
26 struct sample_queue *sample_buffer;
27 struct sample_queue *last_sample;
28 int sample_buffer_idx;
29 unsigned int nr_samples;
30};
31
32struct perf_session { 18struct perf_session {
33 struct perf_header header; 19 struct perf_header header;
34 struct machines machines; 20 struct machines machines;
@@ -39,7 +25,7 @@ struct perf_session {
39 bool one_mmap; 25 bool one_mmap;
40 void *one_mmap_addr; 26 void *one_mmap_addr;
41 u64 one_mmap_offset; 27 u64 one_mmap_offset;
42 struct ordered_samples ordered_samples; 28 struct ordered_events ordered_events;
43 struct perf_data_file *file; 29 struct perf_data_file *file;
44}; 30};
45 31
@@ -58,6 +44,11 @@ void perf_session__delete(struct perf_session *session);
58 44
59void perf_event_header__bswap(struct perf_event_header *hdr); 45void perf_event_header__bswap(struct perf_event_header *hdr);
60 46
47int perf_session__peek_event(struct perf_session *session, off_t file_offset,
48 void *buf, size_t buf_sz,
49 union perf_event **event_ptr,
50 struct perf_sample *sample);
51
61int __perf_session__process_events(struct perf_session *session, 52int __perf_session__process_events(struct perf_session *session,
62 u64 data_offset, u64 data_size, u64 size, 53 u64 data_offset, u64 data_size, u64 size,
63 struct perf_tool *tool); 54 struct perf_tool *tool);
@@ -65,10 +56,16 @@ int perf_session__process_events(struct perf_session *session,
65 struct perf_tool *tool); 56 struct perf_tool *tool);
66 57
67int perf_session_queue_event(struct perf_session *s, union perf_event *event, 58int perf_session_queue_event(struct perf_session *s, union perf_event *event,
68 struct perf_sample *sample, u64 file_offset); 59 struct perf_tool *tool, struct perf_sample *sample,
60 u64 file_offset);
69 61
70void perf_tool__fill_defaults(struct perf_tool *tool); 62void perf_tool__fill_defaults(struct perf_tool *tool);
71 63
64int perf_session__deliver_event(struct perf_session *session,
65 union perf_event *event,
66 struct perf_sample *sample,
67 struct perf_tool *tool, u64 file_offset);
68
72int perf_session__resolve_callchain(struct perf_session *session, 69int perf_session__resolve_callchain(struct perf_session *session,
73 struct perf_evsel *evsel, 70 struct perf_evsel *evsel,
74 struct thread *thread, 71 struct thread *thread,
@@ -128,5 +125,20 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
128 125
129extern volatile int session_done; 126extern volatile int session_done;
130 127
131#define session_done() (*(volatile int *)(&session_done)) 128#define session_done() ACCESS_ONCE(session_done)
129
130int perf_session__deliver_synth_event(struct perf_session *session,
131 union perf_event *event,
132 struct perf_sample *sample,
133 struct perf_tool *tool);
134
135int perf_event__process_id_index(struct perf_tool *tool,
136 union perf_event *event,
137 struct perf_session *session);
138
139int perf_event__synthesize_id_index(struct perf_tool *tool,
140 perf_event__handler_t process,
141 struct perf_evlist *evlist,
142 struct machine *machine);
143
132#endif /* __PERF_SESSION_H */ 144#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 14e5a039bc45..9139dda9f9a3 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -70,12 +70,14 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
70 size_t size, unsigned int width) 70 size_t size, unsigned int width)
71{ 71{
72 const char *comm = thread__comm_str(he->thread); 72 const char *comm = thread__comm_str(he->thread);
73 return repsep_snprintf(bf, size, "%*s:%5d", width - 6, 73
74 comm ?: "", he->thread->tid); 74 width = max(7U, width) - 6;
75 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
76 width, width, comm ?: "");
75} 77}
76 78
77struct sort_entry sort_thread = { 79struct sort_entry sort_thread = {
78 .se_header = "Command: Pid", 80 .se_header = " Pid:Command",
79 .se_cmp = sort__thread_cmp, 81 .se_cmp = sort__thread_cmp,
80 .se_snprintf = hist_entry__thread_snprintf, 82 .se_snprintf = hist_entry__thread_snprintf,
81 .se_width_idx = HISTC_THREAD, 83 .se_width_idx = HISTC_THREAD,
@@ -106,7 +108,7 @@ sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
106static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf, 108static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
107 size_t size, unsigned int width) 109 size_t size, unsigned int width)
108{ 110{
109 return repsep_snprintf(bf, size, "%*s", width, comm__str(he->comm)); 111 return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
110} 112}
111 113
112struct sort_entry sort_comm = { 114struct sort_entry sort_comm = {
@@ -152,10 +154,10 @@ static int _hist_entry__dso_snprintf(struct map *map, char *bf,
152 if (map && map->dso) { 154 if (map && map->dso) {
153 const char *dso_name = !verbose ? map->dso->short_name : 155 const char *dso_name = !verbose ? map->dso->short_name :
154 map->dso->long_name; 156 map->dso->long_name;
155 return repsep_snprintf(bf, size, "%-*s", width, dso_name); 157 return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
156 } 158 }
157 159
158 return repsep_snprintf(bf, size, "%-*s", width, "[unknown]"); 160 return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
159} 161}
160 162
161static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf, 163static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
@@ -257,7 +259,10 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
257 width - ret, ""); 259 width - ret, "");
258 } 260 }
259 261
260 return ret; 262 if (ret > width)
263 bf[width] = '\0';
264
265 return width;
261} 266}
262 267
263static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, 268static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
@@ -286,7 +291,8 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
286 else { 291 else {
287 struct map *map = left->ms.map; 292 struct map *map = left->ms.map;
288 left->srcline = get_srcline(map->dso, 293 left->srcline = get_srcline(map->dso,
289 map__rip_2objdump(map, left->ip)); 294 map__rip_2objdump(map, left->ip),
295 left->ms.sym, true);
290 } 296 }
291 } 297 }
292 if (!right->srcline) { 298 if (!right->srcline) {
@@ -295,17 +301,17 @@ sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
295 else { 301 else {
296 struct map *map = right->ms.map; 302 struct map *map = right->ms.map;
297 right->srcline = get_srcline(map->dso, 303 right->srcline = get_srcline(map->dso,
298 map__rip_2objdump(map, right->ip)); 304 map__rip_2objdump(map, right->ip),
305 right->ms.sym, true);
299 } 306 }
300 } 307 }
301 return strcmp(right->srcline, left->srcline); 308 return strcmp(right->srcline, left->srcline);
302} 309}
303 310
304static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf, 311static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
305 size_t size, 312 size_t size, unsigned int width)
306 unsigned int width __maybe_unused)
307{ 313{
308 return repsep_snprintf(bf, size, "%s", he->srcline); 314 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
309} 315}
310 316
311struct sort_entry sort_srcline = { 317struct sort_entry sort_srcline = {
@@ -332,7 +338,7 @@ sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
332static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf, 338static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
333 size_t size, unsigned int width) 339 size_t size, unsigned int width)
334{ 340{
335 return repsep_snprintf(bf, size, "%-*s", width, 341 return repsep_snprintf(bf, size, "%-*.*s", width, width,
336 he->parent ? he->parent->name : "[other]"); 342 he->parent ? he->parent->name : "[other]");
337} 343}
338 344
@@ -354,7 +360,7 @@ sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
354static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf, 360static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
355 size_t size, unsigned int width) 361 size_t size, unsigned int width)
356{ 362{
357 return repsep_snprintf(bf, size, "%*d", width, he->cpu); 363 return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
358} 364}
359 365
360struct sort_entry sort_cpu = { 366struct sort_entry sort_cpu = {
@@ -369,6 +375,9 @@ struct sort_entry sort_cpu = {
369static int64_t 375static int64_t
370sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right) 376sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
371{ 377{
378 if (!left->branch_info || !right->branch_info)
379 return cmp_null(left->branch_info, right->branch_info);
380
372 return _sort__dso_cmp(left->branch_info->from.map, 381 return _sort__dso_cmp(left->branch_info->from.map,
373 right->branch_info->from.map); 382 right->branch_info->from.map);
374} 383}
@@ -376,13 +385,19 @@ sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
376static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf, 385static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
377 size_t size, unsigned int width) 386 size_t size, unsigned int width)
378{ 387{
379 return _hist_entry__dso_snprintf(he->branch_info->from.map, 388 if (he->branch_info)
380 bf, size, width); 389 return _hist_entry__dso_snprintf(he->branch_info->from.map,
390 bf, size, width);
391 else
392 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
381} 393}
382 394
383static int64_t 395static int64_t
384sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right) 396sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
385{ 397{
398 if (!left->branch_info || !right->branch_info)
399 return cmp_null(left->branch_info, right->branch_info);
400
386 return _sort__dso_cmp(left->branch_info->to.map, 401 return _sort__dso_cmp(left->branch_info->to.map,
387 right->branch_info->to.map); 402 right->branch_info->to.map);
388} 403}
@@ -390,8 +405,11 @@ sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
390static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf, 405static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
391 size_t size, unsigned int width) 406 size_t size, unsigned int width)
392{ 407{
393 return _hist_entry__dso_snprintf(he->branch_info->to.map, 408 if (he->branch_info)
394 bf, size, width); 409 return _hist_entry__dso_snprintf(he->branch_info->to.map,
410 bf, size, width);
411 else
412 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
395} 413}
396 414
397static int64_t 415static int64_t
@@ -400,6 +418,12 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
400 struct addr_map_symbol *from_l = &left->branch_info->from; 418 struct addr_map_symbol *from_l = &left->branch_info->from;
401 struct addr_map_symbol *from_r = &right->branch_info->from; 419 struct addr_map_symbol *from_r = &right->branch_info->from;
402 420
421 if (!left->branch_info || !right->branch_info)
422 return cmp_null(left->branch_info, right->branch_info);
423
424 from_l = &left->branch_info->from;
425 from_r = &right->branch_info->from;
426
403 if (!from_l->sym && !from_r->sym) 427 if (!from_l->sym && !from_r->sym)
404 return _sort__addr_cmp(from_l->addr, from_r->addr); 428 return _sort__addr_cmp(from_l->addr, from_r->addr);
405 429
@@ -409,8 +433,13 @@ sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
409static int64_t 433static int64_t
410sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right) 434sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
411{ 435{
412 struct addr_map_symbol *to_l = &left->branch_info->to; 436 struct addr_map_symbol *to_l, *to_r;
413 struct addr_map_symbol *to_r = &right->branch_info->to; 437
438 if (!left->branch_info || !right->branch_info)
439 return cmp_null(left->branch_info, right->branch_info);
440
441 to_l = &left->branch_info->to;
442 to_r = &right->branch_info->to;
414 443
415 if (!to_l->sym && !to_r->sym) 444 if (!to_l->sym && !to_r->sym)
416 return _sort__addr_cmp(to_l->addr, to_r->addr); 445 return _sort__addr_cmp(to_l->addr, to_r->addr);
@@ -421,19 +450,27 @@ sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
421static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf, 450static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
422 size_t size, unsigned int width) 451 size_t size, unsigned int width)
423{ 452{
424 struct addr_map_symbol *from = &he->branch_info->from; 453 if (he->branch_info) {
425 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr, 454 struct addr_map_symbol *from = &he->branch_info->from;
426 he->level, bf, size, width);
427 455
456 return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
457 he->level, bf, size, width);
458 }
459
460 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
428} 461}
429 462
430static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf, 463static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
431 size_t size, unsigned int width) 464 size_t size, unsigned int width)
432{ 465{
433 struct addr_map_symbol *to = &he->branch_info->to; 466 if (he->branch_info) {
434 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr, 467 struct addr_map_symbol *to = &he->branch_info->to;
435 he->level, bf, size, width);
436 468
469 return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
470 he->level, bf, size, width);
471 }
472
473 return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
437} 474}
438 475
439struct sort_entry sort_dso_from = { 476struct sort_entry sort_dso_from = {
@@ -467,11 +504,13 @@ struct sort_entry sort_sym_to = {
467static int64_t 504static int64_t
468sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right) 505sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
469{ 506{
470 const unsigned char mp = left->branch_info->flags.mispred != 507 unsigned char mp, p;
471 right->branch_info->flags.mispred;
472 const unsigned char p = left->branch_info->flags.predicted !=
473 right->branch_info->flags.predicted;
474 508
509 if (!left->branch_info || !right->branch_info)
510 return cmp_null(left->branch_info, right->branch_info);
511
512 mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
513 p = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
475 return mp || p; 514 return mp || p;
476} 515}
477 516
@@ -479,12 +518,14 @@ static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
479 size_t size, unsigned int width){ 518 size_t size, unsigned int width){
480 static const char *out = "N/A"; 519 static const char *out = "N/A";
481 520
482 if (he->branch_info->flags.predicted) 521 if (he->branch_info) {
483 out = "N"; 522 if (he->branch_info->flags.predicted)
484 else if (he->branch_info->flags.mispred) 523 out = "N";
485 out = "Y"; 524 else if (he->branch_info->flags.mispred)
525 out = "Y";
526 }
486 527
487 return repsep_snprintf(bf, size, "%-*s", width, out); 528 return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
488} 529}
489 530
490/* --sort daddr_sym */ 531/* --sort daddr_sym */
@@ -985,6 +1026,9 @@ struct sort_entry sort_mem_dcacheline = {
985static int64_t 1026static int64_t
986sort__abort_cmp(struct hist_entry *left, struct hist_entry *right) 1027sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
987{ 1028{
1029 if (!left->branch_info || !right->branch_info)
1030 return cmp_null(left->branch_info, right->branch_info);
1031
988 return left->branch_info->flags.abort != 1032 return left->branch_info->flags.abort !=
989 right->branch_info->flags.abort; 1033 right->branch_info->flags.abort;
990} 1034}
@@ -992,10 +1036,15 @@ sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
992static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf, 1036static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
993 size_t size, unsigned int width) 1037 size_t size, unsigned int width)
994{ 1038{
995 static const char *out = "."; 1039 static const char *out = "N/A";
1040
1041 if (he->branch_info) {
1042 if (he->branch_info->flags.abort)
1043 out = "A";
1044 else
1045 out = ".";
1046 }
996 1047
997 if (he->branch_info->flags.abort)
998 out = "A";
999 return repsep_snprintf(bf, size, "%-*s", width, out); 1048 return repsep_snprintf(bf, size, "%-*s", width, out);
1000} 1049}
1001 1050
@@ -1009,6 +1058,9 @@ struct sort_entry sort_abort = {
1009static int64_t 1058static int64_t
1010sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right) 1059sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1011{ 1060{
1061 if (!left->branch_info || !right->branch_info)
1062 return cmp_null(left->branch_info, right->branch_info);
1063
1012 return left->branch_info->flags.in_tx != 1064 return left->branch_info->flags.in_tx !=
1013 right->branch_info->flags.in_tx; 1065 right->branch_info->flags.in_tx;
1014} 1066}
@@ -1016,10 +1068,14 @@ sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
1016static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf, 1068static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
1017 size_t size, unsigned int width) 1069 size_t size, unsigned int width)
1018{ 1070{
1019 static const char *out = "."; 1071 static const char *out = "N/A";
1020 1072
1021 if (he->branch_info->flags.in_tx) 1073 if (he->branch_info) {
1022 out = "T"; 1074 if (he->branch_info->flags.in_tx)
1075 out = "T";
1076 else
1077 out = ".";
1078 }
1023 1079
1024 return repsep_snprintf(bf, size, "%-*s", width, out); 1080 return repsep_snprintf(bf, size, "%-*s", width, out);
1025} 1081}
@@ -1194,7 +1250,7 @@ bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1194 return hse_a->se == hse_b->se; 1250 return hse_a->se == hse_b->se;
1195} 1251}
1196 1252
1197void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists) 1253void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1198{ 1254{
1199 struct hpp_sort_entry *hse; 1255 struct hpp_sort_entry *hse;
1200 1256
@@ -1202,20 +1258,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1202 return; 1258 return;
1203 1259
1204 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1260 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1205 hists__new_col_len(hists, hse->se->se_width_idx, 1261 hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
1206 strlen(hse->se->se_header));
1207} 1262}
1208 1263
1209static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1264static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1210 struct perf_evsel *evsel) 1265 struct perf_evsel *evsel)
1211{ 1266{
1212 struct hpp_sort_entry *hse; 1267 struct hpp_sort_entry *hse;
1213 size_t len; 1268 size_t len = fmt->user_len;
1214 1269
1215 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1270 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1216 len = hists__col_len(&evsel->hists, hse->se->se_width_idx);
1217 1271
1218 return scnprintf(hpp->buf, hpp->size, "%-*s", len, hse->se->se_header); 1272 if (!len)
1273 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1274
1275 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1219} 1276}
1220 1277
1221static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1278static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
@@ -1223,20 +1280,26 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1223 struct perf_evsel *evsel) 1280 struct perf_evsel *evsel)
1224{ 1281{
1225 struct hpp_sort_entry *hse; 1282 struct hpp_sort_entry *hse;
1283 size_t len = fmt->user_len;
1226 1284
1227 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1285 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1228 1286
1229 return hists__col_len(&evsel->hists, hse->se->se_width_idx); 1287 if (!len)
1288 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1289
1290 return len;
1230} 1291}
1231 1292
1232static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1293static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1233 struct hist_entry *he) 1294 struct hist_entry *he)
1234{ 1295{
1235 struct hpp_sort_entry *hse; 1296 struct hpp_sort_entry *hse;
1236 size_t len; 1297 size_t len = fmt->user_len;
1237 1298
1238 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1299 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1239 len = hists__col_len(he->hists, hse->se->se_width_idx); 1300
1301 if (!len)
1302 len = hists__col_len(he->hists, hse->se->se_width_idx);
1240 1303
1241 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len); 1304 return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
1242} 1305}
@@ -1253,6 +1316,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1253 } 1316 }
1254 1317
1255 hse->se = sd->entry; 1318 hse->se = sd->entry;
1319 hse->hpp.name = sd->entry->se_header;
1256 hse->hpp.header = __sort__hpp_header; 1320 hse->hpp.header = __sort__hpp_header;
1257 hse->hpp.width = __sort__hpp_width; 1321 hse->hpp.width = __sort__hpp_width;
1258 hse->hpp.entry = __sort__hpp_entry; 1322 hse->hpp.entry = __sort__hpp_entry;
@@ -1265,6 +1329,8 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd)
1265 INIT_LIST_HEAD(&hse->hpp.list); 1329 INIT_LIST_HEAD(&hse->hpp.list);
1266 INIT_LIST_HEAD(&hse->hpp.sort_list); 1330 INIT_LIST_HEAD(&hse->hpp.sort_list);
1267 hse->hpp.elide = false; 1331 hse->hpp.elide = false;
1332 hse->hpp.len = 0;
1333 hse->hpp.user_len = 0;
1268 1334
1269 return hse; 1335 return hse;
1270} 1336}
@@ -1432,14 +1498,49 @@ static const char *get_default_sort_order(void)
1432 return default_sort_orders[sort__mode]; 1498 return default_sort_orders[sort__mode];
1433} 1499}
1434 1500
1501static int setup_sort_order(void)
1502{
1503 char *new_sort_order;
1504
1505 /*
1506 * Append '+'-prefixed sort order to the default sort
1507 * order string.
1508 */
1509 if (!sort_order || is_strict_order(sort_order))
1510 return 0;
1511
1512 if (sort_order[1] == '\0') {
1513 error("Invalid --sort key: `+'");
1514 return -EINVAL;
1515 }
1516
1517 /*
1518 * We allocate new sort_order string, but we never free it,
1519 * because it's checked over the rest of the code.
1520 */
1521 if (asprintf(&new_sort_order, "%s,%s",
1522 get_default_sort_order(), sort_order + 1) < 0) {
1523 error("Not enough memory to set up --sort");
1524 return -ENOMEM;
1525 }
1526
1527 sort_order = new_sort_order;
1528 return 0;
1529}
1530
1435static int __setup_sorting(void) 1531static int __setup_sorting(void)
1436{ 1532{
1437 char *tmp, *tok, *str; 1533 char *tmp, *tok, *str;
1438 const char *sort_keys = sort_order; 1534 const char *sort_keys;
1439 int ret = 0; 1535 int ret = 0;
1440 1536
1537 ret = setup_sort_order();
1538 if (ret)
1539 return ret;
1540
1541 sort_keys = sort_order;
1441 if (sort_keys == NULL) { 1542 if (sort_keys == NULL) {
1442 if (field_order) { 1543 if (is_strict_order(field_order)) {
1443 /* 1544 /*
1444 * If user specified field order but no sort order, 1545 * If user specified field order but no sort order,
1445 * we'll honor it and not add default sort orders. 1546 * we'll honor it and not add default sort orders.
@@ -1625,23 +1726,36 @@ static void reset_dimensions(void)
1625 memory_sort_dimensions[i].taken = 0; 1726 memory_sort_dimensions[i].taken = 0;
1626} 1727}
1627 1728
1729bool is_strict_order(const char *order)
1730{
1731 return order && (*order != '+');
1732}
1733
1628static int __setup_output_field(void) 1734static int __setup_output_field(void)
1629{ 1735{
1630 char *tmp, *tok, *str; 1736 char *tmp, *tok, *str, *strp;
1631 int ret = 0; 1737 int ret = -EINVAL;
1632 1738
1633 if (field_order == NULL) 1739 if (field_order == NULL)
1634 return 0; 1740 return 0;
1635 1741
1636 reset_dimensions(); 1742 reset_dimensions();
1637 1743
1638 str = strdup(field_order); 1744 strp = str = strdup(field_order);
1639 if (str == NULL) { 1745 if (str == NULL) {
1640 error("Not enough memory to setup output fields"); 1746 error("Not enough memory to setup output fields");
1641 return -ENOMEM; 1747 return -ENOMEM;
1642 } 1748 }
1643 1749
1644 for (tok = strtok_r(str, ", ", &tmp); 1750 if (!is_strict_order(field_order))
1751 strp++;
1752
1753 if (!strlen(strp)) {
1754 error("Invalid --fields key: `+'");
1755 goto out;
1756 }
1757
1758 for (tok = strtok_r(strp, ", ", &tmp);
1645 tok; tok = strtok_r(NULL, ", ", &tmp)) { 1759 tok; tok = strtok_r(NULL, ", ", &tmp)) {
1646 ret = output_field_add(tok); 1760 ret = output_field_add(tok);
1647 if (ret == -EINVAL) { 1761 if (ret == -EINVAL) {
@@ -1653,6 +1767,7 @@ static int __setup_output_field(void)
1653 } 1767 }
1654 } 1768 }
1655 1769
1770out:
1656 free(str); 1771 free(str);
1657 return ret; 1772 return ret;
1658} 1773}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 041f0c9cea2b..c03e4ff8beff 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -218,4 +218,5 @@ void perf_hpp__set_elide(int idx, bool elide);
218 218
219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset); 219int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);
220 220
221bool is_strict_order(const char *order);
221#endif /* __PERF_SORT_H */ 222#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
index f3e4bc5fe5d2..c93fb0c5bd0b 100644
--- a/tools/perf/util/srcline.c
+++ b/tools/perf/util/srcline.c
@@ -8,6 +8,8 @@
8#include "util/util.h" 8#include "util/util.h"
9#include "util/debug.h" 9#include "util/debug.h"
10 10
11#include "symbol.h"
12
11#ifdef HAVE_LIBBFD_SUPPORT 13#ifdef HAVE_LIBBFD_SUPPORT
12 14
13/* 15/*
@@ -18,7 +20,7 @@
18 20
19struct a2l_data { 21struct a2l_data {
20 const char *input; 22 const char *input;
21 unsigned long addr; 23 u64 addr;
22 24
23 bool found; 25 bool found;
24 const char *filename; 26 const char *filename;
@@ -145,7 +147,7 @@ static void addr2line_cleanup(struct a2l_data *a2l)
145 free(a2l); 147 free(a2l);
146} 148}
147 149
148static int addr2line(const char *dso_name, unsigned long addr, 150static int addr2line(const char *dso_name, u64 addr,
149 char **file, unsigned int *line, struct dso *dso) 151 char **file, unsigned int *line, struct dso *dso)
150{ 152{
151 int ret = 0; 153 int ret = 0;
@@ -191,7 +193,7 @@ void dso__free_a2l(struct dso *dso)
191 193
192#else /* HAVE_LIBBFD_SUPPORT */ 194#else /* HAVE_LIBBFD_SUPPORT */
193 195
194static int addr2line(const char *dso_name, unsigned long addr, 196static int addr2line(const char *dso_name, u64 addr,
195 char **file, unsigned int *line_nr, 197 char **file, unsigned int *line_nr,
196 struct dso *dso __maybe_unused) 198 struct dso *dso __maybe_unused)
197{ 199{
@@ -250,7 +252,8 @@ void dso__free_a2l(struct dso *dso __maybe_unused)
250 */ 252 */
251#define A2L_FAIL_LIMIT 123 253#define A2L_FAIL_LIMIT 123
252 254
253char *get_srcline(struct dso *dso, unsigned long addr) 255char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
256 bool show_sym)
254{ 257{
255 char *file = NULL; 258 char *file = NULL;
256 unsigned line = 0; 259 unsigned line = 0;
@@ -258,7 +261,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
258 const char *dso_name; 261 const char *dso_name;
259 262
260 if (!dso->has_srcline) 263 if (!dso->has_srcline)
261 return SRCLINE_UNKNOWN; 264 goto out;
262 265
263 if (dso->symsrc_filename) 266 if (dso->symsrc_filename)
264 dso_name = dso->symsrc_filename; 267 dso_name = dso->symsrc_filename;
@@ -274,7 +277,7 @@ char *get_srcline(struct dso *dso, unsigned long addr)
274 if (!addr2line(dso_name, addr, &file, &line, dso)) 277 if (!addr2line(dso_name, addr, &file, &line, dso))
275 goto out; 278 goto out;
276 279
277 if (asprintf(&srcline, "%s:%u", file, line) < 0) { 280 if (asprintf(&srcline, "%s:%u", basename(file), line) < 0) {
278 free(file); 281 free(file);
279 goto out; 282 goto out;
280 } 283 }
@@ -289,7 +292,13 @@ out:
289 dso->has_srcline = 0; 292 dso->has_srcline = 0;
290 dso__free_a2l(dso); 293 dso__free_a2l(dso);
291 } 294 }
292 return SRCLINE_UNKNOWN; 295 if (sym) {
296 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "",
297 addr - sym->start) < 0)
298 return SRCLINE_UNKNOWN;
299 } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso->short_name, addr) < 0)
300 return SRCLINE_UNKNOWN;
301 return srcline;
293} 302}
294 303
295void free_srcline(char *srcline) 304void free_srcline(char *srcline)
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 2553e5b55b89..6afd6106ceb5 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -9,78 +9,48 @@
9 */ 9 */
10s64 perf_atoll(const char *str) 10s64 perf_atoll(const char *str)
11{ 11{
12 unsigned int i; 12 s64 length;
13 s64 length = -1, unit = 1; 13 char *p;
14 char c;
14 15
15 if (!isdigit(str[0])) 16 if (!isdigit(str[0]))
16 goto out_err; 17 goto out_err;
17 18
18 for (i = 1; i < strlen(str); i++) { 19 length = strtoll(str, &p, 10);
19 switch (str[i]) { 20 switch (c = *p++) {
20 case 'B': 21 case 'b': case 'B':
21 case 'b': 22 if (*p)
22 break;
23 case 'K':
24 if (str[i + 1] != 'B')
25 goto out_err;
26 else
27 goto kilo;
28 case 'k':
29 if (str[i + 1] != 'b')
30 goto out_err;
31kilo:
32 unit = K;
33 break;
34 case 'M':
35 if (str[i + 1] != 'B')
36 goto out_err;
37 else
38 goto mega;
39 case 'm':
40 if (str[i + 1] != 'b')
41 goto out_err;
42mega:
43 unit = K * K;
44 break;
45 case 'G':
46 if (str[i + 1] != 'B')
47 goto out_err; 23 goto out_err;
48 else 24 case '\0':
49 goto giga; 25 return length;
50 case 'g': 26 default:
51 if (str[i + 1] != 'b') 27 goto out_err;
52 goto out_err; 28 /* two-letter suffices */
53giga: 29 case 'k': case 'K':
54 unit = K * K * K; 30 length <<= 10;
55 break; 31 break;
56 case 'T': 32 case 'm': case 'M':
57 if (str[i + 1] != 'B') 33 length <<= 20;
58 goto out_err;
59 else
60 goto tera;
61 case 't':
62 if (str[i + 1] != 'b')
63 goto out_err;
64tera:
65 unit = K * K * K * K;
66 break; 34 break;
67 case '\0': /* only specified figures */ 35 case 'g': case 'G':
68 unit = 1; 36 length <<= 30;
69 break; 37 break;
70 default: 38 case 't': case 'T':
71 if (!isdigit(str[i])) 39 length <<= 40;
72 goto out_err;
73 break; 40 break;
74 }
75 } 41 }
76 42 /* we want the cases to match */
77 length = atoll(str) * unit; 43 if (islower(c)) {
78 goto out; 44 if (strcmp(p, "b") != 0)
45 goto out_err;
46 } else {
47 if (strcmp(p, "B") != 0)
48 goto out_err;
49 }
50 return length;
79 51
80out_err: 52out_err:
81 length = -1; 53 return -1;
82out:
83 return length;
84} 54}
85 55
86/* 56/*
@@ -387,27 +357,3 @@ void *memdup(const void *src, size_t len)
387 357
388 return p; 358 return p;
389} 359}
390
391/**
392 * str_append - reallocate string and append another
393 * @s: pointer to string pointer
394 * @len: pointer to len (initialized)
395 * @a: string to append.
396 */
397int str_append(char **s, int *len, const char *a)
398{
399 int olen = *s ? strlen(*s) : 0;
400 int nlen = olen + strlen(a) + 1;
401 if (*len < nlen) {
402 *len = *len * 2;
403 if (*len < nlen)
404 *len = nlen;
405 *s = realloc(*s, *len);
406 if (!*s)
407 return -ENOMEM;
408 if (olen == 0)
409 **s = 0;
410 }
411 strcat(*s, a);
412 return 0;
413}
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index d75349979e65..06fcd1bf98b6 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -6,10 +6,32 @@
6#include <inttypes.h> 6#include <inttypes.h>
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "machine.h"
9#include "vdso.h" 10#include "vdso.h"
10#include <symbol/kallsyms.h> 11#include <symbol/kallsyms.h>
11#include "debug.h" 12#include "debug.h"
12 13
14#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
15extern char *cplus_demangle(const char *, int);
16
17static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
18{
19 return cplus_demangle(c, i);
20}
21#else
22#ifdef NO_DEMANGLE
23static inline char *bfd_demangle(void __maybe_unused *v,
24 const char __maybe_unused *c,
25 int __maybe_unused i)
26{
27 return NULL;
28}
29#else
30#define PACKAGE 'perf'
31#include <bfd.h>
32#endif
33#endif
34
13#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT 35#ifndef HAVE_ELF_GETPHDRNUM_SUPPORT
14static int elf_getphdrnum(Elf *elf, size_t *dst) 36static int elf_getphdrnum(Elf *elf, size_t *dst)
15{ 37{
@@ -545,6 +567,35 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata)
545 return 0; 567 return 0;
546} 568}
547 569
570static int decompress_kmodule(struct dso *dso, const char *name,
571 enum dso_binary_type type)
572{
573 int fd;
574 const char *ext = strrchr(name, '.');
575 char tmpbuf[] = "/tmp/perf-kmod-XXXXXX";
576
577 if ((type != DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP &&
578 type != DSO_BINARY_TYPE__GUEST_KMODULE_COMP) ||
579 type != dso->symtab_type)
580 return -1;
581
582 if (!ext || !is_supported_compression(ext + 1))
583 return -1;
584
585 fd = mkstemp(tmpbuf);
586 if (fd < 0)
587 return -1;
588
589 if (!decompress_to_file(ext + 1, name, fd)) {
590 close(fd);
591 fd = -1;
592 }
593
594 unlink(tmpbuf);
595
596 return fd;
597}
598
548bool symsrc__possibly_runtime(struct symsrc *ss) 599bool symsrc__possibly_runtime(struct symsrc *ss)
549{ 600{
550 return ss->dynsym || ss->opdsec; 601 return ss->dynsym || ss->opdsec;
@@ -570,7 +621,11 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
570 Elf *elf; 621 Elf *elf;
571 int fd; 622 int fd;
572 623
573 fd = open(name, O_RDONLY); 624 if (dso__needs_decompress(dso))
625 fd = decompress_kmodule(dso, name, type);
626 else
627 fd = open(name, O_RDONLY);
628
574 if (fd < 0) 629 if (fd < 0)
575 return -1; 630 return -1;
576 631
@@ -680,6 +735,11 @@ static u64 ref_reloc(struct kmap *kmap)
680 return 0; 735 return 0;
681} 736}
682 737
738static bool want_demangle(bool is_kernel_sym)
739{
740 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
741}
742
683int dso__load_sym(struct dso *dso, struct map *map, 743int dso__load_sym(struct dso *dso, struct map *map,
684 struct symsrc *syms_ss, struct symsrc *runtime_ss, 744 struct symsrc *syms_ss, struct symsrc *runtime_ss,
685 symbol_filter_t filter, int kmodule) 745 symbol_filter_t filter, int kmodule)
@@ -712,6 +772,14 @@ int dso__load_sym(struct dso *dso, struct map *map,
712 symbols__delete(&dso->symbols[map->type]); 772 symbols__delete(&dso->symbols[map->type]);
713 773
714 if (!syms_ss->symtab) { 774 if (!syms_ss->symtab) {
775 /*
776 * If the vmlinux is stripped, fail so we will fall back
777 * to using kallsyms. The vmlinux runtime symbols aren't
778 * of much use.
779 */
780 if (dso->kernel)
781 goto out_elf_end;
782
715 syms_ss->symtab = syms_ss->dynsym; 783 syms_ss->symtab = syms_ss->dynsym;
716 syms_ss->symshdr = syms_ss->dynshdr; 784 syms_ss->symshdr = syms_ss->dynshdr;
717 } 785 }
@@ -736,7 +804,7 @@ int dso__load_sym(struct dso *dso, struct map *map,
736 if (symstrs == NULL) 804 if (symstrs == NULL)
737 goto out_elf_end; 805 goto out_elf_end;
738 806
739 sec_strndx = elf_getscn(elf, ehdr.e_shstrndx); 807 sec_strndx = elf_getscn(runtime_ss->elf, runtime_ss->ehdr.e_shstrndx);
740 if (sec_strndx == NULL) 808 if (sec_strndx == NULL)
741 goto out_elf_end; 809 goto out_elf_end;
742 810
@@ -916,7 +984,11 @@ int dso__load_sym(struct dso *dso, struct map *map,
916 } 984 }
917 curr_dso->symtab_type = dso->symtab_type; 985 curr_dso->symtab_type = dso->symtab_type;
918 map_groups__insert(kmap->kmaps, curr_map); 986 map_groups__insert(kmap->kmaps, curr_map);
919 dsos__add(&dso->node, curr_dso); 987 /*
988 * The new DSO should go to the kernel DSOS
989 */
990 dsos__add(&map->groups->machine->kernel_dsos,
991 curr_dso);
920 dso__set_loaded(curr_dso, map->type); 992 dso__set_loaded(curr_dso, map->type);
921 } else 993 } else
922 curr_dso = curr_map->dso; 994 curr_dso = curr_map->dso;
@@ -938,9 +1010,12 @@ new_symbol:
938 * DWARF DW_compile_unit has this, but we don't always have access 1010 * DWARF DW_compile_unit has this, but we don't always have access
939 * to it... 1011 * to it...
940 */ 1012 */
941 if (symbol_conf.demangle) { 1013 if (want_demangle(dso->kernel || kmodule)) {
942 demangled = bfd_demangle(NULL, elf_name, 1014 int demangle_flags = DMGL_NO_OPTS;
943 DMGL_PARAMS | DMGL_ANSI); 1015 if (verbose)
1016 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
1017
1018 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
944 if (demangled != NULL) 1019 if (demangled != NULL)
945 elf_name = demangled; 1020 elf_name = demangled;
946 } 1021 }
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index c9541fea9514..d7efb03b3f9a 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -129,6 +129,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
129 129
130 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { 130 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
131 void *tmp; 131 void *tmp;
132 long offset;
132 133
133 if (need_swap) { 134 if (need_swap) {
134 phdr->p_type = bswap_32(phdr->p_type); 135 phdr->p_type = bswap_32(phdr->p_type);
@@ -140,12 +141,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
140 continue; 141 continue;
141 142
142 buf_size = phdr->p_filesz; 143 buf_size = phdr->p_filesz;
144 offset = phdr->p_offset;
143 tmp = realloc(buf, buf_size); 145 tmp = realloc(buf, buf_size);
144 if (tmp == NULL) 146 if (tmp == NULL)
145 goto out_free; 147 goto out_free;
146 148
147 buf = tmp; 149 buf = tmp;
148 fseek(fp, phdr->p_offset, SEEK_SET); 150 fseek(fp, offset, SEEK_SET);
149 if (fread(buf, buf_size, 1, fp) != 1) 151 if (fread(buf, buf_size, 1, fp) != 1)
150 goto out_free; 152 goto out_free;
151 153
@@ -178,6 +180,7 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
178 180
179 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) { 181 for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
180 void *tmp; 182 void *tmp;
183 long offset;
181 184
182 if (need_swap) { 185 if (need_swap) {
183 phdr->p_type = bswap_32(phdr->p_type); 186 phdr->p_type = bswap_32(phdr->p_type);
@@ -189,12 +192,13 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)
189 continue; 192 continue;
190 193
191 buf_size = phdr->p_filesz; 194 buf_size = phdr->p_filesz;
195 offset = phdr->p_offset;
192 tmp = realloc(buf, buf_size); 196 tmp = realloc(buf, buf_size);
193 if (tmp == NULL) 197 if (tmp == NULL)
194 goto out_free; 198 goto out_free;
195 199
196 buf = tmp; 200 buf = tmp;
197 fseek(fp, phdr->p_offset, SEEK_SET); 201 fseek(fp, offset, SEEK_SET);
198 if (fread(buf, buf_size, 1, fp) != 1) 202 if (fread(buf, buf_size, 1, fp) != 1)
199 goto out_free; 203 goto out_free;
200 204
@@ -341,7 +345,6 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
341 345
342 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { 346 if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
343 dso__set_build_id(dso, build_id); 347 dso__set_build_id(dso, build_id);
344 return 1;
345 } 348 }
346 return 0; 349 return 0;
347} 350}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index eb06746b06b2..c24c5b83156c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -15,6 +15,7 @@
15#include "machine.h" 15#include "machine.h"
16#include "symbol.h" 16#include "symbol.h"
17#include "strlist.h" 17#include "strlist.h"
18#include "header.h"
18 19
19#include <elf.h> 20#include <elf.h>
20#include <limits.h> 21#include <limits.h>
@@ -33,6 +34,7 @@ struct symbol_conf symbol_conf = {
33 .try_vmlinux_path = true, 34 .try_vmlinux_path = true,
34 .annotate_src = true, 35 .annotate_src = true,
35 .demangle = true, 36 .demangle = true,
37 .demangle_kernel = false,
36 .cumulate_callchain = true, 38 .cumulate_callchain = true,
37 .show_hist_headers = true, 39 .show_hist_headers = true,
38 .symfs = "", 40 .symfs = "",
@@ -49,7 +51,9 @@ static enum dso_binary_type binary_type_symtab[] = {
49 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 51 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
50 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 52 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
51 DSO_BINARY_TYPE__GUEST_KMODULE, 53 DSO_BINARY_TYPE__GUEST_KMODULE,
54 DSO_BINARY_TYPE__GUEST_KMODULE_COMP,
52 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 55 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
56 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP,
53 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 57 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
54 DSO_BINARY_TYPE__NOT_FOUND, 58 DSO_BINARY_TYPE__NOT_FOUND,
55}; 59};
@@ -184,7 +188,7 @@ void symbols__fixup_end(struct rb_root *symbols)
184 curr = rb_entry(nd, struct symbol, rb_node); 188 curr = rb_entry(nd, struct symbol, rb_node);
185 189
186 if (prev->end == prev->start && prev->end != curr->start) 190 if (prev->end == prev->start && prev->end != curr->start)
187 prev->end = curr->start - 1; 191 prev->end = curr->start;
188 } 192 }
189 193
190 /* Last entry */ 194 /* Last entry */
@@ -205,7 +209,7 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
205 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 209 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
206 prev = curr; 210 prev = curr;
207 curr = rb_entry(nd, struct map, rb_node); 211 curr = rb_entry(nd, struct map, rb_node);
208 prev->end = curr->start - 1; 212 prev->end = curr->start;
209 } 213 }
210 214
211 /* 215 /*
@@ -227,7 +231,7 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
227 sym = ((void *)sym) + symbol_conf.priv_size; 231 sym = ((void *)sym) + symbol_conf.priv_size;
228 232
229 sym->start = start; 233 sym->start = start;
230 sym->end = len ? start + len - 1 : start; 234 sym->end = len ? start + len : start;
231 sym->binding = binding; 235 sym->binding = binding;
232 sym->namelen = namelen - 1; 236 sym->namelen = namelen - 1;
233 237
@@ -323,7 +327,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
323 327
324 if (ip < s->start) 328 if (ip < s->start)
325 n = n->rb_left; 329 n = n->rb_left;
326 else if (ip > s->end) 330 else if (ip >= s->end)
327 n = n->rb_right; 331 n = n->rb_right;
328 else 332 else
329 return s; 333 return s;
@@ -523,10 +527,15 @@ struct process_kallsyms_args {
523 struct dso *dso; 527 struct dso *dso;
524}; 528};
525 529
530/*
531 * These are symbols in the kernel image, so make sure that
532 * sym is from a kernel DSO.
533 */
526bool symbol__is_idle(struct symbol *sym) 534bool symbol__is_idle(struct symbol *sym)
527{ 535{
528 const char * const idle_symbols[] = { 536 const char * const idle_symbols[] = {
529 "cpu_idle", 537 "cpu_idle",
538 "cpu_startup_entry",
530 "intel_idle", 539 "intel_idle",
531 "default_idle", 540 "default_idle",
532 "native_safe_halt", 541 "native_safe_halt",
@@ -1293,7 +1302,9 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1293 return dso->kernel == DSO_TYPE_GUEST_KERNEL; 1302 return dso->kernel == DSO_TYPE_GUEST_KERNEL;
1294 1303
1295 case DSO_BINARY_TYPE__GUEST_KMODULE: 1304 case DSO_BINARY_TYPE__GUEST_KMODULE:
1305 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
1296 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE: 1306 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1307 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
1297 /* 1308 /*
1298 * kernel modules know their symtab type - it's set when 1309 * kernel modules know their symtab type - it's set when
1299 * creating a module dso in machine__new_module(). 1310 * creating a module dso in machine__new_module().
@@ -1361,7 +1372,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1361 return -1; 1372 return -1;
1362 1373
1363 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || 1374 kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1364 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE; 1375 dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
1376 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE ||
1377 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
1365 1378
1366 /* 1379 /*
1367 * Iterate over candidate debug images. 1380 * Iterate over candidate debug images.
@@ -1468,8 +1481,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1468 if (vmlinux[0] == '/') 1481 if (vmlinux[0] == '/')
1469 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux); 1482 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s", vmlinux);
1470 else 1483 else
1471 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", 1484 symbol__join_symfs(symfs_vmlinux, vmlinux);
1472 symbol_conf.symfs, vmlinux);
1473 1485
1474 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1486 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1475 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1487 symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
@@ -1499,12 +1511,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1499 symbol_filter_t filter) 1511 symbol_filter_t filter)
1500{ 1512{
1501 int i, err = 0; 1513 int i, err = 0;
1502 char *filename; 1514 char *filename = NULL;
1503
1504 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1505 vmlinux_path__nr_entries + 1);
1506 1515
1507 filename = dso__build_id_filename(dso, NULL, 0); 1516 if (!symbol_conf.ignore_vmlinux_buildid)
1517 filename = dso__build_id_filename(dso, NULL, 0);
1508 if (filename != NULL) { 1518 if (filename != NULL) {
1509 err = dso__load_vmlinux(dso, map, filename, true, filter); 1519 err = dso__load_vmlinux(dso, map, filename, true, filter);
1510 if (err > 0) 1520 if (err > 0)
@@ -1512,6 +1522,9 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1512 free(filename); 1522 free(filename);
1513 } 1523 }
1514 1524
1525 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1526 vmlinux_path__nr_entries + 1);
1527
1515 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1528 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1516 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); 1529 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1517 if (err > 0) 1530 if (err > 0)
@@ -1745,12 +1758,13 @@ static void vmlinux_path__exit(void)
1745 zfree(&vmlinux_path); 1758 zfree(&vmlinux_path);
1746} 1759}
1747 1760
1748static int vmlinux_path__init(void) 1761static int vmlinux_path__init(struct perf_session_env *env)
1749{ 1762{
1750 struct utsname uts; 1763 struct utsname uts;
1751 char bf[PATH_MAX]; 1764 char bf[PATH_MAX];
1765 char *kernel_version;
1752 1766
1753 vmlinux_path = malloc(sizeof(char *) * 5); 1767 vmlinux_path = malloc(sizeof(char *) * 6);
1754 if (vmlinux_path == NULL) 1768 if (vmlinux_path == NULL)
1755 return -1; 1769 return -1;
1756 1770
@@ -1763,25 +1777,37 @@ static int vmlinux_path__init(void)
1763 goto out_fail; 1777 goto out_fail;
1764 ++vmlinux_path__nr_entries; 1778 ++vmlinux_path__nr_entries;
1765 1779
1766 /* only try running kernel version if no symfs was given */ 1780 /* only try kernel version if no symfs was given */
1767 if (symbol_conf.symfs[0] != 0) 1781 if (symbol_conf.symfs[0] != 0)
1768 return 0; 1782 return 0;
1769 1783
1770 if (uname(&uts) < 0) 1784 if (env) {
1771 return -1; 1785 kernel_version = env->os_release;
1786 } else {
1787 if (uname(&uts) < 0)
1788 goto out_fail;
1789
1790 kernel_version = uts.release;
1791 }
1772 1792
1773 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 1793 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", kernel_version);
1774 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1794 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1775 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1795 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1776 goto out_fail; 1796 goto out_fail;
1777 ++vmlinux_path__nr_entries; 1797 ++vmlinux_path__nr_entries;
1778 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", uts.release); 1798 snprintf(bf, sizeof(bf), "/usr/lib/debug/boot/vmlinux-%s",
1799 kernel_version);
1800 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1801 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1802 goto out_fail;
1803 ++vmlinux_path__nr_entries;
1804 snprintf(bf, sizeof(bf), "/lib/modules/%s/build/vmlinux", kernel_version);
1779 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1805 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1780 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1806 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1781 goto out_fail; 1807 goto out_fail;
1782 ++vmlinux_path__nr_entries; 1808 ++vmlinux_path__nr_entries;
1783 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux", 1809 snprintf(bf, sizeof(bf), "/usr/lib/debug/lib/modules/%s/vmlinux",
1784 uts.release); 1810 kernel_version);
1785 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 1811 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
1786 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 1812 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
1787 goto out_fail; 1813 goto out_fail;
@@ -1827,7 +1853,7 @@ static bool symbol__read_kptr_restrict(void)
1827 return value; 1853 return value;
1828} 1854}
1829 1855
1830int symbol__init(void) 1856int symbol__init(struct perf_session_env *env)
1831{ 1857{
1832 const char *symfs; 1858 const char *symfs;
1833 1859
@@ -1842,7 +1868,7 @@ int symbol__init(void)
1842 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 1868 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
1843 sizeof(struct symbol)); 1869 sizeof(struct symbol));
1844 1870
1845 if (symbol_conf.try_vmlinux_path && vmlinux_path__init() < 0) 1871 if (symbol_conf.try_vmlinux_path && vmlinux_path__init(env) < 0)
1846 return -1; 1872 return -1;
1847 1873
1848 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') { 1874 if (symbol_conf.field_sep && *symbol_conf.field_sep == '.') {
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index e7295e93cff9..9d602e9c6f59 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -13,6 +13,7 @@
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h" 14#include "build-id.h"
15#include "event.h" 15#include "event.h"
16#include "util.h"
16 17
17#ifdef HAVE_LIBELF_SUPPORT 18#ifdef HAVE_LIBELF_SUPPORT
18#include <libelf.h> 19#include <libelf.h>
@@ -22,27 +23,6 @@
22 23
23#include "dso.h" 24#include "dso.h"
24 25
25#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
26extern char *cplus_demangle(const char *, int);
27
28static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i)
29{
30 return cplus_demangle(c, i);
31}
32#else
33#ifdef NO_DEMANGLE
34static inline char *bfd_demangle(void __maybe_unused *v,
35 const char __maybe_unused *c,
36 int __maybe_unused i)
37{
38 return NULL;
39}
40#else
41#define PACKAGE 'perf'
42#include <bfd.h>
43#endif
44#endif
45
46/* 26/*
47 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 27 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
48 * for newer versions we can use mmap to reduce memory usage: 28 * for newer versions we can use mmap to reduce memory usage:
@@ -59,6 +39,7 @@ extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
59#endif 39#endif
60 40
61#ifndef DMGL_PARAMS 41#ifndef DMGL_PARAMS
42#define DMGL_NO_OPTS 0 /* For readability... */
62#define DMGL_PARAMS (1 << 0) /* Include function args */ 43#define DMGL_PARAMS (1 << 0) /* Include function args */
63#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 44#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
64#endif 45#endif
@@ -93,7 +74,7 @@ void symbols__delete(struct rb_root *symbols);
93 74
94static inline size_t symbol__size(const struct symbol *sym) 75static inline size_t symbol__size(const struct symbol *sym)
95{ 76{
96 return sym->end - sym->start + 1; 77 return sym->end - sym->start;
97} 78}
98 79
99struct strlist; 80struct strlist;
@@ -103,6 +84,7 @@ struct symbol_conf {
103 unsigned short nr_events; 84 unsigned short nr_events;
104 bool try_vmlinux_path, 85 bool try_vmlinux_path,
105 ignore_vmlinux, 86 ignore_vmlinux,
87 ignore_vmlinux_buildid,
106 show_kernel_path, 88 show_kernel_path,
107 use_modules, 89 use_modules,
108 sort_by_name, 90 sort_by_name,
@@ -118,8 +100,10 @@ struct symbol_conf {
118 annotate_src, 100 annotate_src,
119 event_group, 101 event_group,
120 demangle, 102 demangle,
103 demangle_kernel,
121 filter_relative, 104 filter_relative,
122 show_hist_headers; 105 show_hist_headers,
106 branch_callstack;
123 const char *vmlinux_name, 107 const char *vmlinux_name,
124 *kallsyms_name, 108 *kallsyms_name,
125 *source_prefix, 109 *source_prefix,
@@ -143,6 +127,14 @@ struct symbol_conf {
143}; 127};
144 128
145extern struct symbol_conf symbol_conf; 129extern struct symbol_conf symbol_conf;
130
131static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
132{
133 return path__join(bf, size, symbol_conf.symfs, path);
134}
135
136#define symbol__join_symfs(bf, path) __symbol__join_symfs(bf, sizeof(bf), path)
137
146extern int vmlinux_path__nr_entries; 138extern int vmlinux_path__nr_entries;
147extern char **vmlinux_path; 139extern char **vmlinux_path;
148 140
@@ -253,7 +245,8 @@ int modules__parse(const char *filename, void *arg,
253int filename__read_debuglink(const char *filename, char *debuglink, 245int filename__read_debuglink(const char *filename, char *debuglink,
254 size_t size); 246 size_t size);
255 247
256int symbol__init(void); 248struct perf_session_env;
249int symbol__init(struct perf_session_env *env);
257void symbol__exit(void); 250void symbol__exit(void);
258void symbol__elf_init(void); 251void symbol__elf_init(void);
259struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 252struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
new file mode 100644
index 000000000000..9ed59a452d1f
--- /dev/null
+++ b/tools/perf/util/thread-stack.c
@@ -0,0 +1,747 @@
1/*
2 * thread-stack.c: Synthesize a thread's stack using call / return events
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <linux/rbtree.h>
17#include <linux/list.h>
18#include "thread.h"
19#include "event.h"
20#include "machine.h"
21#include "util.h"
22#include "debug.h"
23#include "symbol.h"
24#include "comm.h"
25#include "thread-stack.h"
26
27#define CALL_PATH_BLOCK_SHIFT 8
28#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
29#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
30
31struct call_path_block {
32 struct call_path cp[CALL_PATH_BLOCK_SIZE];
33 struct list_head node;
34};
35
36/**
37 * struct call_path_root - root of all call paths.
38 * @call_path: root call path
39 * @blocks: list of blocks to store call paths
40 * @next: next free space
41 * @sz: number of spaces
42 */
43struct call_path_root {
44 struct call_path call_path;
45 struct list_head blocks;
46 size_t next;
47 size_t sz;
48};
49
50/**
51 * struct call_return_processor - provides a call-back to consume call-return
52 * information.
53 * @cpr: call path root
54 * @process: call-back that accepts call/return information
55 * @data: anonymous data for call-back
56 */
57struct call_return_processor {
58 struct call_path_root *cpr;
59 int (*process)(struct call_return *cr, void *data);
60 void *data;
61};
62
63#define STACK_GROWTH 2048
64
65/**
66 * struct thread_stack_entry - thread stack entry.
67 * @ret_addr: return address
68 * @timestamp: timestamp (if known)
69 * @ref: external reference (e.g. db_id of sample)
70 * @branch_count: the branch count when the entry was created
71 * @cp: call path
72 * @no_call: a 'call' was not seen
73 */
74struct thread_stack_entry {
75 u64 ret_addr;
76 u64 timestamp;
77 u64 ref;
78 u64 branch_count;
79 struct call_path *cp;
80 bool no_call;
81};
82
83/**
84 * struct thread_stack - thread stack constructed from 'call' and 'return'
85 * branch samples.
86 * @stack: array that holds the stack
87 * @cnt: number of entries in the stack
88 * @sz: current maximum stack size
89 * @trace_nr: current trace number
90 * @branch_count: running branch count
91 * @kernel_start: kernel start address
92 * @last_time: last timestamp
93 * @crp: call/return processor
94 * @comm: current comm
95 */
96struct thread_stack {
97 struct thread_stack_entry *stack;
98 size_t cnt;
99 size_t sz;
100 u64 trace_nr;
101 u64 branch_count;
102 u64 kernel_start;
103 u64 last_time;
104 struct call_return_processor *crp;
105 struct comm *comm;
106};
107
108static int thread_stack__grow(struct thread_stack *ts)
109{
110 struct thread_stack_entry *new_stack;
111 size_t sz, new_sz;
112
113 new_sz = ts->sz + STACK_GROWTH;
114 sz = new_sz * sizeof(struct thread_stack_entry);
115
116 new_stack = realloc(ts->stack, sz);
117 if (!new_stack)
118 return -ENOMEM;
119
120 ts->stack = new_stack;
121 ts->sz = new_sz;
122
123 return 0;
124}
125
126static struct thread_stack *thread_stack__new(struct thread *thread,
127 struct call_return_processor *crp)
128{
129 struct thread_stack *ts;
130
131 ts = zalloc(sizeof(struct thread_stack));
132 if (!ts)
133 return NULL;
134
135 if (thread_stack__grow(ts)) {
136 free(ts);
137 return NULL;
138 }
139
140 if (thread->mg && thread->mg->machine)
141 ts->kernel_start = machine__kernel_start(thread->mg->machine);
142 else
143 ts->kernel_start = 1ULL << 63;
144 ts->crp = crp;
145
146 return ts;
147}
148
149static int thread_stack__push(struct thread_stack *ts, u64 ret_addr)
150{
151 int err = 0;
152
153 if (ts->cnt == ts->sz) {
154 err = thread_stack__grow(ts);
155 if (err) {
156 pr_warning("Out of memory: discarding thread stack\n");
157 ts->cnt = 0;
158 }
159 }
160
161 ts->stack[ts->cnt++].ret_addr = ret_addr;
162
163 return err;
164}
165
166static void thread_stack__pop(struct thread_stack *ts, u64 ret_addr)
167{
168 size_t i;
169
170 /*
171 * In some cases there may be functions which are not seen to return.
172 * For example when setjmp / longjmp has been used. Or the perf context
173 * switch in the kernel which doesn't stop and start tracing in exactly
174 * the same code path. When that happens the return address will be
175 * further down the stack. If the return address is not found at all,
176 * we assume the opposite (i.e. this is a return for a call that wasn't
177 * seen for some reason) and leave the stack alone.
178 */
179 for (i = ts->cnt; i; ) {
180 if (ts->stack[--i].ret_addr == ret_addr) {
181 ts->cnt = i;
182 return;
183 }
184 }
185}
186
187static bool thread_stack__in_kernel(struct thread_stack *ts)
188{
189 if (!ts->cnt)
190 return false;
191
192 return ts->stack[ts->cnt - 1].cp->in_kernel;
193}
194
195static int thread_stack__call_return(struct thread *thread,
196 struct thread_stack *ts, size_t idx,
197 u64 timestamp, u64 ref, bool no_return)
198{
199 struct call_return_processor *crp = ts->crp;
200 struct thread_stack_entry *tse;
201 struct call_return cr = {
202 .thread = thread,
203 .comm = ts->comm,
204 .db_id = 0,
205 };
206
207 tse = &ts->stack[idx];
208 cr.cp = tse->cp;
209 cr.call_time = tse->timestamp;
210 cr.return_time = timestamp;
211 cr.branch_count = ts->branch_count - tse->branch_count;
212 cr.call_ref = tse->ref;
213 cr.return_ref = ref;
214 if (tse->no_call)
215 cr.flags |= CALL_RETURN_NO_CALL;
216 if (no_return)
217 cr.flags |= CALL_RETURN_NO_RETURN;
218
219 return crp->process(&cr, crp->data);
220}
221
222static int thread_stack__flush(struct thread *thread, struct thread_stack *ts)
223{
224 struct call_return_processor *crp = ts->crp;
225 int err;
226
227 if (!crp) {
228 ts->cnt = 0;
229 return 0;
230 }
231
232 while (ts->cnt) {
233 err = thread_stack__call_return(thread, ts, --ts->cnt,
234 ts->last_time, 0, true);
235 if (err) {
236 pr_err("Error flushing thread stack!\n");
237 ts->cnt = 0;
238 return err;
239 }
240 }
241
242 return 0;
243}
244
245int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
246 u64 to_ip, u16 insn_len, u64 trace_nr)
247{
248 if (!thread)
249 return -EINVAL;
250
251 if (!thread->ts) {
252 thread->ts = thread_stack__new(thread, NULL);
253 if (!thread->ts) {
254 pr_warning("Out of memory: no thread stack\n");
255 return -ENOMEM;
256 }
257 thread->ts->trace_nr = trace_nr;
258 }
259
260 /*
261 * When the trace is discontinuous, the trace_nr changes. In that case
262 * the stack might be completely invalid. Better to report nothing than
263 * to report something misleading, so flush the stack.
264 */
265 if (trace_nr != thread->ts->trace_nr) {
266 if (thread->ts->trace_nr)
267 thread_stack__flush(thread, thread->ts);
268 thread->ts->trace_nr = trace_nr;
269 }
270
271 /* Stop here if thread_stack__process() is in use */
272 if (thread->ts->crp)
273 return 0;
274
275 if (flags & PERF_IP_FLAG_CALL) {
276 u64 ret_addr;
277
278 if (!to_ip)
279 return 0;
280 ret_addr = from_ip + insn_len;
281 if (ret_addr == to_ip)
282 return 0; /* Zero-length calls are excluded */
283 return thread_stack__push(thread->ts, ret_addr);
284 } else if (flags & PERF_IP_FLAG_RETURN) {
285 if (!from_ip)
286 return 0;
287 thread_stack__pop(thread->ts, to_ip);
288 }
289
290 return 0;
291}
292
293void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr)
294{
295 if (!thread || !thread->ts)
296 return;
297
298 if (trace_nr != thread->ts->trace_nr) {
299 if (thread->ts->trace_nr)
300 thread_stack__flush(thread, thread->ts);
301 thread->ts->trace_nr = trace_nr;
302 }
303}
304
305void thread_stack__free(struct thread *thread)
306{
307 if (thread->ts) {
308 thread_stack__flush(thread, thread->ts);
309 zfree(&thread->ts->stack);
310 zfree(&thread->ts);
311 }
312}
313
314void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
315 size_t sz, u64 ip)
316{
317 size_t i;
318
319 if (!thread || !thread->ts)
320 chain->nr = 1;
321 else
322 chain->nr = min(sz, thread->ts->cnt + 1);
323
324 chain->ips[0] = ip;
325
326 for (i = 1; i < chain->nr; i++)
327 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
328}
329
330static void call_path__init(struct call_path *cp, struct call_path *parent,
331 struct symbol *sym, u64 ip, bool in_kernel)
332{
333 cp->parent = parent;
334 cp->sym = sym;
335 cp->ip = sym ? 0 : ip;
336 cp->db_id = 0;
337 cp->in_kernel = in_kernel;
338 RB_CLEAR_NODE(&cp->rb_node);
339 cp->children = RB_ROOT;
340}
341
342static struct call_path_root *call_path_root__new(void)
343{
344 struct call_path_root *cpr;
345
346 cpr = zalloc(sizeof(struct call_path_root));
347 if (!cpr)
348 return NULL;
349 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
350 INIT_LIST_HEAD(&cpr->blocks);
351 return cpr;
352}
353
354static void call_path_root__free(struct call_path_root *cpr)
355{
356 struct call_path_block *pos, *n;
357
358 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
359 list_del(&pos->node);
360 free(pos);
361 }
362 free(cpr);
363}
364
365static struct call_path *call_path__new(struct call_path_root *cpr,
366 struct call_path *parent,
367 struct symbol *sym, u64 ip,
368 bool in_kernel)
369{
370 struct call_path_block *cpb;
371 struct call_path *cp;
372 size_t n;
373
374 if (cpr->next < cpr->sz) {
375 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
376 node);
377 } else {
378 cpb = zalloc(sizeof(struct call_path_block));
379 if (!cpb)
380 return NULL;
381 list_add_tail(&cpb->node, &cpr->blocks);
382 cpr->sz += CALL_PATH_BLOCK_SIZE;
383 }
384
385 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
386 cp = &cpb->cp[n];
387
388 call_path__init(cp, parent, sym, ip, in_kernel);
389
390 return cp;
391}
392
393static struct call_path *call_path__findnew(struct call_path_root *cpr,
394 struct call_path *parent,
395 struct symbol *sym, u64 ip, u64 ks)
396{
397 struct rb_node **p;
398 struct rb_node *node_parent = NULL;
399 struct call_path *cp;
400 bool in_kernel = ip >= ks;
401
402 if (sym)
403 ip = 0;
404
405 if (!parent)
406 return call_path__new(cpr, parent, sym, ip, in_kernel);
407
408 p = &parent->children.rb_node;
409 while (*p != NULL) {
410 node_parent = *p;
411 cp = rb_entry(node_parent, struct call_path, rb_node);
412
413 if (cp->sym == sym && cp->ip == ip)
414 return cp;
415
416 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
417 p = &(*p)->rb_left;
418 else
419 p = &(*p)->rb_right;
420 }
421
422 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
423 if (!cp)
424 return NULL;
425
426 rb_link_node(&cp->rb_node, node_parent, p);
427 rb_insert_color(&cp->rb_node, &parent->children);
428
429 return cp;
430}
431
432struct call_return_processor *
433call_return_processor__new(int (*process)(struct call_return *cr, void *data),
434 void *data)
435{
436 struct call_return_processor *crp;
437
438 crp = zalloc(sizeof(struct call_return_processor));
439 if (!crp)
440 return NULL;
441 crp->cpr = call_path_root__new();
442 if (!crp->cpr)
443 goto out_free;
444 crp->process = process;
445 crp->data = data;
446 return crp;
447
448out_free:
449 free(crp);
450 return NULL;
451}
452
453void call_return_processor__free(struct call_return_processor *crp)
454{
455 if (crp) {
456 call_path_root__free(crp->cpr);
457 free(crp);
458 }
459}
460
461static int thread_stack__push_cp(struct thread_stack *ts, u64 ret_addr,
462 u64 timestamp, u64 ref, struct call_path *cp,
463 bool no_call)
464{
465 struct thread_stack_entry *tse;
466 int err;
467
468 if (ts->cnt == ts->sz) {
469 err = thread_stack__grow(ts);
470 if (err)
471 return err;
472 }
473
474 tse = &ts->stack[ts->cnt++];
475 tse->ret_addr = ret_addr;
476 tse->timestamp = timestamp;
477 tse->ref = ref;
478 tse->branch_count = ts->branch_count;
479 tse->cp = cp;
480 tse->no_call = no_call;
481
482 return 0;
483}
484
485static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts,
486 u64 ret_addr, u64 timestamp, u64 ref,
487 struct symbol *sym)
488{
489 int err;
490
491 if (!ts->cnt)
492 return 1;
493
494 if (ts->cnt == 1) {
495 struct thread_stack_entry *tse = &ts->stack[0];
496
497 if (tse->cp->sym == sym)
498 return thread_stack__call_return(thread, ts, --ts->cnt,
499 timestamp, ref, false);
500 }
501
502 if (ts->stack[ts->cnt - 1].ret_addr == ret_addr) {
503 return thread_stack__call_return(thread, ts, --ts->cnt,
504 timestamp, ref, false);
505 } else {
506 size_t i = ts->cnt - 1;
507
508 while (i--) {
509 if (ts->stack[i].ret_addr != ret_addr)
510 continue;
511 i += 1;
512 while (ts->cnt > i) {
513 err = thread_stack__call_return(thread, ts,
514 --ts->cnt,
515 timestamp, ref,
516 true);
517 if (err)
518 return err;
519 }
520 return thread_stack__call_return(thread, ts, --ts->cnt,
521 timestamp, ref, false);
522 }
523 }
524
525 return 1;
526}
527
528static int thread_stack__bottom(struct thread *thread, struct thread_stack *ts,
529 struct perf_sample *sample,
530 struct addr_location *from_al,
531 struct addr_location *to_al, u64 ref)
532{
533 struct call_path_root *cpr = ts->crp->cpr;
534 struct call_path *cp;
535 struct symbol *sym;
536 u64 ip;
537
538 if (sample->ip) {
539 ip = sample->ip;
540 sym = from_al->sym;
541 } else if (sample->addr) {
542 ip = sample->addr;
543 sym = to_al->sym;
544 } else {
545 return 0;
546 }
547
548 cp = call_path__findnew(cpr, &cpr->call_path, sym, ip,
549 ts->kernel_start);
550 if (!cp)
551 return -ENOMEM;
552
553 return thread_stack__push_cp(thread->ts, ip, sample->time, ref, cp,
554 true);
555}
556
557static int thread_stack__no_call_return(struct thread *thread,
558 struct thread_stack *ts,
559 struct perf_sample *sample,
560 struct addr_location *from_al,
561 struct addr_location *to_al, u64 ref)
562{
563 struct call_path_root *cpr = ts->crp->cpr;
564 struct call_path *cp, *parent;
565 u64 ks = ts->kernel_start;
566 int err;
567
568 if (sample->ip >= ks && sample->addr < ks) {
569 /* Return to userspace, so pop all kernel addresses */
570 while (thread_stack__in_kernel(ts)) {
571 err = thread_stack__call_return(thread, ts, --ts->cnt,
572 sample->time, ref,
573 true);
574 if (err)
575 return err;
576 }
577
578 /* If the stack is empty, push the userspace address */
579 if (!ts->cnt) {
580 cp = call_path__findnew(cpr, &cpr->call_path,
581 to_al->sym, sample->addr,
582 ts->kernel_start);
583 if (!cp)
584 return -ENOMEM;
585 return thread_stack__push_cp(ts, 0, sample->time, ref,
586 cp, true);
587 }
588 } else if (thread_stack__in_kernel(ts) && sample->ip < ks) {
589 /* Return to userspace, so pop all kernel addresses */
590 while (thread_stack__in_kernel(ts)) {
591 err = thread_stack__call_return(thread, ts, --ts->cnt,
592 sample->time, ref,
593 true);
594 if (err)
595 return err;
596 }
597 }
598
599 if (ts->cnt)
600 parent = ts->stack[ts->cnt - 1].cp;
601 else
602 parent = &cpr->call_path;
603
604 /* This 'return' had no 'call', so push and pop top of stack */
605 cp = call_path__findnew(cpr, parent, from_al->sym, sample->ip,
606 ts->kernel_start);
607 if (!cp)
608 return -ENOMEM;
609
610 err = thread_stack__push_cp(ts, sample->addr, sample->time, ref, cp,
611 true);
612 if (err)
613 return err;
614
615 return thread_stack__pop_cp(thread, ts, sample->addr, sample->time, ref,
616 to_al->sym);
617}
618
619static int thread_stack__trace_begin(struct thread *thread,
620 struct thread_stack *ts, u64 timestamp,
621 u64 ref)
622{
623 struct thread_stack_entry *tse;
624 int err;
625
626 if (!ts->cnt)
627 return 0;
628
629 /* Pop trace end */
630 tse = &ts->stack[ts->cnt - 1];
631 if (tse->cp->sym == NULL && tse->cp->ip == 0) {
632 err = thread_stack__call_return(thread, ts, --ts->cnt,
633 timestamp, ref, false);
634 if (err)
635 return err;
636 }
637
638 return 0;
639}
640
641static int thread_stack__trace_end(struct thread_stack *ts,
642 struct perf_sample *sample, u64 ref)
643{
644 struct call_path_root *cpr = ts->crp->cpr;
645 struct call_path *cp;
646 u64 ret_addr;
647
648 /* No point having 'trace end' on the bottom of the stack */
649 if (!ts->cnt || (ts->cnt == 1 && ts->stack[0].ref == ref))
650 return 0;
651
652 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp, NULL, 0,
653 ts->kernel_start);
654 if (!cp)
655 return -ENOMEM;
656
657 ret_addr = sample->ip + sample->insn_len;
658
659 return thread_stack__push_cp(ts, ret_addr, sample->time, ref, cp,
660 false);
661}
662
663int thread_stack__process(struct thread *thread, struct comm *comm,
664 struct perf_sample *sample,
665 struct addr_location *from_al,
666 struct addr_location *to_al, u64 ref,
667 struct call_return_processor *crp)
668{
669 struct thread_stack *ts = thread->ts;
670 int err = 0;
671
672 if (ts) {
673 if (!ts->crp) {
674 /* Supersede thread_stack__event() */
675 thread_stack__free(thread);
676 thread->ts = thread_stack__new(thread, crp);
677 if (!thread->ts)
678 return -ENOMEM;
679 ts = thread->ts;
680 ts->comm = comm;
681 }
682 } else {
683 thread->ts = thread_stack__new(thread, crp);
684 if (!thread->ts)
685 return -ENOMEM;
686 ts = thread->ts;
687 ts->comm = comm;
688 }
689
690 /* Flush stack on exec */
691 if (ts->comm != comm && thread->pid_ == thread->tid) {
692 err = thread_stack__flush(thread, ts);
693 if (err)
694 return err;
695 ts->comm = comm;
696 }
697
698 /* If the stack is empty, put the current symbol on the stack */
699 if (!ts->cnt) {
700 err = thread_stack__bottom(thread, ts, sample, from_al, to_al,
701 ref);
702 if (err)
703 return err;
704 }
705
706 ts->branch_count += 1;
707 ts->last_time = sample->time;
708
709 if (sample->flags & PERF_IP_FLAG_CALL) {
710 struct call_path_root *cpr = ts->crp->cpr;
711 struct call_path *cp;
712 u64 ret_addr;
713
714 if (!sample->ip || !sample->addr)
715 return 0;
716
717 ret_addr = sample->ip + sample->insn_len;
718 if (ret_addr == sample->addr)
719 return 0; /* Zero-length calls are excluded */
720
721 cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp,
722 to_al->sym, sample->addr,
723 ts->kernel_start);
724 if (!cp)
725 return -ENOMEM;
726 err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
727 cp, false);
728 } else if (sample->flags & PERF_IP_FLAG_RETURN) {
729 if (!sample->ip || !sample->addr)
730 return 0;
731
732 err = thread_stack__pop_cp(thread, ts, sample->addr,
733 sample->time, ref, from_al->sym);
734 if (err) {
735 if (err < 0)
736 return err;
737 err = thread_stack__no_call_return(thread, ts, sample,
738 from_al, to_al, ref);
739 }
740 } else if (sample->flags & PERF_IP_FLAG_TRACE_BEGIN) {
741 err = thread_stack__trace_begin(thread, ts, sample->time, ref);
742 } else if (sample->flags & PERF_IP_FLAG_TRACE_END) {
743 err = thread_stack__trace_end(ts, sample, ref);
744 }
745
746 return err;
747}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
new file mode 100644
index 000000000000..b843bbef8ba2
--- /dev/null
+++ b/tools/perf/util/thread-stack.h
@@ -0,0 +1,111 @@
1/*
2 * thread-stack.h: Synthesize a thread's stack using call / return events
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_THREAD_STACK_H
17#define __PERF_THREAD_STACK_H
18
19#include <sys/types.h>
20
21#include <linux/types.h>
22#include <linux/rbtree.h>
23
24struct thread;
25struct comm;
26struct ip_callchain;
27struct symbol;
28struct dso;
29struct call_return_processor;
30struct comm;
31struct perf_sample;
32struct addr_location;
33
34/*
35 * Call/Return flags.
36 *
37 * CALL_RETURN_NO_CALL: 'return' but no matching 'call'
38 * CALL_RETURN_NO_RETURN: 'call' but no matching 'return'
39 */
40enum {
41 CALL_RETURN_NO_CALL = 1 << 0,
42 CALL_RETURN_NO_RETURN = 1 << 1,
43};
44
45/**
46 * struct call_return - paired call/return information.
47 * @thread: thread in which call/return occurred
48 * @comm: comm in which call/return occurred
49 * @cp: call path
50 * @call_time: timestamp of call (if known)
51 * @return_time: timestamp of return (if known)
52 * @branch_count: number of branches seen between call and return
53 * @call_ref: external reference to 'call' sample (e.g. db_id)
54 * @return_ref: external reference to 'return' sample (e.g. db_id)
55 * @db_id: id used for db-export
56 * @flags: Call/Return flags
57 */
58struct call_return {
59 struct thread *thread;
60 struct comm *comm;
61 struct call_path *cp;
62 u64 call_time;
63 u64 return_time;
64 u64 branch_count;
65 u64 call_ref;
66 u64 return_ref;
67 u64 db_id;
68 u32 flags;
69};
70
71/**
72 * struct call_path - node in list of calls leading to a function call.
73 * @parent: call path to the parent function call
74 * @sym: symbol of function called
75 * @ip: only if sym is null, the ip of the function
76 * @db_id: id used for db-export
77 * @in_kernel: whether function is a in the kernel
78 * @rb_node: node in parent's tree of called functions
79 * @children: tree of call paths of functions called
80 *
81 * In combination with the call_return structure, the call_path structure
82 * defines a context-sensitve call-graph.
83 */
84struct call_path {
85 struct call_path *parent;
86 struct symbol *sym;
87 u64 ip;
88 u64 db_id;
89 bool in_kernel;
90 struct rb_node rb_node;
91 struct rb_root children;
92};
93
94int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
95 u64 to_ip, u16 insn_len, u64 trace_nr);
96void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);
97void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
98 size_t sz, u64 ip);
99void thread_stack__free(struct thread *thread);
100
101struct call_return_processor *
102call_return_processor__new(int (*process)(struct call_return *cr, void *data),
103 void *data);
104void call_return_processor__free(struct call_return_processor *crp);
105int thread_stack__process(struct thread *thread, struct comm *comm,
106 struct perf_sample *sample,
107 struct addr_location *from_al,
108 struct addr_location *to_al, u64 ref,
109 struct call_return_processor *crp);
110
111#endif
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 12c7a253a63c..9ebc8b1f9be5 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -4,9 +4,11 @@
4#include <string.h> 4#include <string.h>
5#include "session.h" 5#include "session.h"
6#include "thread.h" 6#include "thread.h"
7#include "thread-stack.h"
7#include "util.h" 8#include "util.h"
8#include "debug.h" 9#include "debug.h"
9#include "comm.h" 10#include "comm.h"
11#include "unwind.h"
10 12
11int thread__init_map_groups(struct thread *thread, struct machine *machine) 13int thread__init_map_groups(struct thread *thread, struct machine *machine)
12{ 14{
@@ -14,7 +16,7 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine)
14 pid_t pid = thread->pid_; 16 pid_t pid = thread->pid_;
15 17
16 if (pid == thread->tid || pid == -1) { 18 if (pid == thread->tid || pid == -1) {
17 thread->mg = map_groups__new(); 19 thread->mg = map_groups__new(machine);
18 } else { 20 } else {
19 leader = machine__findnew_thread(machine, pid, pid); 21 leader = machine__findnew_thread(machine, pid, pid);
20 if (leader) 22 if (leader)
@@ -37,17 +39,21 @@ struct thread *thread__new(pid_t pid, pid_t tid)
37 thread->cpu = -1; 39 thread->cpu = -1;
38 INIT_LIST_HEAD(&thread->comm_list); 40 INIT_LIST_HEAD(&thread->comm_list);
39 41
42 if (unwind__prepare_access(thread) < 0)
43 goto err_thread;
44
40 comm_str = malloc(32); 45 comm_str = malloc(32);
41 if (!comm_str) 46 if (!comm_str)
42 goto err_thread; 47 goto err_thread;
43 48
44 snprintf(comm_str, 32, ":%d", tid); 49 snprintf(comm_str, 32, ":%d", tid);
45 comm = comm__new(comm_str, 0); 50 comm = comm__new(comm_str, 0, false);
46 free(comm_str); 51 free(comm_str);
47 if (!comm) 52 if (!comm)
48 goto err_thread; 53 goto err_thread;
49 54
50 list_add(&comm->list, &thread->comm_list); 55 list_add(&comm->list, &thread->comm_list);
56
51 } 57 }
52 58
53 return thread; 59 return thread;
@@ -61,6 +67,8 @@ void thread__delete(struct thread *thread)
61{ 67{
62 struct comm *comm, *tmp; 68 struct comm *comm, *tmp;
63 69
70 thread_stack__free(thread);
71
64 if (thread->mg) { 72 if (thread->mg) {
65 map_groups__put(thread->mg); 73 map_groups__put(thread->mg);
66 thread->mg = NULL; 74 thread->mg = NULL;
@@ -69,6 +77,7 @@ void thread__delete(struct thread *thread)
69 list_del(&comm->list); 77 list_del(&comm->list);
70 comm__free(comm); 78 comm__free(comm);
71 } 79 }
80 unwind__finish_access(thread);
72 81
73 free(thread); 82 free(thread);
74} 83}
@@ -81,22 +90,38 @@ struct comm *thread__comm(const struct thread *thread)
81 return list_first_entry(&thread->comm_list, struct comm, list); 90 return list_first_entry(&thread->comm_list, struct comm, list);
82} 91}
83 92
84/* CHECKME: time should always be 0 if event aren't ordered */ 93struct comm *thread__exec_comm(const struct thread *thread)
85int thread__set_comm(struct thread *thread, const char *str, u64 timestamp) 94{
95 struct comm *comm, *last = NULL;
96
97 list_for_each_entry(comm, &thread->comm_list, list) {
98 if (comm->exec)
99 return comm;
100 last = comm;
101 }
102
103 return last;
104}
105
106int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
107 bool exec)
86{ 108{
87 struct comm *new, *curr = thread__comm(thread); 109 struct comm *new, *curr = thread__comm(thread);
88 int err; 110 int err;
89 111
90 /* Override latest entry if it had no specific time coverage */ 112 /* Override the default :tid entry */
91 if (!curr->start) { 113 if (!thread->comm_set) {
92 err = comm__override(curr, str, timestamp); 114 err = comm__override(curr, str, timestamp, exec);
93 if (err) 115 if (err)
94 return err; 116 return err;
95 } else { 117 } else {
96 new = comm__new(str, timestamp); 118 new = comm__new(str, timestamp, exec);
97 if (!new) 119 if (!new)
98 return -ENOMEM; 120 return -ENOMEM;
99 list_add(&new->list, &thread->comm_list); 121 list_add(&new->list, &thread->comm_list);
122
123 if (exec)
124 unwind__flush_access(thread);
100 } 125 }
101 126
102 thread->comm_set = true; 127 thread->comm_set = true;
@@ -175,7 +200,6 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
175} 200}
176 201
177void thread__find_cpumode_addr_location(struct thread *thread, 202void thread__find_cpumode_addr_location(struct thread *thread,
178 struct machine *machine,
179 enum map_type type, u64 addr, 203 enum map_type type, u64 addr,
180 struct addr_location *al) 204 struct addr_location *al)
181{ 205{
@@ -188,8 +212,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
188 }; 212 };
189 213
190 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) { 214 for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
191 thread__find_addr_location(thread, machine, cpumodes[i], type, 215 thread__find_addr_location(thread, cpumodes[i], type, addr, al);
192 addr, al);
193 if (al->map) 216 if (al->map)
194 break; 217 break;
195 } 218 }
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 716b7723cce2..160fd066a7d1 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -8,6 +8,8 @@
8#include "symbol.h" 8#include "symbol.h"
9#include <strlist.h> 9#include <strlist.h>
10 10
11struct thread_stack;
12
11struct thread { 13struct thread {
12 union { 14 union {
13 struct rb_node rb_node; 15 struct rb_node rb_node;
@@ -23,8 +25,10 @@ struct thread {
23 bool dead; /* if set thread has exited */ 25 bool dead; /* if set thread has exited */
24 struct list_head comm_list; 26 struct list_head comm_list;
25 int comm_len; 27 int comm_len;
28 u64 db_id;
26 29
27 void *priv; 30 void *priv;
31 struct thread_stack *ts;
28}; 32};
29 33
30struct machine; 34struct machine;
@@ -38,24 +42,31 @@ static inline void thread__exited(struct thread *thread)
38 thread->dead = true; 42 thread->dead = true;
39} 43}
40 44
41int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp); 45int __thread__set_comm(struct thread *thread, const char *comm, u64 timestamp,
46 bool exec);
47static inline int thread__set_comm(struct thread *thread, const char *comm,
48 u64 timestamp)
49{
50 return __thread__set_comm(thread, comm, timestamp, false);
51}
52
42int thread__comm_len(struct thread *thread); 53int thread__comm_len(struct thread *thread);
43struct comm *thread__comm(const struct thread *thread); 54struct comm *thread__comm(const struct thread *thread);
55struct comm *thread__exec_comm(const struct thread *thread);
44const char *thread__comm_str(const struct thread *thread); 56const char *thread__comm_str(const struct thread *thread);
45void thread__insert_map(struct thread *thread, struct map *map); 57void thread__insert_map(struct thread *thread, struct map *map);
46int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 58int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
47size_t thread__fprintf(struct thread *thread, FILE *fp); 59size_t thread__fprintf(struct thread *thread, FILE *fp);
48 60
49void thread__find_addr_map(struct thread *thread, struct machine *machine, 61void thread__find_addr_map(struct thread *thread,
50 u8 cpumode, enum map_type type, u64 addr, 62 u8 cpumode, enum map_type type, u64 addr,
51 struct addr_location *al); 63 struct addr_location *al);
52 64
53void thread__find_addr_location(struct thread *thread, struct machine *machine, 65void thread__find_addr_location(struct thread *thread,
54 u8 cpumode, enum map_type type, u64 addr, 66 u8 cpumode, enum map_type type, u64 addr,
55 struct addr_location *al); 67 struct addr_location *al);
56 68
57void thread__find_cpumode_addr_location(struct thread *thread, 69void thread__find_cpumode_addr_location(struct thread *thread,
58 struct machine *machine,
59 enum map_type type, u64 addr, 70 enum map_type type, u64 addr,
60 struct addr_location *al); 71 struct addr_location *al);
61 72
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 5d3215912105..f93b9734735b 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -214,6 +214,17 @@ out_free_threads:
214 goto out; 214 goto out;
215} 215}
216 216
217struct thread_map *thread_map__new_dummy(void)
218{
219 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
220
221 if (threads != NULL) {
222 threads->map[0] = -1;
223 threads->nr = 1;
224 }
225 return threads;
226}
227
217static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 228static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
218{ 229{
219 struct thread_map *threads = NULL, *nt; 230 struct thread_map *threads = NULL, *nt;
@@ -224,14 +235,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
224 struct strlist *slist; 235 struct strlist *slist;
225 236
226 /* perf-stat expects threads to be generated even if tid not given */ 237 /* perf-stat expects threads to be generated even if tid not given */
227 if (!tid_str) { 238 if (!tid_str)
228 threads = malloc(sizeof(*threads) + sizeof(pid_t)); 239 return thread_map__new_dummy();
229 if (threads != NULL) {
230 threads->map[0] = -1;
231 threads->nr = 1;
232 }
233 return threads;
234 }
235 240
236 slist = strlist__new(false, tid_str); 241 slist = strlist__new(false, tid_str);
237 if (!slist) 242 if (!slist)
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 0cd8b3108084..95313f43cc0f 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -9,6 +9,7 @@ struct thread_map {
9 pid_t map[]; 9 pid_t map[];
10}; 10};
11 11
12struct thread_map *thread_map__new_dummy(void);
12struct thread_map *thread_map__new_by_pid(pid_t pid); 13struct thread_map *thread_map__new_by_pid(pid_t pid);
13struct thread_map *thread_map__new_by_tid(pid_t tid); 14struct thread_map *thread_map__new_by_tid(pid_t tid);
14struct thread_map *thread_map__new_by_uid(uid_t uid); 15struct thread_map *thread_map__new_by_uid(uid_t uid);
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 4385816d3d49..bb2708bbfaca 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -39,8 +39,9 @@ struct perf_tool {
39 event_attr_op attr; 39 event_attr_op attr;
40 event_op2 tracing_data; 40 event_op2 tracing_data;
41 event_op2 finished_round, 41 event_op2 finished_round,
42 build_id; 42 build_id,
43 bool ordered_samples; 43 id_index;
44 bool ordered_events;
44 bool ordering_requires_timestamps; 45 bool ordering_requires_timestamps;
45}; 46};
46 47
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index 57aaccc1692e..5c9bdd1591a9 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -30,6 +30,11 @@
30 30
31struct scripting_context *scripting_context; 31struct scripting_context *scripting_context;
32 32
33static int flush_script_unsupported(void)
34{
35 return 0;
36}
37
33static int stop_script_unsupported(void) 38static int stop_script_unsupported(void)
34{ 39{
35 return 0; 40 return 0;
@@ -74,6 +79,7 @@ static int python_generate_script_unsupported(struct pevent *pevent
74struct scripting_ops python_scripting_unsupported_ops = { 79struct scripting_ops python_scripting_unsupported_ops = {
75 .name = "Python", 80 .name = "Python",
76 .start_script = python_start_script_unsupported, 81 .start_script = python_start_script_unsupported,
82 .flush_script = flush_script_unsupported,
77 .stop_script = stop_script_unsupported, 83 .stop_script = stop_script_unsupported,
78 .process_event = process_event_unsupported, 84 .process_event = process_event_unsupported,
79 .generate_script = python_generate_script_unsupported, 85 .generate_script = python_generate_script_unsupported,
@@ -137,6 +143,7 @@ static int perl_generate_script_unsupported(struct pevent *pevent
137struct scripting_ops perl_scripting_unsupported_ops = { 143struct scripting_ops perl_scripting_unsupported_ops = {
138 .name = "Perl", 144 .name = "Perl",
139 .start_script = perl_start_script_unsupported, 145 .start_script = perl_start_script_unsupported,
146 .flush_script = flush_script_unsupported,
140 .stop_script = stop_script_unsupported, 147 .stop_script = stop_script_unsupported,
141 .process_event = process_event_unsupported, 148 .process_event = process_event_unsupported,
142 .generate_script = perl_generate_script_unsupported, 149 .generate_script = perl_generate_script_unsupported,
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index 7b6d68688327..52aaa19e1eb1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -64,6 +64,7 @@ struct perf_session;
64struct scripting_ops { 64struct scripting_ops {
65 const char *name; 65 const char *name;
66 int (*start_script) (const char *script, int argc, const char **argv); 66 int (*start_script) (const char *script, int argc, const char **argv);
67 int (*flush_script) (void);
67 int (*stop_script) (void); 68 int (*stop_script) (void);
68 void (*process_event) (union perf_event *event, 69 void (*process_event) (union perf_event *event,
69 struct perf_sample *sample, 70 struct perf_sample *sample,
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index 7419768c38b1..2dcfe9a7c8d0 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -26,7 +26,7 @@ static int __report_module(struct addr_location *al, u64 ip,
26 Dwfl_Module *mod; 26 Dwfl_Module *mod;
27 struct dso *dso = NULL; 27 struct dso *dso = NULL;
28 28
29 thread__find_addr_location(ui->thread, ui->machine, 29 thread__find_addr_location(ui->thread,
30 PERF_RECORD_MISC_USER, 30 PERF_RECORD_MISC_USER,
31 MAP__FUNCTION, ip, al); 31 MAP__FUNCTION, ip, al);
32 32
@@ -89,7 +89,7 @@ static int access_dso_mem(struct unwind_info *ui, Dwarf_Addr addr,
89 struct addr_location al; 89 struct addr_location al;
90 ssize_t size; 90 ssize_t size;
91 91
92 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 92 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
93 MAP__FUNCTION, addr, &al); 93 MAP__FUNCTION, addr, &al);
94 if (!al.map) { 94 if (!al.map) {
95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 95 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -164,14 +164,14 @@ frame_callback(Dwfl_Frame *state, void *arg)
164} 164}
165 165
166int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 166int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
167 struct machine *machine, struct thread *thread, 167 struct thread *thread,
168 struct perf_sample *data, 168 struct perf_sample *data,
169 int max_stack) 169 int max_stack)
170{ 170{
171 struct unwind_info ui = { 171 struct unwind_info ui = {
172 .sample = data, 172 .sample = data,
173 .thread = thread, 173 .thread = thread,
174 .machine = machine, 174 .machine = thread->mg->machine,
175 .cb = cb, 175 .cb = cb,
176 .arg = arg, 176 .arg = arg,
177 .max_stack = max_stack, 177 .max_stack = max_stack,
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 92b56db52471..371219a6daf1 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -24,6 +24,7 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <libunwind.h> 25#include <libunwind.h>
26#include <libunwind-ptrace.h> 26#include <libunwind-ptrace.h>
27#include "callchain.h"
27#include "thread.h" 28#include "thread.h"
28#include "session.h" 29#include "session.h"
29#include "perf_regs.h" 30#include "perf_regs.h"
@@ -283,7 +284,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
283{ 284{
284 struct addr_location al; 285 struct addr_location al;
285 286
286 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 287 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
287 MAP__FUNCTION, ip, &al); 288 MAP__FUNCTION, ip, &al);
288 return al.map; 289 return al.map;
289} 290}
@@ -373,7 +374,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
373 struct addr_location al; 374 struct addr_location al;
374 ssize_t size; 375 ssize_t size;
375 376
376 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 377 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
377 MAP__FUNCTION, addr, &al); 378 MAP__FUNCTION, addr, &al);
378 if (!al.map) { 379 if (!al.map) {
379 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 380 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
@@ -475,14 +476,13 @@ static void put_unwind_info(unw_addr_space_t __maybe_unused as,
475 pr_debug("unwind: put_unwind_info called\n"); 476 pr_debug("unwind: put_unwind_info called\n");
476} 477}
477 478
478static int entry(u64 ip, struct thread *thread, struct machine *machine, 479static int entry(u64 ip, struct thread *thread,
479 unwind_entry_cb_t cb, void *arg) 480 unwind_entry_cb_t cb, void *arg)
480{ 481{
481 struct unwind_entry e; 482 struct unwind_entry e;
482 struct addr_location al; 483 struct addr_location al;
483 484
484 thread__find_addr_location(thread, machine, 485 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
485 PERF_RECORD_MISC_USER,
486 MAP__FUNCTION, ip, &al); 486 MAP__FUNCTION, ip, &al);
487 487
488 e.ip = ip; 488 e.ip = ip;
@@ -525,12 +525,12 @@ static unw_accessors_t accessors = {
525 .get_proc_name = get_proc_name, 525 .get_proc_name = get_proc_name,
526}; 526};
527 527
528static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, 528int unwind__prepare_access(struct thread *thread)
529 void *arg, int max_stack)
530{ 529{
531 unw_addr_space_t addr_space; 530 unw_addr_space_t addr_space;
532 unw_cursor_t c; 531
533 int ret; 532 if (callchain_param.record_mode != CALLCHAIN_DWARF)
533 return 0;
534 534
535 addr_space = unw_create_addr_space(&accessors, 0); 535 addr_space = unw_create_addr_space(&accessors, 0);
536 if (!addr_space) { 536 if (!addr_space) {
@@ -538,6 +538,45 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
538 return -ENOMEM; 538 return -ENOMEM;
539 } 539 }
540 540
541 unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
542 thread__set_priv(thread, addr_space);
543
544 return 0;
545}
546
547void unwind__flush_access(struct thread *thread)
548{
549 unw_addr_space_t addr_space;
550
551 if (callchain_param.record_mode != CALLCHAIN_DWARF)
552 return;
553
554 addr_space = thread__priv(thread);
555 unw_flush_cache(addr_space, 0, 0);
556}
557
558void unwind__finish_access(struct thread *thread)
559{
560 unw_addr_space_t addr_space;
561
562 if (callchain_param.record_mode != CALLCHAIN_DWARF)
563 return;
564
565 addr_space = thread__priv(thread);
566 unw_destroy_addr_space(addr_space);
567}
568
569static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
570 void *arg, int max_stack)
571{
572 unw_addr_space_t addr_space;
573 unw_cursor_t c;
574 int ret;
575
576 addr_space = thread__priv(ui->thread);
577 if (addr_space == NULL)
578 return -1;
579
541 ret = unw_init_remote(&c, addr_space, ui); 580 ret = unw_init_remote(&c, addr_space, ui);
542 if (ret) 581 if (ret)
543 display_error(ret); 582 display_error(ret);
@@ -546,22 +585,21 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
546 unw_word_t ip; 585 unw_word_t ip;
547 586
548 unw_get_reg(&c, UNW_REG_IP, &ip); 587 unw_get_reg(&c, UNW_REG_IP, &ip);
549 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; 588 ret = ip ? entry(ip, ui->thread, cb, arg) : 0;
550 } 589 }
551 590
552 unw_destroy_addr_space(addr_space);
553 return ret; 591 return ret;
554} 592}
555 593
556int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 594int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
557 struct machine *machine, struct thread *thread, 595 struct thread *thread,
558 struct perf_sample *data, int max_stack) 596 struct perf_sample *data, int max_stack)
559{ 597{
560 u64 ip; 598 u64 ip;
561 struct unwind_info ui = { 599 struct unwind_info ui = {
562 .sample = data, 600 .sample = data,
563 .thread = thread, 601 .thread = thread,
564 .machine = machine, 602 .machine = thread->mg->machine,
565 }; 603 };
566 int ret; 604 int ret;
567 605
@@ -572,7 +610,7 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
572 if (ret) 610 if (ret)
573 return ret; 611 return ret;
574 612
575 ret = entry(ip, thread, machine, cb, arg); 613 ret = entry(ip, thread, cb, arg);
576 if (ret) 614 if (ret)
577 return -ENOMEM; 615 return -ENOMEM;
578 616
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index f03061260b4e..12790cf94618 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -4,6 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include "event.h" 5#include "event.h"
6#include "symbol.h" 6#include "symbol.h"
7#include "thread.h"
7 8
8struct unwind_entry { 9struct unwind_entry {
9 struct map *map; 10 struct map *map;
@@ -15,23 +16,40 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
15 16
16#ifdef HAVE_DWARF_UNWIND_SUPPORT 17#ifdef HAVE_DWARF_UNWIND_SUPPORT
17int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 18int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
18 struct machine *machine,
19 struct thread *thread, 19 struct thread *thread,
20 struct perf_sample *data, int max_stack); 20 struct perf_sample *data, int max_stack);
21/* libunwind specific */ 21/* libunwind specific */
22#ifdef HAVE_LIBUNWIND_SUPPORT 22#ifdef HAVE_LIBUNWIND_SUPPORT
23int libunwind__arch_reg_id(int regnum); 23int libunwind__arch_reg_id(int regnum);
24int unwind__prepare_access(struct thread *thread);
25void unwind__flush_access(struct thread *thread);
26void unwind__finish_access(struct thread *thread);
27#else
28static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
29{
30 return 0;
31}
32
33static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
34static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
24#endif 35#endif
25#else 36#else
26static inline int 37static inline int
27unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, 38unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
28 void *arg __maybe_unused, 39 void *arg __maybe_unused,
29 struct machine *machine __maybe_unused,
30 struct thread *thread __maybe_unused, 40 struct thread *thread __maybe_unused,
31 struct perf_sample *data __maybe_unused, 41 struct perf_sample *data __maybe_unused,
32 int max_stack __maybe_unused) 42 int max_stack __maybe_unused)
33{ 43{
34 return 0; 44 return 0;
35} 45}
46
47static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
48{
49 return 0;
50}
51
52static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
53static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
36#endif /* HAVE_DWARF_UNWIND_SUPPORT */ 54#endif /* HAVE_DWARF_UNWIND_SUPPORT */
37#endif /* __UNWIND_H */ 55#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index e52e7461911b..b86744f29eef 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -13,6 +13,15 @@
13#include <limits.h> 13#include <limits.h>
14#include <byteswap.h> 14#include <byteswap.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <unistd.h>
17#include "callchain.h"
18
19struct callchain_param callchain_param = {
20 .mode = CHAIN_GRAPH_REL,
21 .min_percent = 0.5,
22 .order = ORDER_CALLEE,
23 .key = CCKEY_FUNCTION
24};
16 25
17/* 26/*
18 * XXX We need to find a better place for these things... 27 * XXX We need to find a better place for these things...
@@ -282,6 +291,18 @@ void get_term_dimensions(struct winsize *ws)
282 ws->ws_col = 80; 291 ws->ws_col = 80;
283} 292}
284 293
294void set_term_quiet_input(struct termios *old)
295{
296 struct termios tc;
297
298 tcgetattr(0, old);
299 tc = *old;
300 tc.c_lflag &= ~(ICANON | ECHO);
301 tc.c_cc[VMIN] = 0;
302 tc.c_cc[VTIME] = 0;
303 tcsetattr(0, TCSANOW, &tc);
304}
305
285static void set_tracing_events_path(const char *mountpoint) 306static void set_tracing_events_path(const char *mountpoint)
286{ 307{
287 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s", 308 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
@@ -421,28 +442,12 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
421 return (unsigned long) -1; 442 return (unsigned long) -1;
422} 443}
423 444
424int filename__read_int(const char *filename, int *value)
425{
426 char line[64];
427 int fd = open(filename, O_RDONLY), err = -1;
428
429 if (fd < 0)
430 return -1;
431
432 if (read(fd, line, sizeof(line)) > 0) {
433 *value = atoi(line);
434 err = 0;
435 }
436
437 close(fd);
438 return err;
439}
440
441int filename__read_str(const char *filename, char **buf, size_t *sizep) 445int filename__read_str(const char *filename, char **buf, size_t *sizep)
442{ 446{
443 size_t size = 0, alloc_size = 0; 447 size_t size = 0, alloc_size = 0;
444 void *bf = NULL, *nbf; 448 void *bf = NULL, *nbf;
445 int fd, n, err = 0; 449 int fd, n, err = 0;
450 char sbuf[STRERR_BUFSIZE];
446 451
447 fd = open(filename, O_RDONLY); 452 fd = open(filename, O_RDONLY);
448 if (fd < 0) 453 if (fd < 0)
@@ -463,8 +468,8 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep)
463 n = read(fd, bf + size, alloc_size - size); 468 n = read(fd, bf + size, alloc_size - size);
464 if (n < 0) { 469 if (n < 0) {
465 if (size) { 470 if (size) {
466 pr_warning("read failed %d: %s\n", 471 pr_warning("read failed %d: %s\n", errno,
467 errno, strerror(errno)); 472 strerror_r(errno, sbuf, sizeof(sbuf)));
468 err = 0; 473 err = 0;
469 } else 474 } else
470 err = -errno; 475 err = -errno;
@@ -501,16 +506,9 @@ const char *get_filename_for_perf_kvm(void)
501 506
502int perf_event_paranoid(void) 507int perf_event_paranoid(void)
503{ 508{
504 char path[PATH_MAX];
505 const char *procfs = procfs__mountpoint();
506 int value; 509 int value;
507 510
508 if (!procfs) 511 if (sysctl__read_int("kernel/perf_event_paranoid", &value))
509 return INT_MAX;
510
511 scnprintf(path, PATH_MAX, "%s/sys/kernel/perf_event_paranoid", procfs);
512
513 if (filename__read_int(path, &value))
514 return INT_MAX; 512 return INT_MAX;
515 513
516 return value; 514 return value;
@@ -536,3 +534,39 @@ void mem_bswap_64(void *src, int byte_size)
536 ++m; 534 ++m;
537 } 535 }
538} 536}
537
538bool find_process(const char *name)
539{
540 size_t len = strlen(name);
541 DIR *dir;
542 struct dirent *d;
543 int ret = -1;
544
545 dir = opendir(procfs__mountpoint());
546 if (!dir)
547 return -1;
548
549 /* Walk through the directory. */
550 while (ret && (d = readdir(dir)) != NULL) {
551 char path[PATH_MAX];
552 char *data;
553 size_t size;
554
555 if ((d->d_type != DT_DIR) ||
556 !strcmp(".", d->d_name) ||
557 !strcmp("..", d->d_name))
558 continue;
559
560 scnprintf(path, sizeof(path), "%s/%s/comm",
561 procfs__mountpoint(), d->d_name);
562
563 if (filename__read_str(path, &data, &size))
564 continue;
565
566 ret = strncmp(name, data, len);
567 free(data);
568 }
569
570 closedir(dir);
571 return ret ? false : true;
572}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 66864364ccb4..027a5153495c 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -39,6 +39,8 @@
39 39
40#define _ALL_SOURCE 1 40#define _ALL_SOURCE 1
41#define _BSD_SOURCE 1 41#define _BSD_SOURCE 1
42/* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
43#define _DEFAULT_SOURCE 1
42#define HAS_BOOL 44#define HAS_BOOL
43 45
44#include <unistd.h> 46#include <unistd.h>
@@ -64,16 +66,18 @@
64#include <regex.h> 66#include <regex.h>
65#include <utime.h> 67#include <utime.h>
66#include <sys/wait.h> 68#include <sys/wait.h>
67#include <sys/poll.h> 69#include <poll.h>
68#include <sys/socket.h> 70#include <sys/socket.h>
69#include <sys/ioctl.h> 71#include <sys/ioctl.h>
70#include <inttypes.h> 72#include <inttypes.h>
73#include <linux/kernel.h>
71#include <linux/magic.h> 74#include <linux/magic.h>
72#include <linux/types.h> 75#include <linux/types.h>
73#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
74#include <api/fs/debugfs.h> 77#include <api/fs/debugfs.h>
75#include <termios.h> 78#include <termios.h>
76#include <linux/bitops.h> 79#include <linux/bitops.h>
80#include <termios.h>
77 81
78extern const char *graph_line; 82extern const char *graph_line;
79extern const char *graph_dotted_line; 83extern const char *graph_dotted_line;
@@ -149,8 +153,7 @@ extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)))
149extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); 153extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN);
150 154
151extern int prefixcmp(const char *str, const char *prefix); 155extern int prefixcmp(const char *str, const char *prefix);
152extern void set_buildid_dir(void); 156extern void set_buildid_dir(const char *dir);
153extern void disable_buildid_cache(void);
154 157
155static inline const char *skip_prefix(const char *str, const char *prefix) 158static inline const char *skip_prefix(const char *str, const char *prefix)
156{ 159{
@@ -266,35 +269,6 @@ void event_attr_init(struct perf_event_attr *attr);
266#define _STR(x) #x 269#define _STR(x) #x
267#define STR(x) _STR(x) 270#define STR(x) _STR(x)
268 271
269/*
270 * Determine whether some value is a power of two, where zero is
271 * *not* considered a power of two.
272 */
273
274static inline __attribute__((const))
275bool is_power_of_2(unsigned long n)
276{
277 return (n != 0 && ((n & (n - 1)) == 0));
278}
279
280static inline unsigned next_pow2(unsigned x)
281{
282 if (!x)
283 return 1;
284 return 1ULL << (32 - __builtin_clz(x - 1));
285}
286
287static inline unsigned long next_pow2_l(unsigned long x)
288{
289#if BITS_PER_LONG == 64
290 if (x <= (1UL << 31))
291 return next_pow2(x);
292 return (unsigned long)next_pow2(x >> 32) << 32;
293#else
294 return next_pow2(x);
295#endif
296}
297
298size_t hex_width(u64 v); 272size_t hex_width(u64 v);
299int hex2u64(const char *ptr, u64 *val); 273int hex2u64(const char *ptr, u64 *val);
300 274
@@ -307,6 +281,7 @@ extern unsigned int page_size;
307extern int cacheline_size; 281extern int cacheline_size;
308 282
309void get_term_dimensions(struct winsize *ws); 283void get_term_dimensions(struct winsize *ws);
284void set_term_quiet_input(struct termios *old);
310 285
311struct parse_tag { 286struct parse_tag {
312 char tag; 287 char tag;
@@ -317,12 +292,28 @@ unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
317 292
318#define SRCLINE_UNKNOWN ((char *) "??:0") 293#define SRCLINE_UNKNOWN ((char *) "??:0")
319 294
295static inline int path__join(char *bf, size_t size,
296 const char *path1, const char *path2)
297{
298 return scnprintf(bf, size, "%s%s%s", path1, path1[0] ? "/" : "", path2);
299}
300
301static inline int path__join3(char *bf, size_t size,
302 const char *path1, const char *path2,
303 const char *path3)
304{
305 return scnprintf(bf, size, "%s%s%s%s%s",
306 path1, path1[0] ? "/" : "",
307 path2, path2[0] ? "/" : "", path3);
308}
309
320struct dso; 310struct dso;
311struct symbol;
321 312
322char *get_srcline(struct dso *dso, unsigned long addr); 313char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
314 bool show_sym);
323void free_srcline(char *srcline); 315void free_srcline(char *srcline);
324 316
325int filename__read_int(const char *filename, int *value);
326int filename__read_str(const char *filename, char **buf, size_t *sizep); 317int filename__read_str(const char *filename, char **buf, size_t *sizep);
327int perf_event_paranoid(void); 318int perf_event_paranoid(void);
328 319
@@ -330,4 +321,10 @@ void mem_bswap_64(void *src, int byte_size);
330void mem_bswap_32(void *src, int byte_size); 321void mem_bswap_32(void *src, int byte_size);
331 322
332const char *get_filename_for_perf_kvm(void); 323const char *get_filename_for_perf_kvm(void);
324bool find_process(const char *name);
325
326#ifdef HAVE_ZLIB_SUPPORT
327int gzip_decompress_to_file(const char *input, int output_fd);
328#endif
329
333#endif /* GIT_COMPAT_UTIL_H */ 330#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index adca69384fcc..5c7dd796979d 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -12,9 +12,16 @@
12#include "util.h" 12#include "util.h"
13#include "symbol.h" 13#include "symbol.h"
14#include "machine.h" 14#include "machine.h"
15#include "thread.h"
15#include "linux/string.h" 16#include "linux/string.h"
16#include "debug.h" 17#include "debug.h"
17 18
19/*
20 * Include definition of find_vdso_map() also used in perf-read-vdso.c for
21 * building perf-read-vdso32 and perf-read-vdsox32.
22 */
23#include "find-vdso-map.c"
24
18#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX" 25#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
19 26
20struct vdso_file { 27struct vdso_file {
@@ -22,10 +29,15 @@ struct vdso_file {
22 bool error; 29 bool error;
23 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)]; 30 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
24 const char *dso_name; 31 const char *dso_name;
32 const char *read_prog;
25}; 33};
26 34
27struct vdso_info { 35struct vdso_info {
28 struct vdso_file vdso; 36 struct vdso_file vdso;
37#if BITS_PER_LONG == 64
38 struct vdso_file vdso32;
39 struct vdso_file vdsox32;
40#endif
29}; 41};
30 42
31static struct vdso_info *vdso_info__new(void) 43static struct vdso_info *vdso_info__new(void)
@@ -35,42 +47,23 @@ static struct vdso_info *vdso_info__new(void)
35 .temp_file_name = VDSO__TEMP_FILE_NAME, 47 .temp_file_name = VDSO__TEMP_FILE_NAME,
36 .dso_name = DSO__NAME_VDSO, 48 .dso_name = DSO__NAME_VDSO,
37 }, 49 },
50#if BITS_PER_LONG == 64
51 .vdso32 = {
52 .temp_file_name = VDSO__TEMP_FILE_NAME,
53 .dso_name = DSO__NAME_VDSO32,
54 .read_prog = "perf-read-vdso32",
55 },
56 .vdsox32 = {
57 .temp_file_name = VDSO__TEMP_FILE_NAME,
58 .dso_name = DSO__NAME_VDSOX32,
59 .read_prog = "perf-read-vdsox32",
60 },
61#endif
38 }; 62 };
39 63
40 return memdup(&vdso_info_init, sizeof(vdso_info_init)); 64 return memdup(&vdso_info_init, sizeof(vdso_info_init));
41} 65}
42 66
43static int find_vdso_map(void **start, void **end)
44{
45 FILE *maps;
46 char line[128];
47 int found = 0;
48
49 maps = fopen("/proc/self/maps", "r");
50 if (!maps) {
51 pr_err("vdso: cannot open maps\n");
52 return -1;
53 }
54
55 while (!found && fgets(line, sizeof(line), maps)) {
56 int m = -1;
57
58 /* We care only about private r-x mappings. */
59 if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
60 start, end, &m))
61 continue;
62 if (m < 0)
63 continue;
64
65 if (!strncmp(&line[m], VDSO__MAP_NAME,
66 sizeof(VDSO__MAP_NAME) - 1))
67 found = 1;
68 }
69
70 fclose(maps);
71 return !found;
72}
73
74static char *get_file(struct vdso_file *vdso_file) 67static char *get_file(struct vdso_file *vdso_file)
75{ 68{
76 char *vdso = NULL; 69 char *vdso = NULL;
@@ -117,6 +110,12 @@ void vdso__exit(struct machine *machine)
117 110
118 if (vdso_info->vdso.found) 111 if (vdso_info->vdso.found)
119 unlink(vdso_info->vdso.temp_file_name); 112 unlink(vdso_info->vdso.temp_file_name);
113#if BITS_PER_LONG == 64
114 if (vdso_info->vdso32.found)
115 unlink(vdso_info->vdso32.temp_file_name);
116 if (vdso_info->vdsox32.found)
117 unlink(vdso_info->vdsox32.temp_file_name);
118#endif
120 119
121 zfree(&machine->vdso_info); 120 zfree(&machine->vdso_info);
122} 121}
@@ -135,6 +134,153 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name,
135 return dso; 134 return dso;
136} 135}
137 136
137#if BITS_PER_LONG == 64
138
139static enum dso_type machine__thread_dso_type(struct machine *machine,
140 struct thread *thread)
141{
142 enum dso_type dso_type = DSO__TYPE_UNKNOWN;
143 struct map *map;
144 struct dso *dso;
145
146 map = map_groups__first(thread->mg, MAP__FUNCTION);
147 for (; map ; map = map_groups__next(map)) {
148 dso = map->dso;
149 if (!dso || dso->long_name[0] != '/')
150 continue;
151 dso_type = dso__type(dso, machine);
152 if (dso_type != DSO__TYPE_UNKNOWN)
153 break;
154 }
155
156 return dso_type;
157}
158
159static int vdso__do_copy_compat(FILE *f, int fd)
160{
161 char buf[4096];
162 size_t count;
163
164 while (1) {
165 count = fread(buf, 1, sizeof(buf), f);
166 if (ferror(f))
167 return -errno;
168 if (feof(f))
169 break;
170 if (count && writen(fd, buf, count) != (ssize_t)count)
171 return -errno;
172 }
173
174 return 0;
175}
176
177static int vdso__copy_compat(const char *prog, int fd)
178{
179 FILE *f;
180 int err;
181
182 f = popen(prog, "r");
183 if (!f)
184 return -errno;
185
186 err = vdso__do_copy_compat(f, fd);
187
188 if (pclose(f) == -1)
189 return -errno;
190
191 return err;
192}
193
194static int vdso__create_compat_file(const char *prog, char *temp_name)
195{
196 int fd, err;
197
198 fd = mkstemp(temp_name);
199 if (fd < 0)
200 return -errno;
201
202 err = vdso__copy_compat(prog, fd);
203
204 if (close(fd) == -1)
205 return -errno;
206
207 return err;
208}
209
210static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
211{
212 int err;
213
214 if (vdso_file->found)
215 return vdso_file->temp_file_name;
216
217 if (vdso_file->error)
218 return NULL;
219
220 err = vdso__create_compat_file(vdso_file->read_prog,
221 vdso_file->temp_file_name);
222 if (err) {
223 pr_err("%s failed, error %d\n", vdso_file->read_prog, err);
224 vdso_file->error = true;
225 return NULL;
226 }
227
228 vdso_file->found = true;
229
230 return vdso_file->temp_file_name;
231}
232
233static struct dso *vdso__findnew_compat(struct machine *machine,
234 struct vdso_file *vdso_file)
235{
236 const char *file_name;
237 struct dso *dso;
238
239 dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true);
240 if (dso)
241 return dso;
242
243 file_name = vdso__get_compat_file(vdso_file);
244 if (!file_name)
245 return NULL;
246
247 return vdso__new(machine, vdso_file->dso_name, file_name);
248}
249
250static int vdso__dso_findnew_compat(struct machine *machine,
251 struct thread *thread,
252 struct vdso_info *vdso_info,
253 struct dso **dso)
254{
255 enum dso_type dso_type;
256
257 dso_type = machine__thread_dso_type(machine, thread);
258
259#ifndef HAVE_PERF_READ_VDSO32
260 if (dso_type == DSO__TYPE_32BIT)
261 return 0;
262#endif
263#ifndef HAVE_PERF_READ_VDSOX32
264 if (dso_type == DSO__TYPE_X32BIT)
265 return 0;
266#endif
267
268 switch (dso_type) {
269 case DSO__TYPE_32BIT:
270 *dso = vdso__findnew_compat(machine, &vdso_info->vdso32);
271 return 1;
272 case DSO__TYPE_X32BIT:
273 *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32);
274 return 1;
275 case DSO__TYPE_UNKNOWN:
276 case DSO__TYPE_64BIT:
277 default:
278 return 0;
279 }
280}
281
282#endif
283
138struct dso *vdso__dso_findnew(struct machine *machine, 284struct dso *vdso__dso_findnew(struct machine *machine,
139 struct thread *thread __maybe_unused) 285 struct thread *thread __maybe_unused)
140{ 286{
@@ -148,6 +294,11 @@ struct dso *vdso__dso_findnew(struct machine *machine,
148 if (!vdso_info) 294 if (!vdso_info)
149 return NULL; 295 return NULL;
150 296
297#if BITS_PER_LONG == 64
298 if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso))
299 return dso;
300#endif
301
151 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true); 302 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
152 if (!dso) { 303 if (!dso) {
153 char *file; 304 char *file;
@@ -164,5 +315,7 @@ struct dso *vdso__dso_findnew(struct machine *machine,
164 315
165bool dso__is_vdso(struct dso *dso) 316bool dso__is_vdso(struct dso *dso)
166{ 317{
167 return !strcmp(dso->short_name, DSO__NAME_VDSO); 318 return !strcmp(dso->short_name, DSO__NAME_VDSO) ||
319 !strcmp(dso->short_name, DSO__NAME_VDSO32) ||
320 !strcmp(dso->short_name, DSO__NAME_VDSOX32);
168} 321}
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index af9d6929a215..d97da1616f0c 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -7,7 +7,9 @@
7 7
8#define VDSO__MAP_NAME "[vdso]" 8#define VDSO__MAP_NAME "[vdso]"
9 9
10#define DSO__NAME_VDSO "[vdso]" 10#define DSO__NAME_VDSO "[vdso]"
11#define DSO__NAME_VDSO32 "[vdso32]"
12#define DSO__NAME_VDSOX32 "[vdsox32]"
11 13
12static inline bool is_vdso_map(const char *filename) 14static inline bool is_vdso_map(const char *filename)
13{ 15{
diff --git a/tools/perf/util/zlib.c b/tools/perf/util/zlib.c
new file mode 100644
index 000000000000..495a449fc25c
--- /dev/null
+++ b/tools/perf/util/zlib.c
@@ -0,0 +1,78 @@
1#include <stdio.h>
2#include <unistd.h>
3#include <sys/stat.h>
4#include <sys/mman.h>
5#include <zlib.h>
6
7#include "util/util.h"
8#include "util/debug.h"
9
10
11#define CHUNK_SIZE 16384
12
13int gzip_decompress_to_file(const char *input, int output_fd)
14{
15 int ret = Z_STREAM_ERROR;
16 int input_fd;
17 void *ptr;
18 int len;
19 struct stat stbuf;
20 unsigned char buf[CHUNK_SIZE];
21 z_stream zs = {
22 .zalloc = Z_NULL,
23 .zfree = Z_NULL,
24 .opaque = Z_NULL,
25 .avail_in = 0,
26 .next_in = Z_NULL,
27 };
28
29 input_fd = open(input, O_RDONLY);
30 if (input_fd < 0)
31 return -1;
32
33 if (fstat(input_fd, &stbuf) < 0)
34 goto out_close;
35
36 ptr = mmap(NULL, stbuf.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
37 if (ptr == MAP_FAILED)
38 goto out_close;
39
40 if (inflateInit2(&zs, 16 + MAX_WBITS) != Z_OK)
41 goto out_unmap;
42
43 zs.next_in = ptr;
44 zs.avail_in = stbuf.st_size;
45
46 do {
47 zs.next_out = buf;
48 zs.avail_out = CHUNK_SIZE;
49
50 ret = inflate(&zs, Z_NO_FLUSH);
51 switch (ret) {
52 case Z_NEED_DICT:
53 ret = Z_DATA_ERROR;
54 /* fall through */
55 case Z_DATA_ERROR:
56 case Z_MEM_ERROR:
57 goto out;
58 default:
59 break;
60 }
61
62 len = CHUNK_SIZE - zs.avail_out;
63 if (writen(output_fd, buf, len) != len) {
64 ret = Z_DATA_ERROR;
65 goto out;
66 }
67
68 } while (ret != Z_STREAM_END);
69
70out:
71 inflateEnd(&zs);
72out_unmap:
73 munmap(ptr, stbuf.st_size);
74out_close:
75 close(input_fd);
76
77 return ret == Z_STREAM_END ? 0 : -1;
78}