aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/examples.txt34
-rw-r--r--tools/perf/Documentation/perf-annotate.txt4
-rw-r--r--tools/perf/Documentation/perf-buildid-list.txt2
-rw-r--r--tools/perf/Documentation/perf-evlist.txt2
-rw-r--r--tools/perf/Documentation/perf-kmem.txt2
-rw-r--r--tools/perf/Documentation/perf-lock.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/perf/Documentation/perf-report.txt11
-rw-r--r--tools/perf/Documentation/perf-sched.txt2
-rw-r--r--tools/perf/Documentation/perf-script.txt9
-rw-r--r--tools/perf/Documentation/perf-test.txt8
-rw-r--r--tools/perf/Documentation/perf-timechart.txt2
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c3
-rw-r--r--tools/perf/builtin-annotate.c132
-rw-r--r--tools/perf/builtin-buildid-list.c53
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-inject.c118
-rw-r--r--tools/perf/builtin-kmem.c16
-rw-r--r--tools/perf/builtin-kvm.c2
-rw-r--r--tools/perf/builtin-lock.c12
-rw-r--r--tools/perf/builtin-probe.c1
-rw-r--r--tools/perf/builtin-record.c603
-rw-r--r--tools/perf/builtin-report.c236
-rw-r--r--tools/perf/builtin-sched.c200
-rw-r--r--tools/perf/builtin-script.c130
-rw-r--r--tools/perf/builtin-stat.c137
-rw-r--r--tools/perf/builtin-test.c545
-rw-r--r--tools/perf/builtin-timechart.c38
-rw-r--r--tools/perf/builtin-top.c558
-rw-r--r--tools/perf/perf.c33
-rw-r--r--tools/perf/perf.h24
-rw-r--r--tools/perf/util/annotate.c8
-rw-r--r--tools/perf/util/annotate.h5
-rw-r--r--tools/perf/util/build-id.c26
-rw-r--r--tools/perf/util/build-id.h2
-rw-r--r--tools/perf/util/callchain.h3
-rw-r--r--tools/perf/util/cgroup.c15
-rw-r--r--tools/perf/util/config.c5
-rw-r--r--tools/perf/util/debugfs.c35
-rw-r--r--tools/perf/util/debugfs.h31
-rw-r--r--tools/perf/util/event.c360
-rw-r--r--tools/perf/util/event.h68
-rw-r--r--tools/perf/util/evlist.c299
-rw-r--r--tools/perf/util/evlist.h43
-rw-r--r--tools/perf/util/evsel.c164
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/header.c743
-rw-r--r--tools/perf/util/header.h51
-rw-r--r--tools/perf/util/hist.c10
-rw-r--r--tools/perf/util/hist.h5
-rw-r--r--tools/perf/util/include/linux/bitops.h118
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/map.h19
-rw-r--r--tools/perf/util/parse-events.c30
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c75
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c346
-rw-r--r--tools/perf/util/session.h72
-rw-r--r--tools/perf/util/setup.py3
-rw-r--r--tools/perf/util/symbol.c11
-rw-r--r--tools/perf/util/symbol.h1
-rw-r--r--tools/perf/util/thread.c6
-rw-r--r--tools/perf/util/thread.h14
-rw-r--r--tools/perf/util/tool.h50
-rw-r--r--tools/perf/util/top.h20
-rw-r--r--tools/perf/util/trace-event-info.c28
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/perf/util/trace-event-scripting.c2
-rw-r--r--tools/perf/util/trace-event.h8
-rw-r--r--tools/perf/util/ui/browsers/annotate.c16
-rw-r--r--tools/perf/util/ui/browsers/hists.c2
-rw-r--r--tools/perf/util/ui/progress.c3
-rw-r--r--tools/perf/util/usage.c5
-rw-r--r--tools/perf/util/util.h11
-rw-r--r--tools/perf/util/values.c1
-rw-r--r--tools/power/x86/turbostat/turbostat.88
-rw-r--r--tools/testing/ktest/sample.conf2
81 files changed, 3490 insertions, 2199 deletions
diff --git a/tools/perf/Documentation/examples.txt b/tools/perf/Documentation/examples.txt
index 8eb6c489fb15..77f952762426 100644
--- a/tools/perf/Documentation/examples.txt
+++ b/tools/perf/Documentation/examples.txt
@@ -17,8 +17,8 @@ titan:~> perf list
17 kmem:kmem_cache_alloc_node [Tracepoint event] 17 kmem:kmem_cache_alloc_node [Tracepoint event]
18 kmem:kfree [Tracepoint event] 18 kmem:kfree [Tracepoint event]
19 kmem:kmem_cache_free [Tracepoint event] 19 kmem:kmem_cache_free [Tracepoint event]
20 kmem:mm_page_free_direct [Tracepoint event] 20 kmem:mm_page_free [Tracepoint event]
21 kmem:mm_pagevec_free [Tracepoint event] 21 kmem:mm_page_free_batched [Tracepoint event]
22 kmem:mm_page_alloc [Tracepoint event] 22 kmem:mm_page_alloc [Tracepoint event]
23 kmem:mm_page_alloc_zone_locked [Tracepoint event] 23 kmem:mm_page_alloc_zone_locked [Tracepoint event]
24 kmem:mm_page_pcpu_drain [Tracepoint event] 24 kmem:mm_page_pcpu_drain [Tracepoint event]
@@ -29,15 +29,15 @@ measured. For example the page alloc/free properties of a 'hackbench
29run' are: 29run' are:
30 30
31 titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc 31 titan:~> perf stat -e kmem:mm_page_pcpu_drain -e kmem:mm_page_alloc
32 -e kmem:mm_pagevec_free -e kmem:mm_page_free_direct ./hackbench 10 32 -e kmem:mm_page_free_batched -e kmem:mm_page_free ./hackbench 10
33 Time: 0.575 33 Time: 0.575
34 34
35 Performance counter stats for './hackbench 10': 35 Performance counter stats for './hackbench 10':
36 36
37 13857 kmem:mm_page_pcpu_drain 37 13857 kmem:mm_page_pcpu_drain
38 27576 kmem:mm_page_alloc 38 27576 kmem:mm_page_alloc
39 6025 kmem:mm_pagevec_free 39 6025 kmem:mm_page_free_batched
40 20934 kmem:mm_page_free_direct 40 20934 kmem:mm_page_free
41 41
42 0.613972165 seconds time elapsed 42 0.613972165 seconds time elapsed
43 43
@@ -45,8 +45,8 @@ You can observe the statistical properties as well, by using the
45'repeat the workload N times' feature of perf stat: 45'repeat the workload N times' feature of perf stat:
46 46
47 titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e 47 titan:~> perf stat --repeat 5 -e kmem:mm_page_pcpu_drain -e
48 kmem:mm_page_alloc -e kmem:mm_pagevec_free -e 48 kmem:mm_page_alloc -e kmem:mm_page_free_batched -e
49 kmem:mm_page_free_direct ./hackbench 10 49 kmem:mm_page_free ./hackbench 10
50 Time: 0.627 50 Time: 0.627
51 Time: 0.644 51 Time: 0.644
52 Time: 0.564 52 Time: 0.564
@@ -57,8 +57,8 @@ You can observe the statistical properties as well, by using the
57 57
58 12920 kmem:mm_page_pcpu_drain ( +- 3.359% ) 58 12920 kmem:mm_page_pcpu_drain ( +- 3.359% )
59 25035 kmem:mm_page_alloc ( +- 3.783% ) 59 25035 kmem:mm_page_alloc ( +- 3.783% )
60 6104 kmem:mm_pagevec_free ( +- 0.934% ) 60 6104 kmem:mm_page_free_batched ( +- 0.934% )
61 18376 kmem:mm_page_free_direct ( +- 4.941% ) 61 18376 kmem:mm_page_free ( +- 4.941% )
62 62
63 0.643954516 seconds time elapsed ( +- 2.363% ) 63 0.643954516 seconds time elapsed ( +- 2.363% )
64 64
@@ -158,15 +158,15 @@ Or you can observe the whole system's page allocations for 10
158seconds: 158seconds:
159 159
160titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e 160titan:~/git> perf stat -a -e kmem:mm_page_pcpu_drain -e
161kmem:mm_page_alloc -e kmem:mm_pagevec_free -e 161kmem:mm_page_alloc -e kmem:mm_page_free_batched -e
162kmem:mm_page_free_direct sleep 10 162kmem:mm_page_free sleep 10
163 163
164 Performance counter stats for 'sleep 10': 164 Performance counter stats for 'sleep 10':
165 165
166 171585 kmem:mm_page_pcpu_drain 166 171585 kmem:mm_page_pcpu_drain
167 322114 kmem:mm_page_alloc 167 322114 kmem:mm_page_alloc
168 73623 kmem:mm_pagevec_free 168 73623 kmem:mm_page_free_batched
169 254115 kmem:mm_page_free_direct 169 254115 kmem:mm_page_free
170 170
171 10.000591410 seconds time elapsed 171 10.000591410 seconds time elapsed
172 172
@@ -174,15 +174,15 @@ Or observe how fluctuating the page allocations are, via statistical
174analysis done over ten 1-second intervals: 174analysis done over ten 1-second intervals:
175 175
176 titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e 176 titan:~/git> perf stat --repeat 10 -a -e kmem:mm_page_pcpu_drain -e
177 kmem:mm_page_alloc -e kmem:mm_pagevec_free -e 177 kmem:mm_page_alloc -e kmem:mm_page_free_batched -e
178 kmem:mm_page_free_direct sleep 1 178 kmem:mm_page_free sleep 1
179 179
180 Performance counter stats for 'sleep 1' (10 runs): 180 Performance counter stats for 'sleep 1' (10 runs):
181 181
182 17254 kmem:mm_page_pcpu_drain ( +- 3.709% ) 182 17254 kmem:mm_page_pcpu_drain ( +- 3.709% )
183 34394 kmem:mm_page_alloc ( +- 4.617% ) 183 34394 kmem:mm_page_alloc ( +- 4.617% )
184 7509 kmem:mm_pagevec_free ( +- 4.820% ) 184 7509 kmem:mm_page_free_batched ( +- 4.820% )
185 25653 kmem:mm_page_free_direct ( +- 3.672% ) 185 25653 kmem:mm_page_free ( +- 3.672% )
186 186
187 1.058135029 seconds time elapsed ( +- 3.089% ) 187 1.058135029 seconds time elapsed ( +- 3.089% )
188 188
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index fe6762ed56bd..c89f9e1453f7 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -22,7 +22,7 @@ OPTIONS
22------- 22-------
23-i:: 23-i::
24--input=:: 24--input=::
25 Input file name. (default: perf.data) 25 Input file name. (default: perf.data unless stdin is a fifo)
26 26
27-d:: 27-d::
28--dsos=<dso[,dso...]>:: 28--dsos=<dso[,dso...]>::
@@ -66,7 +66,7 @@ OPTIONS
66 used. This interfaces starts by centering on the line with more 66 used. This interfaces starts by centering on the line with more
67 samples, TAB/UNTAB cycles through the lines with more samples. 67 samples, TAB/UNTAB cycles through the lines with more samples.
68 68
69-c:: 69-C::
70--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 70--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
71 be provided as a comma-separated list with no space: 0,1. Ranges of 71 be provided as a comma-separated list with no space: 0,1. Ranges of
72 CPUs are specified with -: 0-2. Default is to report samples on all 72 CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index cc22325ffd1b..25c52efcc7f0 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -26,7 +26,7 @@ OPTIONS
26 Show only DSOs with hits. 26 Show only DSOs with hits.
27-i:: 27-i::
28--input=:: 28--input=::
29 Input file name. (default: perf.data) 29 Input file name. (default: perf.data unless stdin is a fifo)
30-f:: 30-f::
31--force:: 31--force::
32 Don't do ownership validation. 32 Don't do ownership validation.
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 0cada9e053dc..0507ec7bad71 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -18,7 +18,7 @@ OPTIONS
18------- 18-------
19-i:: 19-i::
20--input=:: 20--input=::
21 Input file name. (default: perf.data) 21 Input file name. (default: perf.data unless stdin is a fifo)
22 22
23SEE ALSO 23SEE ALSO
24-------- 24--------
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index a52fcde894c7..7c8fbbf3f61c 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -23,7 +23,7 @@ OPTIONS
23------- 23-------
24-i <file>:: 24-i <file>::
25--input=<file>:: 25--input=<file>::
26 Select the input file (default: perf.data) 26 Select the input file (default: perf.data unless stdin is a fifo)
27 27
28--caller:: 28--caller::
29 Show per-callsite statistics 29 Show per-callsite statistics
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index 4a26a2f3a6a3..d6b2a4f2108b 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -29,7 +29,7 @@ COMMON OPTIONS
29 29
30-i:: 30-i::
31--input=<file>:: 31--input=<file>::
32 Input file name. 32 Input file name. (default: perf.data unless stdin is a fifo)
33 33
34-v:: 34-v::
35--verbose:: 35--verbose::
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5a520f825295..2937f7e14bb7 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -89,7 +89,7 @@ OPTIONS
89 89
90-m:: 90-m::
91--mmap-pages=:: 91--mmap-pages=::
92 Number of mmap data pages. 92 Number of mmap data pages. Must be a power of two.
93 93
94-g:: 94-g::
95--call-graph:: 95--call-graph::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 212f24d672e1..9b430e98712e 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -19,7 +19,7 @@ OPTIONS
19------- 19-------
20-i:: 20-i::
21--input=:: 21--input=::
22 Input file name. (default: perf.data) 22 Input file name. (default: perf.data unless stdin is a fifo)
23 23
24-v:: 24-v::
25--verbose:: 25--verbose::
@@ -39,7 +39,7 @@ OPTIONS
39-T:: 39-T::
40--threads:: 40--threads::
41 Show per-thread event counters 41 Show per-thread event counters
42-C:: 42-c::
43--comms=:: 43--comms=::
44 Only consider symbols in these comms. CSV that understands 44 Only consider symbols in these comms. CSV that understands
45 file://filename entries. 45 file://filename entries.
@@ -80,9 +80,10 @@ OPTIONS
80--dump-raw-trace:: 80--dump-raw-trace::
81 Dump raw trace in ASCII. 81 Dump raw trace in ASCII.
82 82
83-g [type,min,order]:: 83-g [type,min[,limit],order]::
84--call-graph:: 84--call-graph::
85 Display call chains using type, min percent threshold and order. 85 Display call chains using type, min percent threshold, optional print
86 limit and order.
86 type can be either: 87 type can be either:
87 - flat: single column, linear exposure of call chains. 88 - flat: single column, linear exposure of call chains.
88 - graph: use a graph tree, displaying absolute overhead rates. 89 - graph: use a graph tree, displaying absolute overhead rates.
@@ -128,7 +129,7 @@ OPTIONS
128--symfs=<directory>:: 129--symfs=<directory>::
129 Look for files with symbols relative to this directory. 130 Look for files with symbols relative to this directory.
130 131
131-c:: 132-C::
132--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 133--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
133 be provided as a comma-separated list with no space: 0,1. Ranges of 134 be provided as a comma-separated list with no space: 0,1. Ranges of
134 CPUs are specified with -: 0-2. Default is to report samples on all 135 CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 5b212b57f70b..8ff4df956951 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -40,7 +40,7 @@ OPTIONS
40------- 40-------
41-i:: 41-i::
42--input=<file>:: 42--input=<file>::
43 Input file name. (default: perf.data) 43 Input file name. (default: perf.data unless stdin is a fifo)
44 44
45-v:: 45-v::
46--verbose:: 46--verbose::
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dec87ecb530e..2f6cef43da25 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -106,7 +106,7 @@ OPTIONS
106 106
107-i:: 107-i::
108--input=:: 108--input=::
109 Input file name. 109 Input file name. (default: perf.data unless stdin is a fifo)
110 110
111-d:: 111-d::
112--debug-mode:: 112--debug-mode::
@@ -182,12 +182,17 @@ OPTIONS
182--hide-call-graph:: 182--hide-call-graph::
183 When printing symbols do not display call chain. 183 When printing symbols do not display call chain.
184 184
185-c:: 185-C::
186--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 186--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can
187 be provided as a comma-separated list with no space: 0,1. Ranges of 187 be provided as a comma-separated list with no space: 0,1. Ranges of
188 CPUs are specified with -: 0-2. Default is to report samples on all 188 CPUs are specified with -: 0-2. Default is to report samples on all
189 CPUs. 189 CPUs.
190 190
191-c::
192--comms=::
193 Only display events for these comms. CSV that understands
194 file://filename entries.
195
191-I:: 196-I::
192--show-info:: 197--show-info::
193 Display extended information about the perf.data file. This adds 198 Display extended information about the perf.data file. This adds
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 2c3b462f64b0..b24ac40fcd58 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -8,13 +8,19 @@ perf-test - Runs sanity tests.
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf test <options>' 11'perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]'
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command does assorted sanity tests, initially through linked routines but 15This command does assorted sanity tests, initially through linked routines but
16also will look for a directory with more tests in the form of scripts. 16also will look for a directory with more tests in the form of scripts.
17 17
18To get a list of available tests use 'perf test list', specifying a test name
19fragment will show all tests that have it.
20
21To run just specific tests, inform test name fragments or the numbers obtained
22from 'perf test list'.
23
18OPTIONS 24OPTIONS
19------- 25-------
20-v:: 26-v::
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index d7b79e2ba2ad..1632b0efc757 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -27,7 +27,7 @@ OPTIONS
27 Select the output file (default: output.svg) 27 Select the output file (default: output.svg)
28-i:: 28-i::
29--input=:: 29--input=::
30 Select the input file (default: perf.data) 30 Select the input file (default: perf.data unless stdin is a fifo)
31-w:: 31-w::
32--width=:: 32--width=::
33 Select the width of the SVG file (default: 1000) 33 Select the width of the SVG file (default: 1000)
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index b98e3075646b..ac86d67b636e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -278,6 +278,7 @@ LIB_H += util/strbuf.h
278LIB_H += util/strlist.h 278LIB_H += util/strlist.h
279LIB_H += util/strfilter.h 279LIB_H += util/strfilter.h
280LIB_H += util/svghelper.h 280LIB_H += util/svghelper.h
281LIB_H += util/tool.h
281LIB_H += util/run-command.h 282LIB_H += util/run-command.h
282LIB_H += util/sigchain.h 283LIB_H += util/sigchain.h
283LIB_H += util/symbol.h 284LIB_H += util/symbol.h
diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c
index 48ae0c5e3f73..7cdd61d0e27c 100644
--- a/tools/perf/arch/powerpc/util/dwarf-regs.c
+++ b/tools/perf/arch/powerpc/util/dwarf-regs.c
@@ -9,7 +9,10 @@
9 * 2 of the License, or (at your option) any later version. 9 * 2 of the License, or (at your option) any later version.
10 */ 10 */
11 11
12#include <stdlib.h>
13#ifndef __UCLIBC__
12#include <libio.h> 14#include <libio.h>
15#endif
13#include <dwarf-regs.h> 16#include <dwarf-regs.h>
14 17
15 18
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 46b4c24f338e..214ba7f9f577 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -27,32 +27,32 @@
27#include "util/sort.h" 27#include "util/sort.h"
28#include "util/hist.h" 28#include "util/hist.h"
29#include "util/session.h" 29#include "util/session.h"
30#include "util/tool.h"
30 31
31#include <linux/bitmap.h> 32#include <linux/bitmap.h>
32 33
33static char const *input_name = "perf.data"; 34struct perf_annotate {
34 35 struct perf_tool tool;
35static bool force, use_tui, use_stdio; 36 char const *input_name;
36 37 bool force, use_tui, use_stdio;
37static bool full_paths; 38 bool full_paths;
38 39 bool print_line;
39static bool print_line; 40 const char *sym_hist_filter;
40 41 const char *cpu_list;
41static const char *sym_hist_filter; 42 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
42 43};
43static const char *cpu_list;
44static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
45 44
46static int perf_evlist__add_sample(struct perf_evlist *evlist, 45static int perf_evsel__add_sample(struct perf_evsel *evsel,
47 struct perf_sample *sample, 46 struct perf_sample *sample,
48 struct perf_evsel *evsel, 47 struct addr_location *al,
49 struct addr_location *al) 48 struct perf_annotate *ann)
50{ 49{
51 struct hist_entry *he; 50 struct hist_entry *he;
52 int ret; 51 int ret;
53 52
54 if (sym_hist_filter != NULL && 53 if (ann->sym_hist_filter != NULL &&
55 (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) { 54 (al->sym == NULL ||
55 strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
56 /* We're only interested in a symbol named sym_hist_filter */ 56 /* We're only interested in a symbol named sym_hist_filter */
57 if (al->sym != NULL) { 57 if (al->sym != NULL) {
58 rb_erase(&al->sym->rb_node, 58 rb_erase(&al->sym->rb_node,
@@ -69,8 +69,7 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist,
69 ret = 0; 69 ret = 0;
70 if (he->ms.sym != NULL) { 70 if (he->ms.sym != NULL) {
71 struct annotation *notes = symbol__annotation(he->ms.sym); 71 struct annotation *notes = symbol__annotation(he->ms.sym);
72 if (notes->src == NULL && 72 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
73 symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
74 return -ENOMEM; 73 return -ENOMEM;
75 74
76 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 75 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
@@ -81,25 +80,26 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist,
81 return ret; 80 return ret;
82} 81}
83 82
84static int process_sample_event(union perf_event *event, 83static int process_sample_event(struct perf_tool *tool,
84 union perf_event *event,
85 struct perf_sample *sample, 85 struct perf_sample *sample,
86 struct perf_evsel *evsel, 86 struct perf_evsel *evsel,
87 struct perf_session *session) 87 struct machine *machine)
88{ 88{
89 struct perf_annotate *ann = container_of(tool, struct perf_annotate, tool);
89 struct addr_location al; 90 struct addr_location al;
90 91
91 if (perf_event__preprocess_sample(event, session, &al, sample, 92 if (perf_event__preprocess_sample(event, machine, &al, sample,
92 symbol__annotate_init) < 0) { 93 symbol__annotate_init) < 0) {
93 pr_warning("problem processing %d event, skipping it.\n", 94 pr_warning("problem processing %d event, skipping it.\n",
94 event->header.type); 95 event->header.type);
95 return -1; 96 return -1;
96 } 97 }
97 98
98 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 99 if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap))
99 return 0; 100 return 0;
100 101
101 if (!al.filtered && 102 if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) {
102 perf_evlist__add_sample(session->evlist, sample, evsel, &al)) {
103 pr_warning("problem incrementing symbol count, " 103 pr_warning("problem incrementing symbol count, "
104 "skipping event\n"); 104 "skipping event\n");
105 return -1; 105 return -1;
@@ -108,14 +108,15 @@ static int process_sample_event(union perf_event *event,
108 return 0; 108 return 0;
109} 109}
110 110
111static int hist_entry__tty_annotate(struct hist_entry *he, int evidx) 111static int hist_entry__tty_annotate(struct hist_entry *he, int evidx,
112 struct perf_annotate *ann)
112{ 113{
113 return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx, 114 return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
114 print_line, full_paths, 0, 0); 115 ann->print_line, ann->full_paths, 0, 0);
115} 116}
116 117
117static void hists__find_annotations(struct hists *self, int evidx, 118static void hists__find_annotations(struct hists *self, int evidx,
118 int nr_events) 119 struct perf_annotate *ann)
119{ 120{
120 struct rb_node *nd = rb_first(&self->entries), *next; 121 struct rb_node *nd = rb_first(&self->entries), *next;
121 int key = K_RIGHT; 122 int key = K_RIGHT;
@@ -138,8 +139,7 @@ find_next:
138 } 139 }
139 140
140 if (use_browser > 0) { 141 if (use_browser > 0) {
141 key = hist_entry__tui_annotate(he, evidx, nr_events, 142 key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0);
142 NULL, NULL, 0);
143 switch (key) { 143 switch (key) {
144 case K_RIGHT: 144 case K_RIGHT:
145 next = rb_next(nd); 145 next = rb_next(nd);
@@ -154,7 +154,7 @@ find_next:
154 if (next != NULL) 154 if (next != NULL)
155 nd = next; 155 nd = next;
156 } else { 156 } else {
157 hist_entry__tty_annotate(he, evidx); 157 hist_entry__tty_annotate(he, evidx, ann);
158 nd = rb_next(nd); 158 nd = rb_next(nd);
159 /* 159 /*
160 * Since we have a hist_entry per IP for the same 160 * Since we have a hist_entry per IP for the same
@@ -167,33 +167,26 @@ find_next:
167 } 167 }
168} 168}
169 169
170static struct perf_event_ops event_ops = { 170static int __cmd_annotate(struct perf_annotate *ann)
171 .sample = process_sample_event,
172 .mmap = perf_event__process_mmap,
173 .comm = perf_event__process_comm,
174 .fork = perf_event__process_task,
175 .ordered_samples = true,
176 .ordering_requires_timestamps = true,
177};
178
179static int __cmd_annotate(void)
180{ 171{
181 int ret; 172 int ret;
182 struct perf_session *session; 173 struct perf_session *session;
183 struct perf_evsel *pos; 174 struct perf_evsel *pos;
184 u64 total_nr_samples; 175 u64 total_nr_samples;
185 176
186 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 177 session = perf_session__new(ann->input_name, O_RDONLY,
178 ann->force, false, &ann->tool);
187 if (session == NULL) 179 if (session == NULL)
188 return -ENOMEM; 180 return -ENOMEM;
189 181
190 if (cpu_list) { 182 if (ann->cpu_list) {
191 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 183 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
184 ann->cpu_bitmap);
192 if (ret) 185 if (ret)
193 goto out_delete; 186 goto out_delete;
194 } 187 }
195 188
196 ret = perf_session__process_events(session, &event_ops); 189 ret = perf_session__process_events(session, &ann->tool);
197 if (ret) 190 if (ret)
198 goto out_delete; 191 goto out_delete;
199 192
@@ -217,13 +210,12 @@ static int __cmd_annotate(void)
217 total_nr_samples += nr_samples; 210 total_nr_samples += nr_samples;
218 hists__collapse_resort(hists); 211 hists__collapse_resort(hists);
219 hists__output_resort(hists); 212 hists__output_resort(hists);
220 hists__find_annotations(hists, pos->idx, 213 hists__find_annotations(hists, pos->idx, ann);
221 session->evlist->nr_entries);
222 } 214 }
223 } 215 }
224 216
225 if (total_nr_samples == 0) { 217 if (total_nr_samples == 0) {
226 ui__warning("The %s file has no samples!\n", input_name); 218 ui__warning("The %s file has no samples!\n", session->filename);
227 goto out_delete; 219 goto out_delete;
228 } 220 }
229out_delete: 221out_delete:
@@ -247,29 +239,41 @@ static const char * const annotate_usage[] = {
247 NULL 239 NULL
248}; 240};
249 241
250static const struct option options[] = { 242int cmd_annotate(int argc, const char **argv, const char *prefix __used)
251 OPT_STRING('i', "input", &input_name, "file", 243{
244 struct perf_annotate annotate = {
245 .tool = {
246 .sample = process_sample_event,
247 .mmap = perf_event__process_mmap,
248 .comm = perf_event__process_comm,
249 .fork = perf_event__process_task,
250 .ordered_samples = true,
251 .ordering_requires_timestamps = true,
252 },
253 };
254 const struct option options[] = {
255 OPT_STRING('i', "input", &annotate.input_name, "file",
252 "input file name"), 256 "input file name"),
253 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 257 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
254 "only consider symbols in these dsos"), 258 "only consider symbols in these dsos"),
255 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 259 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
256 "symbol to annotate"), 260 "symbol to annotate"),
257 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 261 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"),
258 OPT_INCR('v', "verbose", &verbose, 262 OPT_INCR('v', "verbose", &verbose,
259 "be more verbose (show symbol address, etc)"), 263 "be more verbose (show symbol address, etc)"),
260 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 264 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
261 "dump raw trace in ASCII"), 265 "dump raw trace in ASCII"),
262 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 266 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
263 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 267 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
264 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 268 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
265 "file", "vmlinux pathname"), 269 "file", "vmlinux pathname"),
266 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 270 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
267 "load module symbols - WARNING: use only with -k and LIVE kernel"), 271 "load module symbols - WARNING: use only with -k and LIVE kernel"),
268 OPT_BOOLEAN('l', "print-line", &print_line, 272 OPT_BOOLEAN('l', "print-line", &annotate.print_line,
269 "print matching source lines (may be slow)"), 273 "print matching source lines (may be slow)"),
270 OPT_BOOLEAN('P', "full-paths", &full_paths, 274 OPT_BOOLEAN('P', "full-paths", &annotate.full_paths,
271 "Don't shorten the displayed pathnames"), 275 "Don't shorten the displayed pathnames"),
272 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 276 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
273 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 277 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
274 "Look for files with symbols relative to this directory"), 278 "Look for files with symbols relative to this directory"),
275 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 279 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
@@ -279,15 +283,13 @@ static const struct option options[] = {
279 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 283 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
280 "Specify disassembler style (e.g. -M intel for intel syntax)"), 284 "Specify disassembler style (e.g. -M intel for intel syntax)"),
281 OPT_END() 285 OPT_END()
282}; 286 };
283 287
284int cmd_annotate(int argc, const char **argv, const char *prefix __used)
285{
286 argc = parse_options(argc, argv, options, annotate_usage, 0); 288 argc = parse_options(argc, argv, options, annotate_usage, 0);
287 289
288 if (use_stdio) 290 if (annotate.use_stdio)
289 use_browser = 0; 291 use_browser = 0;
290 else if (use_tui) 292 else if (annotate.use_tui)
291 use_browser = 1; 293 use_browser = 1;
292 294
293 setup_browser(true); 295 setup_browser(true);
@@ -308,7 +310,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
308 if (argc > 1) 310 if (argc > 1)
309 usage_with_options(annotate_usage, options); 311 usage_with_options(annotate_usage, options);
310 312
311 sym_hist_filter = argv[0]; 313 annotate.sym_hist_filter = argv[0];
312 } 314 }
313 315
314 if (field_sep && *field_sep == '.') { 316 if (field_sep && *field_sep == '.') {
@@ -316,5 +318,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
316 return -1; 318 return -1;
317 } 319 }
318 320
319 return __cmd_annotate(); 321 return __cmd_annotate(&annotate);
320} 322}
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index cb690a65bf02..52480467e9ff 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -18,7 +18,7 @@
18 18
19#include <libelf.h> 19#include <libelf.h>
20 20
21static char const *input_name = "perf.data"; 21static const char *input_name;
22static bool force; 22static bool force;
23static bool show_kernel; 23static bool show_kernel;
24static bool with_hits; 24static bool with_hits;
@@ -39,24 +39,6 @@ static const struct option options[] = {
39 OPT_END() 39 OPT_END()
40}; 40};
41 41
42static int perf_session__list_build_ids(void)
43{
44 struct perf_session *session;
45
46 session = perf_session__new(input_name, O_RDONLY, force, false,
47 &build_id__mark_dso_hit_ops);
48 if (session == NULL)
49 return -1;
50
51 if (with_hits)
52 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
53
54 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
55
56 perf_session__delete(session);
57 return 0;
58}
59
60static int sysfs__fprintf_build_id(FILE *fp) 42static int sysfs__fprintf_build_id(FILE *fp)
61{ 43{
62 u8 kallsyms_build_id[BUILD_ID_SIZE]; 44 u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -85,17 +67,36 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
85 return fprintf(fp, "%s\n", sbuild_id); 67 return fprintf(fp, "%s\n", sbuild_id);
86} 68}
87 69
88static int __cmd_buildid_list(void) 70static int perf_session__list_build_ids(void)
89{ 71{
90 if (show_kernel) 72 struct perf_session *session;
91 return sysfs__fprintf_build_id(stdout);
92 73
93 elf_version(EV_CURRENT); 74 elf_version(EV_CURRENT);
75
76 session = perf_session__new(input_name, O_RDONLY, force, false,
77 &build_id__mark_dso_hit_ops);
78 if (session == NULL)
79 return -1;
80
94 /* 81 /*
95 * See if this is an ELF file first: 82 * See if this is an ELF file first:
96 */ 83 */
97 if (filename__fprintf_build_id(input_name, stdout)) 84 if (filename__fprintf_build_id(session->filename, stdout))
98 return 0; 85 goto out;
86
87 if (with_hits)
88 perf_session__process_events(session, &build_id__mark_dso_hit_ops);
89
90 perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
91out:
92 perf_session__delete(session);
93 return 0;
94}
95
96static int __cmd_buildid_list(void)
97{
98 if (show_kernel)
99 return sysfs__fprintf_build_id(stdout);
99 100
100 return perf_session__list_build_ids(); 101 return perf_session__list_build_ids();
101} 102}
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index b39f3a1ee7dc..4f19513d7dda 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -9,7 +9,9 @@
9#include "util/debug.h" 9#include "util/debug.h"
10#include "util/event.h" 10#include "util/event.h"
11#include "util/hist.h" 11#include "util/hist.h"
12#include "util/evsel.h"
12#include "util/session.h" 13#include "util/session.h"
14#include "util/tool.h"
13#include "util/sort.h" 15#include "util/sort.h"
14#include "util/symbol.h" 16#include "util/symbol.h"
15#include "util/util.h" 17#include "util/util.h"
@@ -30,14 +32,15 @@ static int hists__add_entry(struct hists *self,
30 return -ENOMEM; 32 return -ENOMEM;
31} 33}
32 34
33static int diff__process_sample_event(union perf_event *event, 35static int diff__process_sample_event(struct perf_tool *tool __used,
36 union perf_event *event,
34 struct perf_sample *sample, 37 struct perf_sample *sample,
35 struct perf_evsel *evsel __used, 38 struct perf_evsel *evsel __used,
36 struct perf_session *session) 39 struct machine *machine)
37{ 40{
38 struct addr_location al; 41 struct addr_location al;
39 42
40 if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 43 if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) {
41 pr_warning("problem processing %d event, skipping it.\n", 44 pr_warning("problem processing %d event, skipping it.\n",
42 event->header.type); 45 event->header.type);
43 return -1; 46 return -1;
@@ -46,16 +49,16 @@ static int diff__process_sample_event(union perf_event *event,
46 if (al.filtered || al.sym == NULL) 49 if (al.filtered || al.sym == NULL)
47 return 0; 50 return 0;
48 51
49 if (hists__add_entry(&session->hists, &al, sample->period)) { 52 if (hists__add_entry(&evsel->hists, &al, sample->period)) {
50 pr_warning("problem incrementing symbol period, skipping event\n"); 53 pr_warning("problem incrementing symbol period, skipping event\n");
51 return -1; 54 return -1;
52 } 55 }
53 56
54 session->hists.stats.total_period += sample->period; 57 evsel->hists.stats.total_period += sample->period;
55 return 0; 58 return 0;
56} 59}
57 60
58static struct perf_event_ops event_ops = { 61static struct perf_tool perf_diff = {
59 .sample = diff__process_sample_event, 62 .sample = diff__process_sample_event,
60 .mmap = perf_event__process_mmap, 63 .mmap = perf_event__process_mmap,
61 .comm = perf_event__process_comm, 64 .comm = perf_event__process_comm,
@@ -145,13 +148,13 @@ static int __cmd_diff(void)
145 int ret, i; 148 int ret, i;
146 struct perf_session *session[2]; 149 struct perf_session *session[2];
147 150
148 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops); 151 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &perf_diff);
149 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops); 152 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &perf_diff);
150 if (session[0] == NULL || session[1] == NULL) 153 if (session[0] == NULL || session[1] == NULL)
151 return -ENOMEM; 154 return -ENOMEM;
152 155
153 for (i = 0; i < 2; ++i) { 156 for (i = 0; i < 2; ++i) {
154 ret = perf_session__process_events(session[i], &event_ops); 157 ret = perf_session__process_events(session[i], &perf_diff);
155 if (ret) 158 if (ret)
156 goto out_delete; 159 goto out_delete;
157 } 160 }
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 4c5e9e04a41f..26760322c4f4 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,7 +15,7 @@
15#include "util/parse-options.h" 15#include "util/parse-options.h"
16#include "util/session.h" 16#include "util/session.h"
17 17
18static char const *input_name = "perf.data"; 18static const char *input_name;
19 19
20static int __cmd_evlist(void) 20static int __cmd_evlist(void)
21{ 21{
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 8dfc12bb119b..09c106193e65 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -9,6 +9,7 @@
9 9
10#include "perf.h" 10#include "perf.h"
11#include "util/session.h" 11#include "util/session.h"
12#include "util/tool.h"
12#include "util/debug.h" 13#include "util/debug.h"
13 14
14#include "util/parse-options.h" 15#include "util/parse-options.h"
@@ -16,8 +17,9 @@
16static char const *input_name = "-"; 17static char const *input_name = "-";
17static bool inject_build_ids; 18static bool inject_build_ids;
18 19
19static int perf_event__repipe_synth(union perf_event *event, 20static int perf_event__repipe_synth(struct perf_tool *tool __used,
20 struct perf_session *session __used) 21 union perf_event *event,
22 struct machine *machine __used)
21{ 23{
22 uint32_t size; 24 uint32_t size;
23 void *buf = event; 25 void *buf = event;
@@ -36,41 +38,70 @@ static int perf_event__repipe_synth(union perf_event *event,
36 return 0; 38 return 0;
37} 39}
38 40
39static int perf_event__repipe(union perf_event *event, 41static int perf_event__repipe_op2_synth(struct perf_tool *tool,
42 union perf_event *event,
43 struct perf_session *session __used)
44{
45 return perf_event__repipe_synth(tool, event, NULL);
46}
47
48static int perf_event__repipe_event_type_synth(struct perf_tool *tool,
49 union perf_event *event)
50{
51 return perf_event__repipe_synth(tool, event, NULL);
52}
53
54static int perf_event__repipe_tracing_data_synth(union perf_event *event,
55 struct perf_session *session __used)
56{
57 return perf_event__repipe_synth(NULL, event, NULL);
58}
59
60static int perf_event__repipe_attr(union perf_event *event,
61 struct perf_evlist **pevlist __used)
62{
63 return perf_event__repipe_synth(NULL, event, NULL);
64}
65
66static int perf_event__repipe(struct perf_tool *tool,
67 union perf_event *event,
40 struct perf_sample *sample __used, 68 struct perf_sample *sample __used,
41 struct perf_session *session) 69 struct machine *machine)
42{ 70{
43 return perf_event__repipe_synth(event, session); 71 return perf_event__repipe_synth(tool, event, machine);
44} 72}
45 73
46static int perf_event__repipe_sample(union perf_event *event, 74static int perf_event__repipe_sample(struct perf_tool *tool,
75 union perf_event *event,
47 struct perf_sample *sample __used, 76 struct perf_sample *sample __used,
48 struct perf_evsel *evsel __used, 77 struct perf_evsel *evsel __used,
49 struct perf_session *session) 78 struct machine *machine)
50{ 79{
51 return perf_event__repipe_synth(event, session); 80 return perf_event__repipe_synth(tool, event, machine);
52} 81}
53 82
54static int perf_event__repipe_mmap(union perf_event *event, 83static int perf_event__repipe_mmap(struct perf_tool *tool,
84 union perf_event *event,
55 struct perf_sample *sample, 85 struct perf_sample *sample,
56 struct perf_session *session) 86 struct machine *machine)
57{ 87{
58 int err; 88 int err;
59 89
60 err = perf_event__process_mmap(event, sample, session); 90 err = perf_event__process_mmap(tool, event, sample, machine);
61 perf_event__repipe(event, sample, session); 91 perf_event__repipe(tool, event, sample, machine);
62 92
63 return err; 93 return err;
64} 94}
65 95
66static int perf_event__repipe_task(union perf_event *event, 96static int perf_event__repipe_task(struct perf_tool *tool,
97 union perf_event *event,
67 struct perf_sample *sample, 98 struct perf_sample *sample,
68 struct perf_session *session) 99 struct machine *machine)
69{ 100{
70 int err; 101 int err;
71 102
72 err = perf_event__process_task(event, sample, session); 103 err = perf_event__process_task(tool, event, sample, machine);
73 perf_event__repipe(event, sample, session); 104 perf_event__repipe(tool, event, sample, machine);
74 105
75 return err; 106 return err;
76} 107}
@@ -80,7 +111,7 @@ static int perf_event__repipe_tracing_data(union perf_event *event,
80{ 111{
81 int err; 112 int err;
82 113
83 perf_event__repipe_synth(event, session); 114 perf_event__repipe_synth(NULL, event, NULL);
84 err = perf_event__process_tracing_data(event, session); 115 err = perf_event__process_tracing_data(event, session);
85 116
86 return err; 117 return err;
@@ -100,10 +131,10 @@ static int dso__read_build_id(struct dso *self)
100 return -1; 131 return -1;
101} 132}
102 133
103static int dso__inject_build_id(struct dso *self, struct perf_session *session) 134static int dso__inject_build_id(struct dso *self, struct perf_tool *tool,
135 struct machine *machine)
104{ 136{
105 u16 misc = PERF_RECORD_MISC_USER; 137 u16 misc = PERF_RECORD_MISC_USER;
106 struct machine *machine;
107 int err; 138 int err;
108 139
109 if (dso__read_build_id(self) < 0) { 140 if (dso__read_build_id(self) < 0) {
@@ -111,17 +142,11 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
111 return -1; 142 return -1;
112 } 143 }
113 144
114 machine = perf_session__find_host_machine(session);
115 if (machine == NULL) {
116 pr_err("Can't find machine for session\n");
117 return -1;
118 }
119
120 if (self->kernel) 145 if (self->kernel)
121 misc = PERF_RECORD_MISC_KERNEL; 146 misc = PERF_RECORD_MISC_KERNEL;
122 147
123 err = perf_event__synthesize_build_id(self, misc, perf_event__repipe, 148 err = perf_event__synthesize_build_id(tool, self, misc, perf_event__repipe,
124 machine, session); 149 machine);
125 if (err) { 150 if (err) {
126 pr_err("Can't synthesize build_id event for %s\n", self->long_name); 151 pr_err("Can't synthesize build_id event for %s\n", self->long_name);
127 return -1; 152 return -1;
@@ -130,10 +155,11 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
130 return 0; 155 return 0;
131} 156}
132 157
133static int perf_event__inject_buildid(union perf_event *event, 158static int perf_event__inject_buildid(struct perf_tool *tool,
159 union perf_event *event,
134 struct perf_sample *sample, 160 struct perf_sample *sample,
135 struct perf_evsel *evsel __used, 161 struct perf_evsel *evsel __used,
136 struct perf_session *session) 162 struct machine *machine)
137{ 163{
138 struct addr_location al; 164 struct addr_location al;
139 struct thread *thread; 165 struct thread *thread;
@@ -141,21 +167,21 @@ static int perf_event__inject_buildid(union perf_event *event,
141 167
142 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 168 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
143 169
144 thread = perf_session__findnew(session, event->ip.pid); 170 thread = machine__findnew_thread(machine, event->ip.pid);
145 if (thread == NULL) { 171 if (thread == NULL) {
146 pr_err("problem processing %d event, skipping it.\n", 172 pr_err("problem processing %d event, skipping it.\n",
147 event->header.type); 173 event->header.type);
148 goto repipe; 174 goto repipe;
149 } 175 }
150 176
151 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 177 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
152 event->ip.pid, event->ip.ip, &al); 178 event->ip.ip, &al);
153 179
154 if (al.map != NULL) { 180 if (al.map != NULL) {
155 if (!al.map->dso->hit) { 181 if (!al.map->dso->hit) {
156 al.map->dso->hit = 1; 182 al.map->dso->hit = 1;
157 if (map__load(al.map, NULL) >= 0) { 183 if (map__load(al.map, NULL) >= 0) {
158 dso__inject_build_id(al.map->dso, session); 184 dso__inject_build_id(al.map->dso, tool, machine);
159 /* 185 /*
160 * If this fails, too bad, let the other side 186 * If this fails, too bad, let the other side
161 * account this as unresolved. 187 * account this as unresolved.
@@ -168,24 +194,24 @@ static int perf_event__inject_buildid(union perf_event *event,
168 } 194 }
169 195
170repipe: 196repipe:
171 perf_event__repipe(event, sample, session); 197 perf_event__repipe(tool, event, sample, machine);
172 return 0; 198 return 0;
173} 199}
174 200
175struct perf_event_ops inject_ops = { 201struct perf_tool perf_inject = {
176 .sample = perf_event__repipe_sample, 202 .sample = perf_event__repipe_sample,
177 .mmap = perf_event__repipe, 203 .mmap = perf_event__repipe,
178 .comm = perf_event__repipe, 204 .comm = perf_event__repipe,
179 .fork = perf_event__repipe, 205 .fork = perf_event__repipe,
180 .exit = perf_event__repipe, 206 .exit = perf_event__repipe,
181 .lost = perf_event__repipe, 207 .lost = perf_event__repipe,
182 .read = perf_event__repipe, 208 .read = perf_event__repipe_sample,
183 .throttle = perf_event__repipe, 209 .throttle = perf_event__repipe,
184 .unthrottle = perf_event__repipe, 210 .unthrottle = perf_event__repipe,
185 .attr = perf_event__repipe_synth, 211 .attr = perf_event__repipe_attr,
186 .event_type = perf_event__repipe_synth, 212 .event_type = perf_event__repipe_event_type_synth,
187 .tracing_data = perf_event__repipe_synth, 213 .tracing_data = perf_event__repipe_tracing_data_synth,
188 .build_id = perf_event__repipe_synth, 214 .build_id = perf_event__repipe_op2_synth,
189}; 215};
190 216
191extern volatile int session_done; 217extern volatile int session_done;
@@ -203,17 +229,17 @@ static int __cmd_inject(void)
203 signal(SIGINT, sig_handler); 229 signal(SIGINT, sig_handler);
204 230
205 if (inject_build_ids) { 231 if (inject_build_ids) {
206 inject_ops.sample = perf_event__inject_buildid; 232 perf_inject.sample = perf_event__inject_buildid;
207 inject_ops.mmap = perf_event__repipe_mmap; 233 perf_inject.mmap = perf_event__repipe_mmap;
208 inject_ops.fork = perf_event__repipe_task; 234 perf_inject.fork = perf_event__repipe_task;
209 inject_ops.tracing_data = perf_event__repipe_tracing_data; 235 perf_inject.tracing_data = perf_event__repipe_tracing_data;
210 } 236 }
211 237
212 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops); 238 session = perf_session__new(input_name, O_RDONLY, false, true, &perf_inject);
213 if (session == NULL) 239 if (session == NULL)
214 return -ENOMEM; 240 return -ENOMEM;
215 241
216 ret = perf_session__process_events(session, &inject_ops); 242 ret = perf_session__process_events(session, &perf_inject);
217 243
218 perf_session__delete(session); 244 perf_session__delete(session);
219 245
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 225e963df105..fe1ad8f21961 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -7,6 +7,7 @@
7#include "util/thread.h" 7#include "util/thread.h"
8#include "util/header.h" 8#include "util/header.h"
9#include "util/session.h" 9#include "util/session.h"
10#include "util/tool.h"
10 11
11#include "util/parse-options.h" 12#include "util/parse-options.h"
12#include "util/trace-event.h" 13#include "util/trace-event.h"
@@ -18,7 +19,7 @@
18struct alloc_stat; 19struct alloc_stat;
19typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *); 20typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
20 21
21static char const *input_name = "perf.data"; 22static const char *input_name;
22 23
23static int alloc_flag; 24static int alloc_flag;
24static int caller_flag; 25static int caller_flag;
@@ -303,12 +304,13 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
303 } 304 }
304} 305}
305 306
306static int process_sample_event(union perf_event *event, 307static int process_sample_event(struct perf_tool *tool __used,
308 union perf_event *event,
307 struct perf_sample *sample, 309 struct perf_sample *sample,
308 struct perf_evsel *evsel __used, 310 struct perf_evsel *evsel __used,
309 struct perf_session *session) 311 struct machine *machine)
310{ 312{
311 struct thread *thread = perf_session__findnew(session, event->ip.pid); 313 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
312 314
313 if (thread == NULL) { 315 if (thread == NULL) {
314 pr_debug("problem processing %d event, skipping it.\n", 316 pr_debug("problem processing %d event, skipping it.\n",
@@ -324,7 +326,7 @@ static int process_sample_event(union perf_event *event,
324 return 0; 326 return 0;
325} 327}
326 328
327static struct perf_event_ops event_ops = { 329static struct perf_tool perf_kmem = {
328 .sample = process_sample_event, 330 .sample = process_sample_event,
329 .comm = perf_event__process_comm, 331 .comm = perf_event__process_comm,
330 .ordered_samples = true, 332 .ordered_samples = true,
@@ -483,7 +485,7 @@ static int __cmd_kmem(void)
483{ 485{
484 int err = -EINVAL; 486 int err = -EINVAL;
485 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 487 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
486 0, false, &event_ops); 488 0, false, &perf_kmem);
487 if (session == NULL) 489 if (session == NULL)
488 return -ENOMEM; 490 return -ENOMEM;
489 491
@@ -494,7 +496,7 @@ static int __cmd_kmem(void)
494 goto out_delete; 496 goto out_delete;
495 497
496 setup_pager(); 498 setup_pager();
497 err = perf_session__process_events(session, &event_ops); 499 err = perf_session__process_events(session, &perf_kmem);
498 if (err != 0) 500 if (err != 0)
499 goto out_delete; 501 goto out_delete;
500 sort_result(); 502 sort_result();
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 34d1e853829d..032324a76b87 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -38,7 +38,7 @@ static const struct option kvm_options[] = {
38 OPT_BOOLEAN(0, "guest", &perf_guest, 38 OPT_BOOLEAN(0, "guest", &perf_guest,
39 "Collect guest os data"), 39 "Collect guest os data"),
40 OPT_BOOLEAN(0, "host", &perf_host, 40 OPT_BOOLEAN(0, "host", &perf_host,
41 "Collect guest os data"), 41 "Collect host os data"),
42 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory", 42 OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
43 "guest mount directory under which every guest os" 43 "guest mount directory under which every guest os"
44 " instance has a subdir"), 44 " instance has a subdir"),
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 899080ace267..2296c391d0f5 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -12,6 +12,7 @@
12 12
13#include "util/debug.h" 13#include "util/debug.h"
14#include "util/session.h" 14#include "util/session.h"
15#include "util/tool.h"
15 16
16#include <sys/types.h> 17#include <sys/types.h>
17#include <sys/prctl.h> 18#include <sys/prctl.h>
@@ -325,7 +326,7 @@ alloc_failed:
325 die("memory allocation failed\n"); 326 die("memory allocation failed\n");
326} 327}
327 328
328static char const *input_name = "perf.data"; 329static const char *input_name;
329 330
330struct raw_event_sample { 331struct raw_event_sample {
331 u32 size; 332 u32 size;
@@ -845,12 +846,13 @@ static void dump_info(void)
845 die("Unknown type of information\n"); 846 die("Unknown type of information\n");
846} 847}
847 848
848static int process_sample_event(union perf_event *event, 849static int process_sample_event(struct perf_tool *tool __used,
850 union perf_event *event,
849 struct perf_sample *sample, 851 struct perf_sample *sample,
850 struct perf_evsel *evsel __used, 852 struct perf_evsel *evsel __used,
851 struct perf_session *s) 853 struct machine *machine)
852{ 854{
853 struct thread *thread = perf_session__findnew(s, sample->tid); 855 struct thread *thread = machine__findnew_thread(machine, sample->tid);
854 856
855 if (thread == NULL) { 857 if (thread == NULL) {
856 pr_debug("problem processing %d event, skipping it.\n", 858 pr_debug("problem processing %d event, skipping it.\n",
@@ -863,7 +865,7 @@ static int process_sample_event(union perf_event *event,
863 return 0; 865 return 0;
864} 866}
865 867
866static struct perf_event_ops eops = { 868static struct perf_tool eops = {
867 .sample = process_sample_event, 869 .sample = process_sample_event,
868 .comm = perf_event__process_comm, 870 .comm = perf_event__process_comm,
869 .ordered_samples = true, 871 .ordered_samples = true,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 710ae3d0a489..59d43abfbfec 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -46,7 +46,6 @@
46 46
47#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 47#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
48#define DEFAULT_FUNC_FILTER "!_*" 48#define DEFAULT_FUNC_FILTER "!_*"
49#define MAX_PATH_LEN 256
50 49
51/* Session management structure */ 50/* Session management structure */
52static struct { 51static struct {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6ab58cc99d53..0abfb18b911f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -22,6 +22,7 @@
22#include "util/evsel.h" 22#include "util/evsel.h"
23#include "util/debug.h" 23#include "util/debug.h"
24#include "util/session.h" 24#include "util/session.h"
25#include "util/tool.h"
25#include "util/symbol.h" 26#include "util/symbol.h"
26#include "util/cpumap.h" 27#include "util/cpumap.h"
27#include "util/thread_map.h" 28#include "util/thread_map.h"
@@ -35,55 +36,36 @@ enum write_mode_t {
35 WRITE_APPEND 36 WRITE_APPEND
36}; 37};
37 38
38static u64 user_interval = ULLONG_MAX; 39struct perf_record {
39static u64 default_interval = 0; 40 struct perf_tool tool;
40 41 struct perf_record_opts opts;
41static unsigned int page_size; 42 u64 bytes_written;
42static unsigned int mmap_pages = UINT_MAX; 43 const char *output_name;
43static unsigned int user_freq = UINT_MAX; 44 struct perf_evlist *evlist;
44static int freq = 1000; 45 struct perf_session *session;
45static int output; 46 const char *progname;
46static int pipe_output = 0; 47 int output;
47static const char *output_name = NULL; 48 unsigned int page_size;
48static bool group = false; 49 int realtime_prio;
49static int realtime_prio = 0; 50 enum write_mode_t write_mode;
50static bool nodelay = false; 51 bool no_buildid;
51static bool raw_samples = false; 52 bool no_buildid_cache;
52static bool sample_id_all_avail = true; 53 bool force;
53static bool system_wide = false; 54 bool file_new;
54static pid_t target_pid = -1; 55 bool append_file;
55static pid_t target_tid = -1; 56 long samples;
56static pid_t child_pid = -1; 57 off_t post_processing_offset;
57static bool no_inherit = false; 58};
58static enum write_mode_t write_mode = WRITE_FORCE; 59
59static bool call_graph = false; 60static void advance_output(struct perf_record *rec, size_t size)
60static bool inherit_stat = false;
61static bool no_samples = false;
62static bool sample_address = false;
63static bool sample_time = false;
64static bool no_buildid = false;
65static bool no_buildid_cache = false;
66static struct perf_evlist *evsel_list;
67
68static long samples = 0;
69static u64 bytes_written = 0;
70
71static int file_new = 1;
72static off_t post_processing_offset;
73
74static struct perf_session *session;
75static const char *cpu_list;
76static const char *progname;
77
78static void advance_output(size_t size)
79{ 61{
80 bytes_written += size; 62 rec->bytes_written += size;
81} 63}
82 64
83static void write_output(void *buf, size_t size) 65static void write_output(struct perf_record *rec, void *buf, size_t size)
84{ 66{
85 while (size) { 67 while (size) {
86 int ret = write(output, buf, size); 68 int ret = write(rec->output, buf, size);
87 69
88 if (ret < 0) 70 if (ret < 0)
89 die("failed to write"); 71 die("failed to write");
@@ -91,30 +73,33 @@ static void write_output(void *buf, size_t size)
91 size -= ret; 73 size -= ret;
92 buf += ret; 74 buf += ret;
93 75
94 bytes_written += ret; 76 rec->bytes_written += ret;
95 } 77 }
96} 78}
97 79
98static int process_synthesized_event(union perf_event *event, 80static int process_synthesized_event(struct perf_tool *tool,
81 union perf_event *event,
99 struct perf_sample *sample __used, 82 struct perf_sample *sample __used,
100 struct perf_session *self __used) 83 struct machine *machine __used)
101{ 84{
102 write_output(event, event->header.size); 85 struct perf_record *rec = container_of(tool, struct perf_record, tool);
86 write_output(rec, event, event->header.size);
103 return 0; 87 return 0;
104} 88}
105 89
106static void mmap_read(struct perf_mmap *md) 90static void perf_record__mmap_read(struct perf_record *rec,
91 struct perf_mmap *md)
107{ 92{
108 unsigned int head = perf_mmap__read_head(md); 93 unsigned int head = perf_mmap__read_head(md);
109 unsigned int old = md->prev; 94 unsigned int old = md->prev;
110 unsigned char *data = md->base + page_size; 95 unsigned char *data = md->base + rec->page_size;
111 unsigned long size; 96 unsigned long size;
112 void *buf; 97 void *buf;
113 98
114 if (old == head) 99 if (old == head)
115 return; 100 return;
116 101
117 samples++; 102 rec->samples++;
118 103
119 size = head - old; 104 size = head - old;
120 105
@@ -123,14 +108,14 @@ static void mmap_read(struct perf_mmap *md)
123 size = md->mask + 1 - (old & md->mask); 108 size = md->mask + 1 - (old & md->mask);
124 old += size; 109 old += size;
125 110
126 write_output(buf, size); 111 write_output(rec, buf, size);
127 } 112 }
128 113
129 buf = &data[old & md->mask]; 114 buf = &data[old & md->mask];
130 size = head - old; 115 size = head - old;
131 old += size; 116 old += size;
132 117
133 write_output(buf, size); 118 write_output(rec, buf, size);
134 119
135 md->prev = old; 120 md->prev = old;
136 perf_mmap__write_tail(md, old); 121 perf_mmap__write_tail(md, old);
@@ -149,17 +134,18 @@ static void sig_handler(int sig)
149 signr = sig; 134 signr = sig;
150} 135}
151 136
152static void sig_atexit(void) 137static void perf_record__sig_exit(int exit_status __used, void *arg)
153{ 138{
139 struct perf_record *rec = arg;
154 int status; 140 int status;
155 141
156 if (child_pid > 0) { 142 if (rec->evlist->workload.pid > 0) {
157 if (!child_finished) 143 if (!child_finished)
158 kill(child_pid, SIGTERM); 144 kill(rec->evlist->workload.pid, SIGTERM);
159 145
160 wait(&status); 146 wait(&status);
161 if (WIFSIGNALED(status)) 147 if (WIFSIGNALED(status))
162 psignal(WTERMSIG(status), progname); 148 psignal(WTERMSIG(status), rec->progname);
163 } 149 }
164 150
165 if (signr == -1 || signr == SIGUSR1) 151 if (signr == -1 || signr == SIGUSR1)
@@ -169,78 +155,6 @@ static void sig_atexit(void)
169 kill(getpid(), signr); 155 kill(getpid(), signr);
170} 156}
171 157
172static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
173{
174 struct perf_event_attr *attr = &evsel->attr;
175 int track = !evsel->idx; /* only the first counter needs these */
176
177 attr->disabled = 1;
178 attr->inherit = !no_inherit;
179 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING |
181 PERF_FORMAT_ID;
182
183 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
184
185 if (evlist->nr_entries > 1)
186 attr->sample_type |= PERF_SAMPLE_ID;
187
188 /*
189 * We default some events to a 1 default interval. But keep
190 * it a weak assumption overridable by the user.
191 */
192 if (!attr->sample_period || (user_freq != UINT_MAX &&
193 user_interval != ULLONG_MAX)) {
194 if (freq) {
195 attr->sample_type |= PERF_SAMPLE_PERIOD;
196 attr->freq = 1;
197 attr->sample_freq = freq;
198 } else {
199 attr->sample_period = default_interval;
200 }
201 }
202
203 if (no_samples)
204 attr->sample_freq = 0;
205
206 if (inherit_stat)
207 attr->inherit_stat = 1;
208
209 if (sample_address) {
210 attr->sample_type |= PERF_SAMPLE_ADDR;
211 attr->mmap_data = track;
212 }
213
214 if (call_graph)
215 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
216
217 if (system_wide)
218 attr->sample_type |= PERF_SAMPLE_CPU;
219
220 if (sample_id_all_avail &&
221 (sample_time || system_wide || !no_inherit || cpu_list))
222 attr->sample_type |= PERF_SAMPLE_TIME;
223
224 if (raw_samples) {
225 attr->sample_type |= PERF_SAMPLE_TIME;
226 attr->sample_type |= PERF_SAMPLE_RAW;
227 attr->sample_type |= PERF_SAMPLE_CPU;
228 }
229
230 if (nodelay) {
231 attr->watermark = 0;
232 attr->wakeup_events = 1;
233 }
234
235 attr->mmap = track;
236 attr->comm = track;
237
238 if (target_pid == -1 && target_tid == -1 && !system_wide) {
239 attr->disabled = 1;
240 attr->enable_on_exec = 1;
241 }
242}
243
244static bool perf_evlist__equal(struct perf_evlist *evlist, 158static bool perf_evlist__equal(struct perf_evlist *evlist,
245 struct perf_evlist *other) 159 struct perf_evlist *other)
246{ 160{
@@ -260,15 +174,17 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
260 return true; 174 return true;
261} 175}
262 176
263static void open_counters(struct perf_evlist *evlist) 177static void perf_record__open(struct perf_record *rec)
264{ 178{
265 struct perf_evsel *pos, *first; 179 struct perf_evsel *pos, *first;
266 180 struct perf_evlist *evlist = rec->evlist;
267 if (evlist->cpus->map[0] < 0) 181 struct perf_session *session = rec->session;
268 no_inherit = true; 182 struct perf_record_opts *opts = &rec->opts;
269 183
270 first = list_entry(evlist->entries.next, struct perf_evsel, node); 184 first = list_entry(evlist->entries.next, struct perf_evsel, node);
271 185
186 perf_evlist__config_attrs(evlist, opts);
187
272 list_for_each_entry(pos, &evlist->entries, node) { 188 list_for_each_entry(pos, &evlist->entries, node) {
273 struct perf_event_attr *attr = &pos->attr; 189 struct perf_event_attr *attr = &pos->attr;
274 struct xyarray *group_fd = NULL; 190 struct xyarray *group_fd = NULL;
@@ -286,29 +202,27 @@ static void open_counters(struct perf_evlist *evlist)
286 */ 202 */
287 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME; 203 bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
288 204
289 if (group && pos != first) 205 if (opts->group && pos != first)
290 group_fd = first->fd; 206 group_fd = first->fd;
291
292 config_attr(pos, evlist);
293retry_sample_id: 207retry_sample_id:
294 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 208 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
295try_again: 209try_again:
296 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, 210 if (perf_evsel__open(pos, evlist->cpus, evlist->threads,
297 group_fd) < 0) { 211 opts->group, group_fd) < 0) {
298 int err = errno; 212 int err = errno;
299 213
300 if (err == EPERM || err == EACCES) { 214 if (err == EPERM || err == EACCES) {
301 ui__error_paranoid(); 215 ui__error_paranoid();
302 exit(EXIT_FAILURE); 216 exit(EXIT_FAILURE);
303 } else if (err == ENODEV && cpu_list) { 217 } else if (err == ENODEV && opts->cpu_list) {
304 die("No such device - did you specify" 218 die("No such device - did you specify"
305 " an out-of-range profile CPU?\n"); 219 " an out-of-range profile CPU?\n");
306 } else if (err == EINVAL && sample_id_all_avail) { 220 } else if (err == EINVAL && opts->sample_id_all_avail) {
307 /* 221 /*
308 * Old kernel, no attr->sample_id_type_all field 222 * Old kernel, no attr->sample_id_type_all field
309 */ 223 */
310 sample_id_all_avail = false; 224 opts->sample_id_all_avail = false;
311 if (!sample_time && !raw_samples && !time_needed) 225 if (!opts->sample_time && !opts->raw_samples && !time_needed)
312 attr->sample_type &= ~PERF_SAMPLE_TIME; 226 attr->sample_type &= ~PERF_SAMPLE_TIME;
313 227
314 goto retry_sample_id; 228 goto retry_sample_id;
@@ -358,10 +272,20 @@ try_again:
358 exit(-1); 272 exit(-1);
359 } 273 }
360 274
361 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) 275 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
276 if (errno == EPERM)
277 die("Permission error mapping pages.\n"
278 "Consider increasing "
279 "/proc/sys/kernel/perf_event_mlock_kb,\n"
280 "or try again with a smaller value of -m/--mmap_pages.\n"
281 "(current value: %d)\n", opts->mmap_pages);
282 else if (!is_power_of_2(opts->mmap_pages))
283 die("--mmap_pages/-m value must be a power of two.");
284
362 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 285 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
286 }
363 287
364 if (file_new) 288 if (rec->file_new)
365 session->evlist = evlist; 289 session->evlist = evlist;
366 else { 290 else {
367 if (!perf_evlist__equal(session->evlist, evlist)) { 291 if (!perf_evlist__equal(session->evlist, evlist)) {
@@ -373,29 +297,32 @@ try_again:
373 perf_session__update_sample_type(session); 297 perf_session__update_sample_type(session);
374} 298}
375 299
376static int process_buildids(void) 300static int process_buildids(struct perf_record *rec)
377{ 301{
378 u64 size = lseek(output, 0, SEEK_CUR); 302 u64 size = lseek(rec->output, 0, SEEK_CUR);
379 303
380 if (size == 0) 304 if (size == 0)
381 return 0; 305 return 0;
382 306
383 session->fd = output; 307 rec->session->fd = rec->output;
384 return __perf_session__process_events(session, post_processing_offset, 308 return __perf_session__process_events(rec->session, rec->post_processing_offset,
385 size - post_processing_offset, 309 size - rec->post_processing_offset,
386 size, &build_id__mark_dso_hit_ops); 310 size, &build_id__mark_dso_hit_ops);
387} 311}
388 312
389static void atexit_header(void) 313static void perf_record__exit(int status __used, void *arg)
390{ 314{
391 if (!pipe_output) { 315 struct perf_record *rec = arg;
392 session->header.data_size += bytes_written; 316
393 317 if (!rec->opts.pipe_output) {
394 if (!no_buildid) 318 rec->session->header.data_size += rec->bytes_written;
395 process_buildids(); 319
396 perf_session__write_header(session, evsel_list, output, true); 320 if (!rec->no_buildid)
397 perf_session__delete(session); 321 process_buildids(rec);
398 perf_evlist__delete(evsel_list); 322 perf_session__write_header(rec->session, rec->evlist,
323 rec->output, true);
324 perf_session__delete(rec->session);
325 perf_evlist__delete(rec->evlist);
399 symbol__exit(); 326 symbol__exit();
400 } 327 }
401} 328}
@@ -403,7 +330,7 @@ static void atexit_header(void)
403static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 330static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
404{ 331{
405 int err; 332 int err;
406 struct perf_session *psession = data; 333 struct perf_tool *tool = data;
407 334
408 if (machine__is_host(machine)) 335 if (machine__is_host(machine))
409 return; 336 return;
@@ -416,8 +343,8 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
416 *method is used to avoid symbol missing when the first addr is 343 *method is used to avoid symbol missing when the first addr is
417 *in module instead of in guest kernel. 344 *in module instead of in guest kernel.
418 */ 345 */
419 err = perf_event__synthesize_modules(process_synthesized_event, 346 err = perf_event__synthesize_modules(tool, process_synthesized_event,
420 psession, machine); 347 machine);
421 if (err < 0) 348 if (err < 0)
422 pr_err("Couldn't record guest kernel [%d]'s reference" 349 pr_err("Couldn't record guest kernel [%d]'s reference"
423 " relocation symbol.\n", machine->pid); 350 " relocation symbol.\n", machine->pid);
@@ -426,12 +353,11 @@ static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
426 * We use _stext for guest kernel because guest kernel's /proc/kallsyms 353 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
427 * have no _text sometimes. 354 * have no _text sometimes.
428 */ 355 */
429 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 356 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
430 psession, machine, "_text"); 357 machine, "_text");
431 if (err < 0) 358 if (err < 0)
432 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 359 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
433 psession, machine, 360 machine, "_stext");
434 "_stext");
435 if (err < 0) 361 if (err < 0)
436 pr_err("Couldn't record guest kernel [%d]'s reference" 362 pr_err("Couldn't record guest kernel [%d]'s reference"
437 " relocation symbol.\n", machine->pid); 363 " relocation symbol.\n", machine->pid);
@@ -442,73 +368,71 @@ static struct perf_event_header finished_round_event = {
442 .type = PERF_RECORD_FINISHED_ROUND, 368 .type = PERF_RECORD_FINISHED_ROUND,
443}; 369};
444 370
445static void mmap_read_all(void) 371static void perf_record__mmap_read_all(struct perf_record *rec)
446{ 372{
447 int i; 373 int i;
448 374
449 for (i = 0; i < evsel_list->nr_mmaps; i++) { 375 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
450 if (evsel_list->mmap[i].base) 376 if (rec->evlist->mmap[i].base)
451 mmap_read(&evsel_list->mmap[i]); 377 perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
452 } 378 }
453 379
454 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 380 if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
455 write_output(&finished_round_event, sizeof(finished_round_event)); 381 write_output(rec, &finished_round_event, sizeof(finished_round_event));
456} 382}
457 383
458static int __cmd_record(int argc, const char **argv) 384static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
459{ 385{
460 struct stat st; 386 struct stat st;
461 int flags; 387 int flags;
462 int err; 388 int err, output;
463 unsigned long waking = 0; 389 unsigned long waking = 0;
464 int child_ready_pipe[2], go_pipe[2];
465 const bool forks = argc > 0; 390 const bool forks = argc > 0;
466 char buf;
467 struct machine *machine; 391 struct machine *machine;
392 struct perf_tool *tool = &rec->tool;
393 struct perf_record_opts *opts = &rec->opts;
394 struct perf_evlist *evsel_list = rec->evlist;
395 const char *output_name = rec->output_name;
396 struct perf_session *session;
468 397
469 progname = argv[0]; 398 rec->progname = argv[0];
470 399
471 page_size = sysconf(_SC_PAGE_SIZE); 400 rec->page_size = sysconf(_SC_PAGE_SIZE);
472 401
473 atexit(sig_atexit); 402 on_exit(perf_record__sig_exit, rec);
474 signal(SIGCHLD, sig_handler); 403 signal(SIGCHLD, sig_handler);
475 signal(SIGINT, sig_handler); 404 signal(SIGINT, sig_handler);
476 signal(SIGUSR1, sig_handler); 405 signal(SIGUSR1, sig_handler);
477 406
478 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
479 perror("failed to create pipes");
480 exit(-1);
481 }
482
483 if (!output_name) { 407 if (!output_name) {
484 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 408 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
485 pipe_output = 1; 409 opts->pipe_output = true;
486 else 410 else
487 output_name = "perf.data"; 411 rec->output_name = output_name = "perf.data";
488 } 412 }
489 if (output_name) { 413 if (output_name) {
490 if (!strcmp(output_name, "-")) 414 if (!strcmp(output_name, "-"))
491 pipe_output = 1; 415 opts->pipe_output = true;
492 else if (!stat(output_name, &st) && st.st_size) { 416 else if (!stat(output_name, &st) && st.st_size) {
493 if (write_mode == WRITE_FORCE) { 417 if (rec->write_mode == WRITE_FORCE) {
494 char oldname[PATH_MAX]; 418 char oldname[PATH_MAX];
495 snprintf(oldname, sizeof(oldname), "%s.old", 419 snprintf(oldname, sizeof(oldname), "%s.old",
496 output_name); 420 output_name);
497 unlink(oldname); 421 unlink(oldname);
498 rename(output_name, oldname); 422 rename(output_name, oldname);
499 } 423 }
500 } else if (write_mode == WRITE_APPEND) { 424 } else if (rec->write_mode == WRITE_APPEND) {
501 write_mode = WRITE_FORCE; 425 rec->write_mode = WRITE_FORCE;
502 } 426 }
503 } 427 }
504 428
505 flags = O_CREAT|O_RDWR; 429 flags = O_CREAT|O_RDWR;
506 if (write_mode == WRITE_APPEND) 430 if (rec->write_mode == WRITE_APPEND)
507 file_new = 0; 431 rec->file_new = 0;
508 else 432 else
509 flags |= O_TRUNC; 433 flags |= O_TRUNC;
510 434
511 if (pipe_output) 435 if (opts->pipe_output)
512 output = STDOUT_FILENO; 436 output = STDOUT_FILENO;
513 else 437 else
514 output = open(output_name, flags, S_IRUSR | S_IWUSR); 438 output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -517,17 +441,21 @@ static int __cmd_record(int argc, const char **argv)
517 exit(-1); 441 exit(-1);
518 } 442 }
519 443
444 rec->output = output;
445
520 session = perf_session__new(output_name, O_WRONLY, 446 session = perf_session__new(output_name, O_WRONLY,
521 write_mode == WRITE_FORCE, false, NULL); 447 rec->write_mode == WRITE_FORCE, false, NULL);
522 if (session == NULL) { 448 if (session == NULL) {
523 pr_err("Not enough memory for reading perf file header\n"); 449 pr_err("Not enough memory for reading perf file header\n");
524 return -1; 450 return -1;
525 } 451 }
526 452
527 if (!no_buildid) 453 rec->session = session;
454
455 if (!rec->no_buildid)
528 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 456 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
529 457
530 if (!file_new) { 458 if (!rec->file_new) {
531 err = perf_session__read_header(session, output); 459 err = perf_session__read_header(session, output);
532 if (err < 0) 460 if (err < 0)
533 goto out_delete_session; 461 goto out_delete_session;
@@ -549,94 +477,57 @@ static int __cmd_record(int argc, const char **argv)
549 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 477 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
550 perf_header__set_feat(&session->header, HEADER_CPUID); 478 perf_header__set_feat(&session->header, HEADER_CPUID);
551 479
552 /* 512 kiB: default amount of unprivileged mlocked memory */
553 if (mmap_pages == UINT_MAX)
554 mmap_pages = (512 * 1024) / page_size;
555
556 if (forks) { 480 if (forks) {
557 child_pid = fork(); 481 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
558 if (child_pid < 0) { 482 if (err < 0) {
559 perror("failed to fork"); 483 pr_err("Couldn't run the workload!\n");
560 exit(-1); 484 goto out_delete_session;
561 }
562
563 if (!child_pid) {
564 if (pipe_output)
565 dup2(2, 1);
566 close(child_ready_pipe[0]);
567 close(go_pipe[1]);
568 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
569
570 /*
571 * Do a dummy execvp to get the PLT entry resolved,
572 * so we avoid the resolver overhead on the real
573 * execvp call.
574 */
575 execvp("", (char **)argv);
576
577 /*
578 * Tell the parent we're ready to go
579 */
580 close(child_ready_pipe[1]);
581
582 /*
583 * Wait until the parent tells us to go.
584 */
585 if (read(go_pipe[0], &buf, 1) == -1)
586 perror("unable to read pipe");
587
588 execvp(argv[0], (char **)argv);
589
590 perror(argv[0]);
591 kill(getppid(), SIGUSR1);
592 exit(-1);
593 }
594
595 if (!system_wide && target_tid == -1 && target_pid == -1)
596 evsel_list->threads->map[0] = child_pid;
597
598 close(child_ready_pipe[1]);
599 close(go_pipe[0]);
600 /*
601 * wait for child to settle
602 */
603 if (read(child_ready_pipe[0], &buf, 1) == -1) {
604 perror("unable to read pipe");
605 exit(-1);
606 } 485 }
607 close(child_ready_pipe[0]);
608 } 486 }
609 487
610 open_counters(evsel_list); 488 perf_record__open(rec);
611 489
612 /* 490 /*
613 * perf_session__delete(session) will be called at atexit_header() 491 * perf_session__delete(session) will be called at perf_record__exit()
614 */ 492 */
615 atexit(atexit_header); 493 on_exit(perf_record__exit, rec);
616 494
617 if (pipe_output) { 495 if (opts->pipe_output) {
618 err = perf_header__write_pipe(output); 496 err = perf_header__write_pipe(output);
619 if (err < 0) 497 if (err < 0)
620 return err; 498 return err;
621 } else if (file_new) { 499 } else if (rec->file_new) {
622 err = perf_session__write_header(session, evsel_list, 500 err = perf_session__write_header(session, evsel_list,
623 output, false); 501 output, false);
624 if (err < 0) 502 if (err < 0)
625 return err; 503 return err;
626 } 504 }
627 505
628 post_processing_offset = lseek(output, 0, SEEK_CUR); 506 if (!!rec->no_buildid
507 && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
508 pr_err("Couldn't generating buildids. "
509 "Use --no-buildid to profile anyway.\n");
510 return -1;
511 }
629 512
630 if (pipe_output) { 513 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
631 err = perf_session__synthesize_attrs(session, 514
632 process_synthesized_event); 515 machine = perf_session__find_host_machine(session);
516 if (!machine) {
517 pr_err("Couldn't find native kernel information.\n");
518 return -1;
519 }
520
521 if (opts->pipe_output) {
522 err = perf_event__synthesize_attrs(tool, session,
523 process_synthesized_event);
633 if (err < 0) { 524 if (err < 0) {
634 pr_err("Couldn't synthesize attrs.\n"); 525 pr_err("Couldn't synthesize attrs.\n");
635 return err; 526 return err;
636 } 527 }
637 528
638 err = perf_event__synthesize_event_types(process_synthesized_event, 529 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
639 session); 530 machine);
640 if (err < 0) { 531 if (err < 0) {
641 pr_err("Couldn't synthesize event_types.\n"); 532 pr_err("Couldn't synthesize event_types.\n");
642 return err; 533 return err;
@@ -651,56 +542,49 @@ static int __cmd_record(int argc, const char **argv)
651 * return this more properly and also 542 * return this more properly and also
652 * propagate errors that now are calling die() 543 * propagate errors that now are calling die()
653 */ 544 */
654 err = perf_event__synthesize_tracing_data(output, evsel_list, 545 err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
655 process_synthesized_event, 546 process_synthesized_event);
656 session);
657 if (err <= 0) { 547 if (err <= 0) {
658 pr_err("Couldn't record tracing data.\n"); 548 pr_err("Couldn't record tracing data.\n");
659 return err; 549 return err;
660 } 550 }
661 advance_output(err); 551 advance_output(rec, err);
662 } 552 }
663 } 553 }
664 554
665 machine = perf_session__find_host_machine(session); 555 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
666 if (!machine) { 556 machine, "_text");
667 pr_err("Couldn't find native kernel information.\n");
668 return -1;
669 }
670
671 err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
672 session, machine, "_text");
673 if (err < 0) 557 if (err < 0)
674 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 558 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
675 session, machine, "_stext"); 559 machine, "_stext");
676 if (err < 0) 560 if (err < 0)
677 pr_err("Couldn't record kernel reference relocation symbol\n" 561 pr_err("Couldn't record kernel reference relocation symbol\n"
678 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 562 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
679 "Check /proc/kallsyms permission or run as root.\n"); 563 "Check /proc/kallsyms permission or run as root.\n");
680 564
681 err = perf_event__synthesize_modules(process_synthesized_event, 565 err = perf_event__synthesize_modules(tool, process_synthesized_event,
682 session, machine); 566 machine);
683 if (err < 0) 567 if (err < 0)
684 pr_err("Couldn't record kernel module information.\n" 568 pr_err("Couldn't record kernel module information.\n"
685 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 569 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
686 "Check /proc/modules permission or run as root.\n"); 570 "Check /proc/modules permission or run as root.\n");
687 571
688 if (perf_guest) 572 if (perf_guest)
689 perf_session__process_machines(session, 573 perf_session__process_machines(session, tool,
690 perf_event__synthesize_guest_os); 574 perf_event__synthesize_guest_os);
691 575
692 if (!system_wide) 576 if (!opts->system_wide)
693 perf_event__synthesize_thread_map(evsel_list->threads, 577 perf_event__synthesize_thread_map(tool, evsel_list->threads,
694 process_synthesized_event, 578 process_synthesized_event,
695 session); 579 machine);
696 else 580 else
697 perf_event__synthesize_threads(process_synthesized_event, 581 perf_event__synthesize_threads(tool, process_synthesized_event,
698 session); 582 machine);
699 583
700 if (realtime_prio) { 584 if (rec->realtime_prio) {
701 struct sched_param param; 585 struct sched_param param;
702 586
703 param.sched_priority = realtime_prio; 587 param.sched_priority = rec->realtime_prio;
704 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 588 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
705 pr_err("Could not set realtime priority.\n"); 589 pr_err("Could not set realtime priority.\n");
706 exit(-1); 590 exit(-1);
@@ -713,14 +597,14 @@ static int __cmd_record(int argc, const char **argv)
713 * Let the child rip 597 * Let the child rip
714 */ 598 */
715 if (forks) 599 if (forks)
716 close(go_pipe[1]); 600 perf_evlist__start_workload(evsel_list);
717 601
718 for (;;) { 602 for (;;) {
719 int hits = samples; 603 int hits = rec->samples;
720 604
721 mmap_read_all(); 605 perf_record__mmap_read_all(rec);
722 606
723 if (hits == samples) { 607 if (hits == rec->samples) {
724 if (done) 608 if (done)
725 break; 609 break;
726 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 610 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
@@ -741,9 +625,9 @@ static int __cmd_record(int argc, const char **argv)
741 */ 625 */
742 fprintf(stderr, 626 fprintf(stderr,
743 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 627 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
744 (double)bytes_written / 1024.0 / 1024.0, 628 (double)rec->bytes_written / 1024.0 / 1024.0,
745 output_name, 629 output_name,
746 bytes_written / 24); 630 rec->bytes_written / 24);
747 631
748 return 0; 632 return 0;
749 633
@@ -758,58 +642,89 @@ static const char * const record_usage[] = {
758 NULL 642 NULL
759}; 643};
760 644
761static bool force, append_file; 645/*
646 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
647 * because we need to have access to it in perf_record__exit, that is called
648 * after cmd_record() exits, but since record_options need to be accessible to
649 * builtin-script, leave it here.
650 *
651 * At least we don't ouch it in all the other functions here directly.
652 *
653 * Just say no to tons of global variables, sigh.
654 */
655static struct perf_record record = {
656 .opts = {
657 .target_pid = -1,
658 .target_tid = -1,
659 .mmap_pages = UINT_MAX,
660 .user_freq = UINT_MAX,
661 .user_interval = ULLONG_MAX,
662 .freq = 1000,
663 .sample_id_all_avail = true,
664 },
665 .write_mode = WRITE_FORCE,
666 .file_new = true,
667};
762 668
669/*
670 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
671 * with it and switch to use the library functions in perf_evlist that came
672 * from builtin-record.c, i.e. use perf_record_opts,
673 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
674 * using pipes, etc.
675 */
763const struct option record_options[] = { 676const struct option record_options[] = {
764 OPT_CALLBACK('e', "event", &evsel_list, "event", 677 OPT_CALLBACK('e', "event", &record.evlist, "event",
765 "event selector. use 'perf list' to list available events", 678 "event selector. use 'perf list' to list available events",
766 parse_events_option), 679 parse_events_option),
767 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 680 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
768 "event filter", parse_filter), 681 "event filter", parse_filter),
769 OPT_INTEGER('p', "pid", &target_pid, 682 OPT_INTEGER('p', "pid", &record.opts.target_pid,
770 "record events on existing process id"), 683 "record events on existing process id"),
771 OPT_INTEGER('t', "tid", &target_tid, 684 OPT_INTEGER('t', "tid", &record.opts.target_tid,
772 "record events on existing thread id"), 685 "record events on existing thread id"),
773 OPT_INTEGER('r', "realtime", &realtime_prio, 686 OPT_INTEGER('r', "realtime", &record.realtime_prio,
774 "collect data with this RT SCHED_FIFO priority"), 687 "collect data with this RT SCHED_FIFO priority"),
775 OPT_BOOLEAN('D', "no-delay", &nodelay, 688 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
776 "collect data without buffering"), 689 "collect data without buffering"),
777 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 690 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
778 "collect raw sample records from all opened counters"), 691 "collect raw sample records from all opened counters"),
779 OPT_BOOLEAN('a', "all-cpus", &system_wide, 692 OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
780 "system-wide collection from all CPUs"), 693 "system-wide collection from all CPUs"),
781 OPT_BOOLEAN('A', "append", &append_file, 694 OPT_BOOLEAN('A', "append", &record.append_file,
782 "append to the output file to do incremental profiling"), 695 "append to the output file to do incremental profiling"),
783 OPT_STRING('C', "cpu", &cpu_list, "cpu", 696 OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
784 "list of cpus to monitor"), 697 "list of cpus to monitor"),
785 OPT_BOOLEAN('f', "force", &force, 698 OPT_BOOLEAN('f', "force", &record.force,
786 "overwrite existing data file (deprecated)"), 699 "overwrite existing data file (deprecated)"),
787 OPT_U64('c', "count", &user_interval, "event period to sample"), 700 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
788 OPT_STRING('o', "output", &output_name, "file", 701 OPT_STRING('o', "output", &record.output_name, "file",
789 "output file name"), 702 "output file name"),
790 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 703 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
791 "child tasks do not inherit counters"), 704 "child tasks do not inherit counters"),
792 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 705 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
793 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 706 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
794 OPT_BOOLEAN(0, "group", &group, 707 "number of mmap data pages"),
708 OPT_BOOLEAN(0, "group", &record.opts.group,
795 "put the counters into a counter group"), 709 "put the counters into a counter group"),
796 OPT_BOOLEAN('g', "call-graph", &call_graph, 710 OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
797 "do call-graph (stack chain/backtrace) recording"), 711 "do call-graph (stack chain/backtrace) recording"),
798 OPT_INCR('v', "verbose", &verbose, 712 OPT_INCR('v', "verbose", &verbose,
799 "be more verbose (show counter open errors, etc)"), 713 "be more verbose (show counter open errors, etc)"),
800 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 714 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
801 OPT_BOOLEAN('s', "stat", &inherit_stat, 715 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
802 "per thread counts"), 716 "per thread counts"),
803 OPT_BOOLEAN('d', "data", &sample_address, 717 OPT_BOOLEAN('d', "data", &record.opts.sample_address,
804 "Sample addresses"), 718 "Sample addresses"),
805 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"), 719 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
806 OPT_BOOLEAN('n', "no-samples", &no_samples, 720 OPT_BOOLEAN('P', "period", &record.opts.period, "Sample period"),
721 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
807 "don't sample"), 722 "don't sample"),
808 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 723 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
809 "do not update the buildid cache"), 724 "do not update the buildid cache"),
810 OPT_BOOLEAN('B', "no-buildid", &no_buildid, 725 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
811 "do not collect buildids in perf.data"), 726 "do not collect buildids in perf.data"),
812 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 727 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
813 "monitor event in cgroup name only", 728 "monitor event in cgroup name only",
814 parse_cgroups), 729 parse_cgroups),
815 OPT_END() 730 OPT_END()
@@ -819,6 +734,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
819{ 734{
820 int err = -ENOMEM; 735 int err = -ENOMEM;
821 struct perf_evsel *pos; 736 struct perf_evsel *pos;
737 struct perf_evlist *evsel_list;
738 struct perf_record *rec = &record;
822 739
823 perf_header__set_cmdline(argc, argv); 740 perf_header__set_cmdline(argc, argv);
824 741
@@ -826,23 +743,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
826 if (evsel_list == NULL) 743 if (evsel_list == NULL)
827 return -ENOMEM; 744 return -ENOMEM;
828 745
746 rec->evlist = evsel_list;
747
829 argc = parse_options(argc, argv, record_options, record_usage, 748 argc = parse_options(argc, argv, record_options, record_usage,
830 PARSE_OPT_STOP_AT_NON_OPTION); 749 PARSE_OPT_STOP_AT_NON_OPTION);
831 if (!argc && target_pid == -1 && target_tid == -1 && 750 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
832 !system_wide && !cpu_list) 751 !rec->opts.system_wide && !rec->opts.cpu_list)
833 usage_with_options(record_usage, record_options); 752 usage_with_options(record_usage, record_options);
834 753
835 if (force && append_file) { 754 if (rec->force && rec->append_file) {
836 fprintf(stderr, "Can't overwrite and append at the same time." 755 fprintf(stderr, "Can't overwrite and append at the same time."
837 " You need to choose between -f and -A"); 756 " You need to choose between -f and -A");
838 usage_with_options(record_usage, record_options); 757 usage_with_options(record_usage, record_options);
839 } else if (append_file) { 758 } else if (rec->append_file) {
840 write_mode = WRITE_APPEND; 759 rec->write_mode = WRITE_APPEND;
841 } else { 760 } else {
842 write_mode = WRITE_FORCE; 761 rec->write_mode = WRITE_FORCE;
843 } 762 }
844 763
845 if (nr_cgroups && !system_wide) { 764 if (nr_cgroups && !rec->opts.system_wide) {
846 fprintf(stderr, "cgroup monitoring only available in" 765 fprintf(stderr, "cgroup monitoring only available in"
847 " system-wide mode\n"); 766 " system-wide mode\n");
848 usage_with_options(record_usage, record_options); 767 usage_with_options(record_usage, record_options);
@@ -860,7 +779,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
860"If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 779"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
861"even with a suitable vmlinux or kallsyms file.\n\n"); 780"even with a suitable vmlinux or kallsyms file.\n\n");
862 781
863 if (no_buildid_cache || no_buildid) 782 if (rec->no_buildid_cache || rec->no_buildid)
864 disable_buildid_cache(); 783 disable_buildid_cache();
865 784
866 if (evsel_list->nr_entries == 0 && 785 if (evsel_list->nr_entries == 0 &&
@@ -869,43 +788,37 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
869 goto out_symbol_exit; 788 goto out_symbol_exit;
870 } 789 }
871 790
872 if (target_pid != -1) 791 if (rec->opts.target_pid != -1)
873 target_tid = target_pid; 792 rec->opts.target_tid = rec->opts.target_pid;
874 793
875 if (perf_evlist__create_maps(evsel_list, target_pid, 794 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
876 target_tid, cpu_list) < 0) 795 rec->opts.target_tid, rec->opts.cpu_list) < 0)
877 usage_with_options(record_usage, record_options); 796 usage_with_options(record_usage, record_options);
878 797
879 list_for_each_entry(pos, &evsel_list->entries, node) { 798 list_for_each_entry(pos, &evsel_list->entries, node) {
880 if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
881 evsel_list->threads->nr) < 0)
882 goto out_free_fd;
883 if (perf_header__push_event(pos->attr.config, event_name(pos))) 799 if (perf_header__push_event(pos->attr.config, event_name(pos)))
884 goto out_free_fd; 800 goto out_free_fd;
885 } 801 }
886 802
887 if (perf_evlist__alloc_pollfd(evsel_list) < 0) 803 if (rec->opts.user_interval != ULLONG_MAX)
888 goto out_free_fd; 804 rec->opts.default_interval = rec->opts.user_interval;
889 805 if (rec->opts.user_freq != UINT_MAX)
890 if (user_interval != ULLONG_MAX) 806 rec->opts.freq = rec->opts.user_freq;
891 default_interval = user_interval;
892 if (user_freq != UINT_MAX)
893 freq = user_freq;
894 807
895 /* 808 /*
896 * User specified count overrides default frequency. 809 * User specified count overrides default frequency.
897 */ 810 */
898 if (default_interval) 811 if (rec->opts.default_interval)
899 freq = 0; 812 rec->opts.freq = 0;
900 else if (freq) { 813 else if (rec->opts.freq) {
901 default_interval = freq; 814 rec->opts.default_interval = rec->opts.freq;
902 } else { 815 } else {
903 fprintf(stderr, "frequency and count are zero, aborting\n"); 816 fprintf(stderr, "frequency and count are zero, aborting\n");
904 err = -EINVAL; 817 err = -EINVAL;
905 goto out_free_fd; 818 goto out_free_fd;
906 } 819 }
907 820
908 err = __cmd_record(argc, argv); 821 err = __cmd_record(&record, argc, argv);
909out_free_fd: 822out_free_fd:
910 perf_evlist__delete_maps(evsel_list); 823 perf_evlist__delete_maps(evsel_list);
911out_symbol_exit: 824out_symbol_exit:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4d7c8340c326..25d34d483e49 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -25,6 +25,7 @@
25#include "util/evsel.h" 25#include "util/evsel.h"
26#include "util/header.h" 26#include "util/header.h"
27#include "util/session.h" 27#include "util/session.h"
28#include "util/tool.h"
28 29
29#include "util/parse-options.h" 30#include "util/parse-options.h"
30#include "util/parse-events.h" 31#include "util/parse-events.h"
@@ -35,38 +36,35 @@
35 36
36#include <linux/bitmap.h> 37#include <linux/bitmap.h>
37 38
38static char const *input_name = "perf.data"; 39struct perf_report {
39 40 struct perf_tool tool;
40static bool force, use_tui, use_stdio; 41 struct perf_session *session;
41static bool hide_unresolved; 42 char const *input_name;
42static bool dont_use_callchains; 43 bool force, use_tui, use_stdio;
43static bool show_full_info; 44 bool hide_unresolved;
44 45 bool dont_use_callchains;
45static bool show_threads; 46 bool show_full_info;
46static struct perf_read_values show_threads_values; 47 bool show_threads;
47 48 bool inverted_callchain;
48static const char default_pretty_printing_style[] = "normal"; 49 struct perf_read_values show_threads_values;
49static const char *pretty_printing_style = default_pretty_printing_style; 50 const char *pretty_printing_style;
50 51 symbol_filter_t annotate_init;
51static char callchain_default_opt[] = "fractal,0.5,callee"; 52 const char *cpu_list;
52static bool inverted_callchain; 53 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
53static symbol_filter_t annotate_init; 54};
54
55static const char *cpu_list;
56static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
57 55
58static int perf_session__add_hist_entry(struct perf_session *session, 56static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
59 struct addr_location *al, 57 struct addr_location *al,
60 struct perf_sample *sample, 58 struct perf_sample *sample,
61 struct perf_evsel *evsel) 59 struct machine *machine)
62{ 60{
63 struct symbol *parent = NULL; 61 struct symbol *parent = NULL;
64 int err = 0; 62 int err = 0;
65 struct hist_entry *he; 63 struct hist_entry *he;
66 64
67 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { 65 if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
68 err = perf_session__resolve_callchain(session, al->thread, 66 err = machine__resolve_callchain(machine, evsel, al->thread,
69 sample->callchain, &parent); 67 sample->callchain, &parent);
70 if (err) 68 if (err)
71 return err; 69 return err;
72 } 70 }
@@ -76,7 +74,8 @@ static int perf_session__add_hist_entry(struct perf_session *session,
76 return -ENOMEM; 74 return -ENOMEM;
77 75
78 if (symbol_conf.use_callchain) { 76 if (symbol_conf.use_callchain) {
79 err = callchain_append(he->callchain, &session->callchain_cursor, 77 err = callchain_append(he->callchain,
78 &evsel->hists.callchain_cursor,
80 sample->period); 79 sample->period);
81 if (err) 80 if (err)
82 return err; 81 return err;
@@ -92,8 +91,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
92 assert(evsel != NULL); 91 assert(evsel != NULL);
93 92
94 err = -ENOMEM; 93 err = -ENOMEM;
95 if (notes->src == NULL && 94 if (notes->src == NULL && symbol__alloc_hist(he->ms.sym) < 0)
96 symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0)
97 goto out; 95 goto out;
98 96
99 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 97 err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
@@ -106,30 +104,32 @@ out:
106} 104}
107 105
108 106
109static int process_sample_event(union perf_event *event, 107static int process_sample_event(struct perf_tool *tool,
108 union perf_event *event,
110 struct perf_sample *sample, 109 struct perf_sample *sample,
111 struct perf_evsel *evsel, 110 struct perf_evsel *evsel,
112 struct perf_session *session) 111 struct machine *machine)
113{ 112{
113 struct perf_report *rep = container_of(tool, struct perf_report, tool);
114 struct addr_location al; 114 struct addr_location al;
115 115
116 if (perf_event__preprocess_sample(event, session, &al, sample, 116 if (perf_event__preprocess_sample(event, machine, &al, sample,
117 annotate_init) < 0) { 117 rep->annotate_init) < 0) {
118 fprintf(stderr, "problem processing %d event, skipping it.\n", 118 fprintf(stderr, "problem processing %d event, skipping it.\n",
119 event->header.type); 119 event->header.type);
120 return -1; 120 return -1;
121 } 121 }
122 122
123 if (al.filtered || (hide_unresolved && al.sym == NULL)) 123 if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
124 return 0; 124 return 0;
125 125
126 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 126 if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
127 return 0; 127 return 0;
128 128
129 if (al.map != NULL) 129 if (al.map != NULL)
130 al.map->dso->hit = 1; 130 al.map->dso->hit = 1;
131 131
132 if (perf_session__add_hist_entry(session, &al, sample, evsel)) { 132 if (perf_evsel__add_hist_entry(evsel, &al, sample, machine)) {
133 pr_debug("problem incrementing symbol period, skipping event\n"); 133 pr_debug("problem incrementing symbol period, skipping event\n");
134 return -1; 134 return -1;
135 } 135 }
@@ -137,15 +137,17 @@ static int process_sample_event(union perf_event *event,
137 return 0; 137 return 0;
138} 138}
139 139
140static int process_read_event(union perf_event *event, 140static int process_read_event(struct perf_tool *tool,
141 union perf_event *event,
141 struct perf_sample *sample __used, 142 struct perf_sample *sample __used,
142 struct perf_session *session) 143 struct perf_evsel *evsel,
144 struct machine *machine __used)
143{ 145{
144 struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, 146 struct perf_report *rep = container_of(tool, struct perf_report, tool);
145 event->read.id); 147
146 if (show_threads) { 148 if (rep->show_threads) {
147 const char *name = evsel ? event_name(evsel) : "unknown"; 149 const char *name = evsel ? event_name(evsel) : "unknown";
148 perf_read_values_add_value(&show_threads_values, 150 perf_read_values_add_value(&rep->show_threads_values,
149 event->read.pid, event->read.tid, 151 event->read.pid, event->read.tid,
150 event->read.id, 152 event->read.id,
151 name, 153 name,
@@ -159,8 +161,10 @@ static int process_read_event(union perf_event *event,
159 return 0; 161 return 0;
160} 162}
161 163
162static int perf_session__setup_sample_type(struct perf_session *self) 164static int perf_report__setup_sample_type(struct perf_report *rep)
163{ 165{
166 struct perf_session *self = rep->session;
167
164 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) { 168 if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
165 if (sort__has_parent) { 169 if (sort__has_parent) {
166 ui__warning("Selected --sort parent, but no " 170 ui__warning("Selected --sort parent, but no "
@@ -173,7 +177,8 @@ static int perf_session__setup_sample_type(struct perf_session *self)
173 "you call 'perf record' without -g?\n"); 177 "you call 'perf record' without -g?\n");
174 return -1; 178 return -1;
175 } 179 }
176 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE && 180 } else if (!rep->dont_use_callchains &&
181 callchain_param.mode != CHAIN_NONE &&
177 !symbol_conf.use_callchain) { 182 !symbol_conf.use_callchain) {
178 symbol_conf.use_callchain = true; 183 symbol_conf.use_callchain = true;
179 if (callchain_register_param(&callchain_param) < 0) { 184 if (callchain_register_param(&callchain_param) < 0) {
@@ -186,22 +191,6 @@ static int perf_session__setup_sample_type(struct perf_session *self)
186 return 0; 191 return 0;
187} 192}
188 193
189static struct perf_event_ops event_ops = {
190 .sample = process_sample_event,
191 .mmap = perf_event__process_mmap,
192 .comm = perf_event__process_comm,
193 .exit = perf_event__process_task,
194 .fork = perf_event__process_task,
195 .lost = perf_event__process_lost,
196 .read = process_read_event,
197 .attr = perf_event__process_attr,
198 .event_type = perf_event__process_event_type,
199 .tracing_data = perf_event__process_tracing_data,
200 .build_id = perf_event__process_build_id,
201 .ordered_samples = true,
202 .ordering_requires_timestamps = true,
203};
204
205extern volatile int session_done; 194extern volatile int session_done;
206 195
207static void sig_handler(int sig __used) 196static void sig_handler(int sig __used)
@@ -224,6 +213,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
224} 213}
225 214
226static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, 215static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
216 struct perf_report *rep,
227 const char *help) 217 const char *help)
228{ 218{
229 struct perf_evsel *pos; 219 struct perf_evsel *pos;
@@ -241,18 +231,18 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
241 parent_pattern == default_parent_pattern) { 231 parent_pattern == default_parent_pattern) {
242 fprintf(stdout, "#\n# (%s)\n#\n", help); 232 fprintf(stdout, "#\n# (%s)\n#\n", help);
243 233
244 if (show_threads) { 234 if (rep->show_threads) {
245 bool style = !strcmp(pretty_printing_style, "raw"); 235 bool style = !strcmp(rep->pretty_printing_style, "raw");
246 perf_read_values_display(stdout, &show_threads_values, 236 perf_read_values_display(stdout, &rep->show_threads_values,
247 style); 237 style);
248 perf_read_values_destroy(&show_threads_values); 238 perf_read_values_destroy(&rep->show_threads_values);
249 } 239 }
250 } 240 }
251 241
252 return 0; 242 return 0;
253} 243}
254 244
255static int __cmd_report(void) 245static int __cmd_report(struct perf_report *rep)
256{ 246{
257 int ret = -EINVAL; 247 int ret = -EINVAL;
258 u64 nr_samples; 248 u64 nr_samples;
@@ -264,27 +254,31 @@ static int __cmd_report(void)
264 254
265 signal(SIGINT, sig_handler); 255 signal(SIGINT, sig_handler);
266 256
267 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops); 257 session = perf_session__new(rep->input_name, O_RDONLY,
258 rep->force, false, &rep->tool);
268 if (session == NULL) 259 if (session == NULL)
269 return -ENOMEM; 260 return -ENOMEM;
270 261
271 if (cpu_list) { 262 rep->session = session;
272 ret = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap); 263
264 if (rep->cpu_list) {
265 ret = perf_session__cpu_bitmap(session, rep->cpu_list,
266 rep->cpu_bitmap);
273 if (ret) 267 if (ret)
274 goto out_delete; 268 goto out_delete;
275 } 269 }
276 270
277 if (use_browser <= 0) 271 if (use_browser <= 0)
278 perf_session__fprintf_info(session, stdout, show_full_info); 272 perf_session__fprintf_info(session, stdout, rep->show_full_info);
279 273
280 if (show_threads) 274 if (rep->show_threads)
281 perf_read_values_init(&show_threads_values); 275 perf_read_values_init(&rep->show_threads_values);
282 276
283 ret = perf_session__setup_sample_type(session); 277 ret = perf_report__setup_sample_type(rep);
284 if (ret) 278 if (ret)
285 goto out_delete; 279 goto out_delete;
286 280
287 ret = perf_session__process_events(session, &event_ops); 281 ret = perf_session__process_events(session, &rep->tool);
288 if (ret) 282 if (ret)
289 goto out_delete; 283 goto out_delete;
290 284
@@ -327,7 +321,7 @@ static int __cmd_report(void)
327 } 321 }
328 322
329 if (nr_samples == 0) { 323 if (nr_samples == 0) {
330 ui__warning("The %s file has no samples!\n", input_name); 324 ui__warning("The %s file has no samples!\n", session->filename);
331 goto out_delete; 325 goto out_delete;
332 } 326 }
333 327
@@ -335,7 +329,7 @@ static int __cmd_report(void)
335 perf_evlist__tui_browse_hists(session->evlist, help, 329 perf_evlist__tui_browse_hists(session->evlist, help,
336 NULL, NULL, 0); 330 NULL, NULL, 0);
337 } else 331 } else
338 perf_evlist__tty_browse_hists(session->evlist, help); 332 perf_evlist__tty_browse_hists(session->evlist, rep, help);
339 333
340out_delete: 334out_delete:
341 /* 335 /*
@@ -354,9 +348,9 @@ out_delete:
354} 348}
355 349
356static int 350static int
357parse_callchain_opt(const struct option *opt __used, const char *arg, 351parse_callchain_opt(const struct option *opt, const char *arg, int unset)
358 int unset)
359{ 352{
353 struct perf_report *rep = (struct perf_report *)opt->value;
360 char *tok, *tok2; 354 char *tok, *tok2;
361 char *endptr; 355 char *endptr;
362 356
@@ -364,7 +358,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
364 * --no-call-graph 358 * --no-call-graph
365 */ 359 */
366 if (unset) { 360 if (unset) {
367 dont_use_callchains = true; 361 rep->dont_use_callchains = true;
368 return 0; 362 return 0;
369 } 363 }
370 364
@@ -412,7 +406,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
412 goto setup; 406 goto setup;
413 407
414 if (tok2[0] != 'c') { 408 if (tok2[0] != 'c') {
415 callchain_param.print_limit = strtod(tok2, &endptr); 409 callchain_param.print_limit = strtoul(tok2, &endptr, 0);
416 tok2 = strtok(NULL, ","); 410 tok2 = strtok(NULL, ",");
417 if (!tok2) 411 if (!tok2)
418 goto setup; 412 goto setup;
@@ -433,13 +427,34 @@ setup:
433 return 0; 427 return 0;
434} 428}
435 429
436static const char * const report_usage[] = { 430int cmd_report(int argc, const char **argv, const char *prefix __used)
437 "perf report [<options>] <command>", 431{
438 NULL 432 struct stat st;
439}; 433 char callchain_default_opt[] = "fractal,0.5,callee";
440 434 const char * const report_usage[] = {
441static const struct option options[] = { 435 "perf report [<options>]",
442 OPT_STRING('i', "input", &input_name, "file", 436 NULL
437 };
438 struct perf_report report = {
439 .tool = {
440 .sample = process_sample_event,
441 .mmap = perf_event__process_mmap,
442 .comm = perf_event__process_comm,
443 .exit = perf_event__process_task,
444 .fork = perf_event__process_task,
445 .lost = perf_event__process_lost,
446 .read = process_read_event,
447 .attr = perf_event__process_attr,
448 .event_type = perf_event__process_event_type,
449 .tracing_data = perf_event__process_tracing_data,
450 .build_id = perf_event__process_build_id,
451 .ordered_samples = true,
452 .ordering_requires_timestamps = true,
453 },
454 .pretty_printing_style = "normal",
455 };
456 const struct option options[] = {
457 OPT_STRING('i', "input", &report.input_name, "file",
443 "input file name"), 458 "input file name"),
444 OPT_INCR('v', "verbose", &verbose, 459 OPT_INCR('v', "verbose", &verbose,
445 "be more verbose (show symbol address, etc)"), 460 "be more verbose (show symbol address, etc)"),
@@ -449,17 +464,18 @@ static const struct option options[] = {
449 "file", "vmlinux pathname"), 464 "file", "vmlinux pathname"),
450 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 465 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
451 "file", "kallsyms pathname"), 466 "file", "kallsyms pathname"),
452 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 467 OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
453 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 468 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
454 "load module symbols - WARNING: use only with -k and LIVE kernel"), 469 "load module symbols - WARNING: use only with -k and LIVE kernel"),
455 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 470 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
456 "Show a column with the number of samples"), 471 "Show a column with the number of samples"),
457 OPT_BOOLEAN('T', "threads", &show_threads, 472 OPT_BOOLEAN('T', "threads", &report.show_threads,
458 "Show per-thread event counters"), 473 "Show per-thread event counters"),
459 OPT_STRING(0, "pretty", &pretty_printing_style, "key", 474 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
460 "pretty printing style key: normal raw"), 475 "pretty printing style key: normal raw"),
461 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 476 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
462 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 477 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
478 "Use the stdio interface"),
463 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 479 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
464 "sort by key(s): pid, comm, dso, symbol, parent"), 480 "sort by key(s): pid, comm, dso, symbol, parent"),
465 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 481 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -468,13 +484,14 @@ static const struct option options[] = {
468 "regex filter to identify parent, see: '--sort parent'"), 484 "regex filter to identify parent, see: '--sort parent'"),
469 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 485 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
470 "Only display entries with parent-match"), 486 "Only display entries with parent-match"),
471 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order", 487 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent[,print_limit],call_order",
472 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. " 488 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold, optional print limit and callchain order. "
473 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), 489 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
474 OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"), 490 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
491 "alias for inverted call graph"),
475 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 492 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
476 "only consider symbols in these dsos"), 493 "only consider symbols in these dsos"),
477 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 494 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
478 "only consider symbols in these comms"), 495 "only consider symbols in these comms"),
479 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 496 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
480 "only consider these symbols"), 497 "only consider these symbols"),
@@ -484,12 +501,13 @@ static const struct option options[] = {
484 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 501 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
485 "separator for columns, no spaces will be added between " 502 "separator for columns, no spaces will be added between "
486 "columns '.' is reserved."), 503 "columns '.' is reserved."),
487 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 504 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
488 "Only display entries resolved to a symbol"), 505 "Only display entries resolved to a symbol"),
489 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 506 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
490 "Look for files with symbols relative to this directory"), 507 "Look for files with symbols relative to this directory"),
491 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 508 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
492 OPT_BOOLEAN('I', "show-info", &show_full_info, 509 "list of cpus to profile"),
510 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
493 "Display extended information about perf.data file"), 511 "Display extended information about perf.data file"),
494 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 512 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
495 "Interleave source code with assembly code (default)"), 513 "Interleave source code with assembly code (default)"),
@@ -500,24 +518,30 @@ static const struct option options[] = {
500 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 518 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
501 "Show a column with the sum of periods"), 519 "Show a column with the sum of periods"),
502 OPT_END() 520 OPT_END()
503}; 521 };
504 522
505int cmd_report(int argc, const char **argv, const char *prefix __used)
506{
507 argc = parse_options(argc, argv, options, report_usage, 0); 523 argc = parse_options(argc, argv, options, report_usage, 0);
508 524
509 if (use_stdio) 525 if (report.use_stdio)
510 use_browser = 0; 526 use_browser = 0;
511 else if (use_tui) 527 else if (report.use_tui)
512 use_browser = 1; 528 use_browser = 1;
513 529
514 if (inverted_callchain) 530 if (report.inverted_callchain)
515 callchain_param.order = ORDER_CALLER; 531 callchain_param.order = ORDER_CALLER;
516 532
517 if (strcmp(input_name, "-") != 0) 533 if (!report.input_name || !strlen(report.input_name)) {
534 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
535 report.input_name = "-";
536 else
537 report.input_name = "perf.data";
538 }
539
540 if (strcmp(report.input_name, "-") != 0)
518 setup_browser(true); 541 setup_browser(true);
519 else 542 else
520 use_browser = 0; 543 use_browser = 0;
544
521 /* 545 /*
522 * Only in the newt browser we are doing integrated annotation, 546 * Only in the newt browser we are doing integrated annotation,
523 * so don't allocate extra space that won't be used in the stdio 547 * so don't allocate extra space that won't be used in the stdio
@@ -525,7 +549,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
525 */ 549 */
526 if (use_browser > 0) { 550 if (use_browser > 0) {
527 symbol_conf.priv_size = sizeof(struct annotation); 551 symbol_conf.priv_size = sizeof(struct annotation);
528 annotate_init = symbol__annotate_init; 552 report.annotate_init = symbol__annotate_init;
529 /* 553 /*
530 * For searching by name on the "Browse map details". 554 * For searching by name on the "Browse map details".
531 * providing it only in verbose mode not to bloat too 555 * providing it only in verbose mode not to bloat too
@@ -572,5 +596,5 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
572 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); 596 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
573 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); 597 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
574 598
575 return __cmd_report(); 599 return __cmd_report(&report);
576} 600}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 5177964943e7..fb8b5f83b4a0 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -2,11 +2,14 @@
2#include "perf.h" 2#include "perf.h"
3 3
4#include "util/util.h" 4#include "util/util.h"
5#include "util/evlist.h"
5#include "util/cache.h" 6#include "util/cache.h"
7#include "util/evsel.h"
6#include "util/symbol.h" 8#include "util/symbol.h"
7#include "util/thread.h" 9#include "util/thread.h"
8#include "util/header.h" 10#include "util/header.h"
9#include "util/session.h" 11#include "util/session.h"
12#include "util/tool.h"
10 13
11#include "util/parse-options.h" 14#include "util/parse-options.h"
12#include "util/trace-event.h" 15#include "util/trace-event.h"
@@ -19,7 +22,7 @@
19#include <pthread.h> 22#include <pthread.h>
20#include <math.h> 23#include <math.h>
21 24
22static char const *input_name = "perf.data"; 25static const char *input_name;
23 26
24static char default_sort_order[] = "avg, max, switch, runtime"; 27static char default_sort_order[] = "avg, max, switch, runtime";
25static const char *sort_order = default_sort_order; 28static const char *sort_order = default_sort_order;
@@ -723,21 +726,21 @@ struct trace_migrate_task_event {
723 726
724struct trace_sched_handler { 727struct trace_sched_handler {
725 void (*switch_event)(struct trace_switch_event *, 728 void (*switch_event)(struct trace_switch_event *,
726 struct perf_session *, 729 struct machine *,
727 struct event *, 730 struct event *,
728 int cpu, 731 int cpu,
729 u64 timestamp, 732 u64 timestamp,
730 struct thread *thread); 733 struct thread *thread);
731 734
732 void (*runtime_event)(struct trace_runtime_event *, 735 void (*runtime_event)(struct trace_runtime_event *,
733 struct perf_session *, 736 struct machine *,
734 struct event *, 737 struct event *,
735 int cpu, 738 int cpu,
736 u64 timestamp, 739 u64 timestamp,
737 struct thread *thread); 740 struct thread *thread);
738 741
739 void (*wakeup_event)(struct trace_wakeup_event *, 742 void (*wakeup_event)(struct trace_wakeup_event *,
740 struct perf_session *, 743 struct machine *,
741 struct event *, 744 struct event *,
742 int cpu, 745 int cpu,
743 u64 timestamp, 746 u64 timestamp,
@@ -750,7 +753,7 @@ struct trace_sched_handler {
750 struct thread *thread); 753 struct thread *thread);
751 754
752 void (*migrate_task_event)(struct trace_migrate_task_event *, 755 void (*migrate_task_event)(struct trace_migrate_task_event *,
753 struct perf_session *session, 756 struct machine *machine,
754 struct event *, 757 struct event *,
755 int cpu, 758 int cpu,
756 u64 timestamp, 759 u64 timestamp,
@@ -760,7 +763,7 @@ struct trace_sched_handler {
760 763
761static void 764static void
762replay_wakeup_event(struct trace_wakeup_event *wakeup_event, 765replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
763 struct perf_session *session __used, 766 struct machine *machine __used,
764 struct event *event, 767 struct event *event,
765 int cpu __used, 768 int cpu __used,
766 u64 timestamp __used, 769 u64 timestamp __used,
@@ -787,7 +790,7 @@ static u64 cpu_last_switched[MAX_CPUS];
787 790
788static void 791static void
789replay_switch_event(struct trace_switch_event *switch_event, 792replay_switch_event(struct trace_switch_event *switch_event,
790 struct perf_session *session __used, 793 struct machine *machine __used,
791 struct event *event, 794 struct event *event,
792 int cpu, 795 int cpu,
793 u64 timestamp, 796 u64 timestamp,
@@ -1021,7 +1024,7 @@ add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
1021 1024
1022static void 1025static void
1023latency_switch_event(struct trace_switch_event *switch_event, 1026latency_switch_event(struct trace_switch_event *switch_event,
1024 struct perf_session *session, 1027 struct machine *machine,
1025 struct event *event __used, 1028 struct event *event __used,
1026 int cpu, 1029 int cpu,
1027 u64 timestamp, 1030 u64 timestamp,
@@ -1045,8 +1048,8 @@ latency_switch_event(struct trace_switch_event *switch_event,
1045 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1048 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1046 1049
1047 1050
1048 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1051 sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
1049 sched_in = perf_session__findnew(session, switch_event->next_pid); 1052 sched_in = machine__findnew_thread(machine, switch_event->next_pid);
1050 1053
1051 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1054 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid);
1052 if (!out_events) { 1055 if (!out_events) {
@@ -1074,13 +1077,13 @@ latency_switch_event(struct trace_switch_event *switch_event,
1074 1077
1075static void 1078static void
1076latency_runtime_event(struct trace_runtime_event *runtime_event, 1079latency_runtime_event(struct trace_runtime_event *runtime_event,
1077 struct perf_session *session, 1080 struct machine *machine,
1078 struct event *event __used, 1081 struct event *event __used,
1079 int cpu, 1082 int cpu,
1080 u64 timestamp, 1083 u64 timestamp,
1081 struct thread *this_thread __used) 1084 struct thread *this_thread __used)
1082{ 1085{
1083 struct thread *thread = perf_session__findnew(session, runtime_event->pid); 1086 struct thread *thread = machine__findnew_thread(machine, runtime_event->pid);
1084 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1087 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid);
1085 1088
1086 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1089 BUG_ON(cpu >= MAX_CPUS || cpu < 0);
@@ -1097,7 +1100,7 @@ latency_runtime_event(struct trace_runtime_event *runtime_event,
1097 1100
1098static void 1101static void
1099latency_wakeup_event(struct trace_wakeup_event *wakeup_event, 1102latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1100 struct perf_session *session, 1103 struct machine *machine,
1101 struct event *__event __used, 1104 struct event *__event __used,
1102 int cpu __used, 1105 int cpu __used,
1103 u64 timestamp, 1106 u64 timestamp,
@@ -1111,7 +1114,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1111 if (!wakeup_event->success) 1114 if (!wakeup_event->success)
1112 return; 1115 return;
1113 1116
1114 wakee = perf_session__findnew(session, wakeup_event->pid); 1117 wakee = machine__findnew_thread(machine, wakeup_event->pid);
1115 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1118 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid);
1116 if (!atoms) { 1119 if (!atoms) {
1117 thread_atoms_insert(wakee); 1120 thread_atoms_insert(wakee);
@@ -1145,7 +1148,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event,
1145 1148
1146static void 1149static void
1147latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, 1150latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1148 struct perf_session *session, 1151 struct machine *machine,
1149 struct event *__event __used, 1152 struct event *__event __used,
1150 int cpu __used, 1153 int cpu __used,
1151 u64 timestamp, 1154 u64 timestamp,
@@ -1161,7 +1164,7 @@ latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event,
1161 if (profile_cpu == -1) 1164 if (profile_cpu == -1)
1162 return; 1165 return;
1163 1166
1164 migrant = perf_session__findnew(session, migrate_task_event->pid); 1167 migrant = machine__findnew_thread(machine, migrate_task_event->pid);
1165 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); 1168 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid);
1166 if (!atoms) { 1169 if (!atoms) {
1167 thread_atoms_insert(migrant); 1170 thread_atoms_insert(migrant);
@@ -1356,12 +1359,13 @@ static void sort_lat(void)
1356static struct trace_sched_handler *trace_handler; 1359static struct trace_sched_handler *trace_handler;
1357 1360
1358static void 1361static void
1359process_sched_wakeup_event(void *data, struct perf_session *session, 1362process_sched_wakeup_event(struct perf_tool *tool __used,
1360 struct event *event, 1363 struct event *event,
1361 int cpu __used, 1364 struct perf_sample *sample,
1362 u64 timestamp __used, 1365 struct machine *machine,
1363 struct thread *thread __used) 1366 struct thread *thread)
1364{ 1367{
1368 void *data = sample->raw_data;
1365 struct trace_wakeup_event wakeup_event; 1369 struct trace_wakeup_event wakeup_event;
1366 1370
1367 FILL_COMMON_FIELDS(wakeup_event, event, data); 1371 FILL_COMMON_FIELDS(wakeup_event, event, data);
@@ -1373,8 +1377,8 @@ process_sched_wakeup_event(void *data, struct perf_session *session,
1373 FILL_FIELD(wakeup_event, cpu, event, data); 1377 FILL_FIELD(wakeup_event, cpu, event, data);
1374 1378
1375 if (trace_handler->wakeup_event) 1379 if (trace_handler->wakeup_event)
1376 trace_handler->wakeup_event(&wakeup_event, session, event, 1380 trace_handler->wakeup_event(&wakeup_event, machine, event,
1377 cpu, timestamp, thread); 1381 sample->cpu, sample->time, thread);
1378} 1382}
1379 1383
1380/* 1384/*
@@ -1392,7 +1396,7 @@ static char next_shortname2 = '0';
1392 1396
1393static void 1397static void
1394map_switch_event(struct trace_switch_event *switch_event, 1398map_switch_event(struct trace_switch_event *switch_event,
1395 struct perf_session *session, 1399 struct machine *machine,
1396 struct event *event __used, 1400 struct event *event __used,
1397 int this_cpu, 1401 int this_cpu,
1398 u64 timestamp, 1402 u64 timestamp,
@@ -1420,8 +1424,8 @@ map_switch_event(struct trace_switch_event *switch_event,
1420 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1424 die("hm, delta: %" PRIu64 " < 0 ?\n", delta);
1421 1425
1422 1426
1423 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1427 sched_out = machine__findnew_thread(machine, switch_event->prev_pid);
1424 sched_in = perf_session__findnew(session, switch_event->next_pid); 1428 sched_in = machine__findnew_thread(machine, switch_event->next_pid);
1425 1429
1426 curr_thread[this_cpu] = sched_in; 1430 curr_thread[this_cpu] = sched_in;
1427 1431
@@ -1469,14 +1473,15 @@ map_switch_event(struct trace_switch_event *switch_event,
1469 } 1473 }
1470} 1474}
1471 1475
1472
1473static void 1476static void
1474process_sched_switch_event(void *data, struct perf_session *session, 1477process_sched_switch_event(struct perf_tool *tool __used,
1475 struct event *event, 1478 struct event *event,
1476 int this_cpu, 1479 struct perf_sample *sample,
1477 u64 timestamp __used, 1480 struct machine *machine,
1478 struct thread *thread __used) 1481 struct thread *thread)
1479{ 1482{
1483 int this_cpu = sample->cpu;
1484 void *data = sample->raw_data;
1480 struct trace_switch_event switch_event; 1485 struct trace_switch_event switch_event;
1481 1486
1482 FILL_COMMON_FIELDS(switch_event, event, data); 1487 FILL_COMMON_FIELDS(switch_event, event, data);
@@ -1498,19 +1503,20 @@ process_sched_switch_event(void *data, struct perf_session *session,
1498 nr_context_switch_bugs++; 1503 nr_context_switch_bugs++;
1499 } 1504 }
1500 if (trace_handler->switch_event) 1505 if (trace_handler->switch_event)
1501 trace_handler->switch_event(&switch_event, session, event, 1506 trace_handler->switch_event(&switch_event, machine, event,
1502 this_cpu, timestamp, thread); 1507 this_cpu, sample->time, thread);
1503 1508
1504 curr_pid[this_cpu] = switch_event.next_pid; 1509 curr_pid[this_cpu] = switch_event.next_pid;
1505} 1510}
1506 1511
1507static void 1512static void
1508process_sched_runtime_event(void *data, struct perf_session *session, 1513process_sched_runtime_event(struct perf_tool *tool __used,
1509 struct event *event, 1514 struct event *event,
1510 int cpu __used, 1515 struct perf_sample *sample,
1511 u64 timestamp __used, 1516 struct machine *machine,
1512 struct thread *thread __used) 1517 struct thread *thread)
1513{ 1518{
1519 void *data = sample->raw_data;
1514 struct trace_runtime_event runtime_event; 1520 struct trace_runtime_event runtime_event;
1515 1521
1516 FILL_ARRAY(runtime_event, comm, event, data); 1522 FILL_ARRAY(runtime_event, comm, event, data);
@@ -1519,16 +1525,18 @@ process_sched_runtime_event(void *data, struct perf_session *session,
1519 FILL_FIELD(runtime_event, vruntime, event, data); 1525 FILL_FIELD(runtime_event, vruntime, event, data);
1520 1526
1521 if (trace_handler->runtime_event) 1527 if (trace_handler->runtime_event)
1522 trace_handler->runtime_event(&runtime_event, session, event, cpu, timestamp, thread); 1528 trace_handler->runtime_event(&runtime_event, machine, event,
1529 sample->cpu, sample->time, thread);
1523} 1530}
1524 1531
1525static void 1532static void
1526process_sched_fork_event(void *data, 1533process_sched_fork_event(struct perf_tool *tool __used,
1527 struct event *event, 1534 struct event *event,
1528 int cpu __used, 1535 struct perf_sample *sample,
1529 u64 timestamp __used, 1536 struct machine *machine __used,
1530 struct thread *thread __used) 1537 struct thread *thread)
1531{ 1538{
1539 void *data = sample->raw_data;
1532 struct trace_fork_event fork_event; 1540 struct trace_fork_event fork_event;
1533 1541
1534 FILL_COMMON_FIELDS(fork_event, event, data); 1542 FILL_COMMON_FIELDS(fork_event, event, data);
@@ -1540,13 +1548,14 @@ process_sched_fork_event(void *data,
1540 1548
1541 if (trace_handler->fork_event) 1549 if (trace_handler->fork_event)
1542 trace_handler->fork_event(&fork_event, event, 1550 trace_handler->fork_event(&fork_event, event,
1543 cpu, timestamp, thread); 1551 sample->cpu, sample->time, thread);
1544} 1552}
1545 1553
1546static void 1554static void
1547process_sched_exit_event(struct event *event, 1555process_sched_exit_event(struct perf_tool *tool __used,
1548 int cpu __used, 1556 struct event *event,
1549 u64 timestamp __used, 1557 struct perf_sample *sample __used,
1558 struct machine *machine __used,
1550 struct thread *thread __used) 1559 struct thread *thread __used)
1551{ 1560{
1552 if (verbose) 1561 if (verbose)
@@ -1554,12 +1563,13 @@ process_sched_exit_event(struct event *event,
1554} 1563}
1555 1564
1556static void 1565static void
1557process_sched_migrate_task_event(void *data, struct perf_session *session, 1566process_sched_migrate_task_event(struct perf_tool *tool __used,
1558 struct event *event, 1567 struct event *event,
1559 int cpu __used, 1568 struct perf_sample *sample,
1560 u64 timestamp __used, 1569 struct machine *machine,
1561 struct thread *thread __used) 1570 struct thread *thread)
1562{ 1571{
1572 void *data = sample->raw_data;
1563 struct trace_migrate_task_event migrate_task_event; 1573 struct trace_migrate_task_event migrate_task_event;
1564 1574
1565 FILL_COMMON_FIELDS(migrate_task_event, event, data); 1575 FILL_COMMON_FIELDS(migrate_task_event, event, data);
@@ -1570,67 +1580,47 @@ process_sched_migrate_task_event(void *data, struct perf_session *session,
1570 FILL_FIELD(migrate_task_event, cpu, event, data); 1580 FILL_FIELD(migrate_task_event, cpu, event, data);
1571 1581
1572 if (trace_handler->migrate_task_event) 1582 if (trace_handler->migrate_task_event)
1573 trace_handler->migrate_task_event(&migrate_task_event, session, 1583 trace_handler->migrate_task_event(&migrate_task_event, machine,
1574 event, cpu, timestamp, thread); 1584 event, sample->cpu,
1585 sample->time, thread);
1575} 1586}
1576 1587
1577static void process_raw_event(union perf_event *raw_event __used, 1588typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event,
1578 struct perf_session *session, void *data, int cpu, 1589 struct perf_sample *sample,
1579 u64 timestamp, struct thread *thread) 1590 struct machine *machine,
1580{ 1591 struct thread *thread);
1581 struct event *event;
1582 int type;
1583
1584
1585 type = trace_parse_common_type(data);
1586 event = trace_find_event(type);
1587
1588 if (!strcmp(event->name, "sched_switch"))
1589 process_sched_switch_event(data, session, event, cpu, timestamp, thread);
1590 if (!strcmp(event->name, "sched_stat_runtime"))
1591 process_sched_runtime_event(data, session, event, cpu, timestamp, thread);
1592 if (!strcmp(event->name, "sched_wakeup"))
1593 process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
1594 if (!strcmp(event->name, "sched_wakeup_new"))
1595 process_sched_wakeup_event(data, session, event, cpu, timestamp, thread);
1596 if (!strcmp(event->name, "sched_process_fork"))
1597 process_sched_fork_event(data, event, cpu, timestamp, thread);
1598 if (!strcmp(event->name, "sched_process_exit"))
1599 process_sched_exit_event(event, cpu, timestamp, thread);
1600 if (!strcmp(event->name, "sched_migrate_task"))
1601 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
1602}
1603 1592
1604static int process_sample_event(union perf_event *event, 1593static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
1605 struct perf_sample *sample, 1594 union perf_event *event __used,
1606 struct perf_evsel *evsel __used, 1595 struct perf_sample *sample,
1607 struct perf_session *session) 1596 struct perf_evsel *evsel,
1597 struct machine *machine)
1608{ 1598{
1609 struct thread *thread; 1599 struct thread *thread = machine__findnew_thread(machine, sample->pid);
1610
1611 if (!(session->sample_type & PERF_SAMPLE_RAW))
1612 return 0;
1613 1600
1614 thread = perf_session__findnew(session, sample->pid);
1615 if (thread == NULL) { 1601 if (thread == NULL) {
1616 pr_debug("problem processing %d event, skipping it.\n", 1602 pr_debug("problem processing %s event, skipping it.\n",
1617 event->header.type); 1603 evsel->name);
1618 return -1; 1604 return -1;
1619 } 1605 }
1620 1606
1621 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1607 evsel->hists.stats.total_period += sample->period;
1608 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1622 1609
1623 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu) 1610 if (evsel->handler.func != NULL) {
1624 return 0; 1611 tracepoint_handler f = evsel->handler.func;
1625 1612
1626 process_raw_event(event, session, sample->raw_data, sample->cpu, 1613 if (evsel->handler.data == NULL)
1627 sample->time, thread); 1614 evsel->handler.data = trace_find_event(evsel->attr.config);
1615
1616 f(tool, evsel->handler.data, sample, machine, thread);
1617 }
1628 1618
1629 return 0; 1619 return 0;
1630} 1620}
1631 1621
1632static struct perf_event_ops event_ops = { 1622static struct perf_tool perf_sched = {
1633 .sample = process_sample_event, 1623 .sample = perf_sched__process_tracepoint_sample,
1634 .comm = perf_event__process_comm, 1624 .comm = perf_event__process_comm,
1635 .lost = perf_event__process_lost, 1625 .lost = perf_event__process_lost,
1636 .fork = perf_event__process_task, 1626 .fork = perf_event__process_task,
@@ -1640,13 +1630,25 @@ static struct perf_event_ops event_ops = {
1640static void read_events(bool destroy, struct perf_session **psession) 1630static void read_events(bool destroy, struct perf_session **psession)
1641{ 1631{
1642 int err = -EINVAL; 1632 int err = -EINVAL;
1633 const struct perf_evsel_str_handler handlers[] = {
1634 { "sched:sched_switch", process_sched_switch_event, },
1635 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1636 { "sched:sched_wakeup", process_sched_wakeup_event, },
1637 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1638 { "sched:sched_process_fork", process_sched_fork_event, },
1639 { "sched:sched_process_exit", process_sched_exit_event, },
1640 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1641 };
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 1642 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1644 0, false, &event_ops); 1643 0, false, &perf_sched);
1645 if (session == NULL) 1644 if (session == NULL)
1646 die("No Memory"); 1645 die("No Memory");
1647 1646
1647 err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers);
1648 assert(err == 0);
1649