aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-annotate.txt2
-rw-r--r--tools/perf/Documentation/perf-report.txt4
-rw-r--r--tools/perf/Documentation/perf-script.txt7
-rw-r--r--tools/perf/Documentation/perf-test.txt8
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/builtin-annotate.c133
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-inject.c118
-rw-r--r--tools/perf/builtin-kmem.c14
-rw-r--r--tools/perf/builtin-lock.c10
-rw-r--r--tools/perf/builtin-probe.c1
-rw-r--r--tools/perf/builtin-record.c585
-rw-r--r--tools/perf/builtin-report.c225
-rw-r--r--tools/perf/builtin-sched.c198
-rw-r--r--tools/perf/builtin-script.c50
-rw-r--r--tools/perf/builtin-stat.c43
-rw-r--r--tools/perf/builtin-test.c418
-rw-r--r--tools/perf/builtin-timechart.c34
-rw-r--r--tools/perf/builtin-top.c557
-rw-r--r--tools/perf/perf.c33
-rw-r--r--tools/perf/perf.h23
-rw-r--r--tools/perf/util/annotate.c6
-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/debugfs.c35
-rw-r--r--tools/perf/util/debugfs.h31
-rw-r--r--tools/perf/util/event.c243
-rw-r--r--tools/perf/util/event.h65
-rw-r--r--tools/perf/util/evlist.c293
-rw-r--r--tools/perf/util/evlist.h43
-rw-r--r--tools/perf/util/evsel.c70
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/header.c75
-rw-r--r--tools/perf/util/header.h45
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/map.c4
-rw-r--r--tools/perf/util/map.h19
-rw-r--r--tools/perf/util/parse-events.c28
-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.c4
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c4
-rw-r--r--tools/perf/util/session.c326
-rw-r--r--tools/perf/util/session.h62
-rw-r--r--tools/perf/util/setup.py3
-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-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
59 files changed, 2456 insertions, 1599 deletions
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index fe6762ed56bd..476029d30621 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -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-report.txt b/tools/perf/Documentation/perf-report.txt
index 212f24d672e1..dc85392a5ac7 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -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.
@@ -128,7 +128,7 @@ OPTIONS
128--symfs=<directory>:: 128--symfs=<directory>::
129 Look for files with symbols relative to this directory. 129 Look for files with symbols relative to this directory.
130 130
131-c:: 131-C::
132--cpu:: Only report samples for the list of CPUs provided. Multiple CPUs can 132--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 133 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 134 CPUs are specified with -: 0-2. Default is to report samples on all
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index dec87ecb530e..7f61eaaf9ab8 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -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/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/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 46b4c24f338e..d449645c5ef1 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", ann->input_name);
227 goto out_delete; 219 goto out_delete;
228 } 220 }
229out_delete: 221out_delete:
@@ -247,29 +239,42 @@ 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 .input_name = "perf.data",
254 };
255 const struct option options[] = {
256 OPT_STRING('i', "input", &annotate.input_name, "file",
252 "input file name"), 257 "input file name"),
253 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 258 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
254 "only consider symbols in these dsos"), 259 "only consider symbols in these dsos"),
255 OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", 260 OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol",
256 "symbol to annotate"), 261 "symbol to annotate"),
257 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 262 OPT_BOOLEAN('f', "force", &annotate.force, "don't complain, do it"),
258 OPT_INCR('v', "verbose", &verbose, 263 OPT_INCR('v', "verbose", &verbose,
259 "be more verbose (show symbol address, etc)"), 264 "be more verbose (show symbol address, etc)"),
260 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 265 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
261 "dump raw trace in ASCII"), 266 "dump raw trace in ASCII"),
262 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 267 OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
263 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 268 OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
264 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 269 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
265 "file", "vmlinux pathname"), 270 "file", "vmlinux pathname"),
266 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 271 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
267 "load module symbols - WARNING: use only with -k and LIVE kernel"), 272 "load module symbols - WARNING: use only with -k and LIVE kernel"),
268 OPT_BOOLEAN('l', "print-line", &print_line, 273 OPT_BOOLEAN('l', "print-line", &annotate.print_line,
269 "print matching source lines (may be slow)"), 274 "print matching source lines (may be slow)"),
270 OPT_BOOLEAN('P', "full-paths", &full_paths, 275 OPT_BOOLEAN('P', "full-paths", &annotate.full_paths,
271 "Don't shorten the displayed pathnames"), 276 "Don't shorten the displayed pathnames"),
272 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 277 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
273 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 278 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
274 "Look for files with symbols relative to this directory"), 279 "Look for files with symbols relative to this directory"),
275 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 280 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
@@ -279,15 +284,13 @@ static const struct option options[] = {
279 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 284 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
280 "Specify disassembler style (e.g. -M intel for intel syntax)"), 285 "Specify disassembler style (e.g. -M intel for intel syntax)"),
281 OPT_END() 286 OPT_END()
282}; 287 };
283 288
284int cmd_annotate(int argc, const char **argv, const char *prefix __used)
285{
286 argc = parse_options(argc, argv, options, annotate_usage, 0); 289 argc = parse_options(argc, argv, options, annotate_usage, 0);
287 290
288 if (use_stdio) 291 if (annotate.use_stdio)
289 use_browser = 0; 292 use_browser = 0;
290 else if (use_tui) 293 else if (annotate.use_tui)
291 use_browser = 1; 294 use_browser = 1;
292 295
293 setup_browser(true); 296 setup_browser(true);
@@ -308,7 +311,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
308 if (argc > 1) 311 if (argc > 1)
309 usage_with_options(annotate_usage, options); 312 usage_with_options(annotate_usage, options);
310 313
311 sym_hist_filter = argv[0]; 314 annotate.sym_hist_filter = argv[0];
312 } 315 }
313 316
314 if (field_sep && *field_sep == '.') { 317 if (field_sep && *field_sep == '.') {
@@ -316,5 +319,5 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
316 return -1; 319 return -1;
317 } 320 }
318 321
319 return __cmd_annotate(); 322 return __cmd_annotate(&annotate);
320} 323}
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-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..886174e9525b 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"
@@ -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-lock.c b/tools/perf/builtin-lock.c
index 899080ace267..4db5e5293067 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>
@@ -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..766fa0a91a32 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,10 @@ 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)
362 die("failed to mmap with %d (%s)\n", errno, strerror(errno)); 276 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
363 277
364 if (file_new) 278 if (rec->file_new)
365 session->evlist = evlist; 279 session->evlist = evlist;
366 else { 280 else {
367 if (!perf_evlist__equal(session->evlist, evlist)) { 281 if (!perf_evlist__equal(session->evlist, evlist)) {
@@ -373,29 +287,32 @@ try_again:
373 perf_session__update_sample_type(session); 287 perf_session__update_sample_type(session);
374} 288}
375 289
376static int process_buildids(void) 290static int process_buildids(struct perf_record *rec)
377{ 291{
378 u64 size = lseek(output, 0, SEEK_CUR); 292 u64 size = lseek(rec->output, 0, SEEK_CUR);
379 293
380 if (size == 0) 294 if (size == 0)
381 return 0; 295 return 0;
382 296
383 session->fd = output; 297 rec->session->fd = rec->output;
384 return __perf_session__process_events(session, post_processing_offset, 298 return __perf_session__process_events(rec->session, rec->post_processing_offset,
385 size - post_processing_offset, 299 size - rec->post_processing_offset,
386 size, &build_id__mark_dso_hit_ops); 300 size, &build_id__mark_dso_hit_ops);
387} 301}
388 302
389static void atexit_header(void) 303static void perf_record__exit(int status __used, void *arg)
390{ 304{
391 if (!pipe_output) { 305 struct perf_record *rec = arg;
392 session->header.data_size += bytes_written; 306
393 307 if (!rec->opts.pipe_output) {
394 if (!no_buildid) 308 rec->session->header.data_size += rec->bytes_written;
395 process_buildids(); 309
396 perf_session__write_header(session, evsel_list, output, true); 310 if (!rec->no_buildid)
397 perf_session__delete(session); 311 process_buildids(rec);
398 perf_evlist__delete(evsel_list); 312 perf_session__write_header(rec->session, rec->evlist,
313 rec->output, true);
314 perf_session__delete(rec->session);
315 perf_evlist__delete(rec->evlist);
399 symbol__exit(); 316 symbol__exit();
400 } 317 }
401} 318}
@@ -403,7 +320,7 @@ static void atexit_header(void)
403static void perf_event__synthesize_guest_os(struct machine *machine, void *data) 320static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
404{ 321{
405 int err; 322 int err;
406 struct perf_session *psession = data; 323 struct perf_tool *tool = data;
407 324
408 if (machine__is_host(machine)) 325 if (machine__is_host(machine))
409 return; 326 return;
@@ -416,8 +333,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 333 *method is used to avoid symbol missing when the first addr is
417 *in module instead of in guest kernel. 334 *in module instead of in guest kernel.
418 */ 335 */
419 err = perf_event__synthesize_modules(process_synthesized_event, 336 err = perf_event__synthesize_modules(tool, process_synthesized_event,
420 psession, machine); 337 machine);
421 if (err < 0) 338 if (err < 0)
422 pr_err("Couldn't record guest kernel [%d]'s reference" 339 pr_err("Couldn't record guest kernel [%d]'s reference"
423 " relocation symbol.\n", machine->pid); 340 " relocation symbol.\n", machine->pid);
@@ -426,12 +343,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 343 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
427 * have no _text sometimes. 344 * have no _text sometimes.
428 */ 345 */
429 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 346 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
430 psession, machine, "_text"); 347 machine, "_text");
431 if (err < 0) 348 if (err < 0)
432 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 349 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
433 psession, machine, 350 machine, "_stext");
434 "_stext");
435 if (err < 0) 351 if (err < 0)
436 pr_err("Couldn't record guest kernel [%d]'s reference" 352 pr_err("Couldn't record guest kernel [%d]'s reference"
437 " relocation symbol.\n", machine->pid); 353 " relocation symbol.\n", machine->pid);
@@ -442,73 +358,71 @@ static struct perf_event_header finished_round_event = {
442 .type = PERF_RECORD_FINISHED_ROUND, 358 .type = PERF_RECORD_FINISHED_ROUND,
443}; 359};
444 360
445static void mmap_read_all(void) 361static void perf_record__mmap_read_all(struct perf_record *rec)
446{ 362{
447 int i; 363 int i;
448 364
449 for (i = 0; i < evsel_list->nr_mmaps; i++) { 365 for (i = 0; i < rec->evlist->nr_mmaps; i++) {
450 if (evsel_list->mmap[i].base) 366 if (rec->evlist->mmap[i].base)
451 mmap_read(&evsel_list->mmap[i]); 367 perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
452 } 368 }
453 369
454 if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO)) 370 if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO))
455 write_output(&finished_round_event, sizeof(finished_round_event)); 371 write_output(rec, &finished_round_event, sizeof(finished_round_event));
456} 372}
457 373
458static int __cmd_record(int argc, const char **argv) 374static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
459{ 375{
460 struct stat st; 376 struct stat st;
461 int flags; 377 int flags;
462 int err; 378 int err, output;
463 unsigned long waking = 0; 379 unsigned long waking = 0;
464 int child_ready_pipe[2], go_pipe[2];
465 const bool forks = argc > 0; 380 const bool forks = argc > 0;
466 char buf;
467 struct machine *machine; 381 struct machine *machine;
382 struct perf_tool *tool = &rec->tool;
383 struct perf_record_opts *opts = &rec->opts;
384 struct perf_evlist *evsel_list = rec->evlist;
385 const char *output_name = rec->output_name;
386 struct perf_session *session;
468 387
469 progname = argv[0]; 388 rec->progname = argv[0];
470 389
471 page_size = sysconf(_SC_PAGE_SIZE); 390 rec->page_size = sysconf(_SC_PAGE_SIZE);
472 391
473 atexit(sig_atexit); 392 on_exit(perf_record__sig_exit, rec);
474 signal(SIGCHLD, sig_handler); 393 signal(SIGCHLD, sig_handler);
475 signal(SIGINT, sig_handler); 394 signal(SIGINT, sig_handler);
476 signal(SIGUSR1, sig_handler); 395 signal(SIGUSR1, sig_handler);
477 396
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) { 397 if (!output_name) {
484 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 398 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
485 pipe_output = 1; 399 opts->pipe_output = true;
486 else 400 else
487 output_name = "perf.data"; 401 rec->output_name = output_name = "perf.data";
488 } 402 }
489 if (output_name) { 403 if (output_name) {
490 if (!strcmp(output_name, "-")) 404 if (!strcmp(output_name, "-"))
491 pipe_output = 1; 405 opts->pipe_output = true;
492 else if (!stat(output_name, &st) && st.st_size) { 406 else if (!stat(output_name, &st) && st.st_size) {
493 if (write_mode == WRITE_FORCE) { 407 if (rec->write_mode == WRITE_FORCE) {
494 char oldname[PATH_MAX]; 408 char oldname[PATH_MAX];
495 snprintf(oldname, sizeof(oldname), "%s.old", 409 snprintf(oldname, sizeof(oldname), "%s.old",
496 output_name); 410 output_name);
497 unlink(oldname); 411 unlink(oldname);
498 rename(output_name, oldname); 412 rename(output_name, oldname);
499 } 413 }
500 } else if (write_mode == WRITE_APPEND) { 414 } else if (rec->write_mode == WRITE_APPEND) {
501 write_mode = WRITE_FORCE; 415 rec->write_mode = WRITE_FORCE;
502 } 416 }
503 } 417 }
504 418
505 flags = O_CREAT|O_RDWR; 419 flags = O_CREAT|O_RDWR;
506 if (write_mode == WRITE_APPEND) 420 if (rec->write_mode == WRITE_APPEND)
507 file_new = 0; 421 rec->file_new = 0;
508 else 422 else
509 flags |= O_TRUNC; 423 flags |= O_TRUNC;
510 424
511 if (pipe_output) 425 if (opts->pipe_output)
512 output = STDOUT_FILENO; 426 output = STDOUT_FILENO;
513 else 427 else
514 output = open(output_name, flags, S_IRUSR | S_IWUSR); 428 output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -517,17 +431,21 @@ static int __cmd_record(int argc, const char **argv)
517 exit(-1); 431 exit(-1);
518 } 432 }
519 433
434 rec->output = output;
435
520 session = perf_session__new(output_name, O_WRONLY, 436 session = perf_session__new(output_name, O_WRONLY,
521 write_mode == WRITE_FORCE, false, NULL); 437 rec->write_mode == WRITE_FORCE, false, NULL);
522 if (session == NULL) { 438 if (session == NULL) {
523 pr_err("Not enough memory for reading perf file header\n"); 439 pr_err("Not enough memory for reading perf file header\n");
524 return -1; 440 return -1;
525 } 441 }
526 442
527 if (!no_buildid) 443 rec->session = session;
444
445 if (!rec->no_buildid)
528 perf_header__set_feat(&session->header, HEADER_BUILD_ID); 446 perf_header__set_feat(&session->header, HEADER_BUILD_ID);
529 447
530 if (!file_new) { 448 if (!rec->file_new) {
531 err = perf_session__read_header(session, output); 449 err = perf_session__read_header(session, output);
532 if (err < 0) 450 if (err < 0)
533 goto out_delete_session; 451 goto out_delete_session;
@@ -549,94 +467,50 @@ static int __cmd_record(int argc, const char **argv)
549 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY); 467 perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
550 perf_header__set_feat(&session->header, HEADER_CPUID); 468 perf_header__set_feat(&session->header, HEADER_CPUID);
551 469
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) { 470 if (forks) {
557 child_pid = fork(); 471 err = perf_evlist__prepare_workload(evsel_list, opts, argv);
558 if (child_pid < 0) { 472 if (err < 0) {
559 perror("failed to fork"); 473 pr_err("Couldn't run the workload!\n");
560 exit(-1); 474 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 } 475 }
607 close(child_ready_pipe[0]);
608 } 476 }
609 477
610 open_counters(evsel_list); 478 perf_record__open(rec);
611 479
612 /* 480 /*
613 * perf_session__delete(session) will be called at atexit_header() 481 * perf_session__delete(session) will be called at perf_record__exit()
614 */ 482 */
615 atexit(atexit_header); 483 on_exit(perf_record__exit, rec);
616 484
617 if (pipe_output) { 485 if (opts->pipe_output) {
618 err = perf_header__write_pipe(output); 486 err = perf_header__write_pipe(output);
619 if (err < 0) 487 if (err < 0)
620 return err; 488 return err;
621 } else if (file_new) { 489 } else if (rec->file_new) {
622 err = perf_session__write_header(session, evsel_list, 490 err = perf_session__write_header(session, evsel_list,
623 output, false); 491 output, false);
624 if (err < 0) 492 if (err < 0)
625 return err; 493 return err;
626 } 494 }
627 495
628 post_processing_offset = lseek(output, 0, SEEK_CUR); 496 rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
497
498 machine = perf_session__find_host_machine(session);
499 if (!machine) {
500 pr_err("Couldn't find native kernel information.\n");
501 return -1;
502 }
629 503
630 if (pipe_output) { 504 if (opts->pipe_output) {
631 err = perf_session__synthesize_attrs(session, 505 err = perf_event__synthesize_attrs(tool, session,
632 process_synthesized_event); 506 process_synthesized_event);
633 if (err < 0) { 507 if (err < 0) {
634 pr_err("Couldn't synthesize attrs.\n"); 508 pr_err("Couldn't synthesize attrs.\n");
635 return err; 509 return err;
636 } 510 }
637 511
638 err = perf_event__synthesize_event_types(process_synthesized_event, 512 err = perf_event__synthesize_event_types(tool, process_synthesized_event,
639 session); 513 machine);
640 if (err < 0) { 514 if (err < 0) {
641 pr_err("Couldn't synthesize event_types.\n"); 515 pr_err("Couldn't synthesize event_types.\n");
642 return err; 516 return err;
@@ -651,56 +525,49 @@ static int __cmd_record(int argc, const char **argv)
651 * return this more properly and also 525 * return this more properly and also
652 * propagate errors that now are calling die() 526 * propagate errors that now are calling die()
653 */ 527 */
654 err = perf_event__synthesize_tracing_data(output, evsel_list, 528 err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
655 process_synthesized_event, 529 process_synthesized_event);
656 session);
657 if (err <= 0) { 530 if (err <= 0) {
658 pr_err("Couldn't record tracing data.\n"); 531 pr_err("Couldn't record tracing data.\n");
659 return err; 532 return err;
660 } 533 }
661 advance_output(err); 534 advance_output(rec, err);
662 } 535 }
663 } 536 }
664 537
665 machine = perf_session__find_host_machine(session); 538 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
666 if (!machine) { 539 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) 540 if (err < 0)
674 err = perf_event__synthesize_kernel_mmap(process_synthesized_event, 541 err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
675 session, machine, "_stext"); 542 machine, "_stext");
676 if (err < 0) 543 if (err < 0)
677 pr_err("Couldn't record kernel reference relocation symbol\n" 544 pr_err("Couldn't record kernel reference relocation symbol\n"
678 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 545 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
679 "Check /proc/kallsyms permission or run as root.\n"); 546 "Check /proc/kallsyms permission or run as root.\n");
680 547
681 err = perf_event__synthesize_modules(process_synthesized_event, 548 err = perf_event__synthesize_modules(tool, process_synthesized_event,
682 session, machine); 549 machine);
683 if (err < 0) 550 if (err < 0)
684 pr_err("Couldn't record kernel module information.\n" 551 pr_err("Couldn't record kernel module information.\n"
685 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n" 552 "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
686 "Check /proc/modules permission or run as root.\n"); 553 "Check /proc/modules permission or run as root.\n");
687 554
688 if (perf_guest) 555 if (perf_guest)
689 perf_session__process_machines(session, 556 perf_session__process_machines(session, tool,
690 perf_event__synthesize_guest_os); 557 perf_event__synthesize_guest_os);
691 558
692 if (!system_wide) 559 if (!opts->system_wide)
693 perf_event__synthesize_thread_map(evsel_list->threads, 560 perf_event__synthesize_thread_map(tool, evsel_list->threads,
694 process_synthesized_event, 561 process_synthesized_event,
695 session); 562 machine);
696 else 563 else
697 perf_event__synthesize_threads(process_synthesized_event, 564 perf_event__synthesize_threads(tool, process_synthesized_event,
698 session); 565 machine);
699 566
700 if (realtime_prio) { 567 if (rec->realtime_prio) {
701 struct sched_param param; 568 struct sched_param param;
702 569
703 param.sched_priority = realtime_prio; 570 param.sched_priority = rec->realtime_prio;
704 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 571 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
705 pr_err("Could not set realtime priority.\n"); 572 pr_err("Could not set realtime priority.\n");
706 exit(-1); 573 exit(-1);
@@ -713,14 +580,14 @@ static int __cmd_record(int argc, const char **argv)
713 * Let the child rip 580 * Let the child rip
714 */ 581 */
715 if (forks) 582 if (forks)
716 close(go_pipe[1]); 583 perf_evlist__start_workload(evsel_list);
717 584
718 for (;;) { 585 for (;;) {
719 int hits = samples; 586 int hits = rec->samples;
720 587
721 mmap_read_all(); 588 perf_record__mmap_read_all(rec);
722 589
723 if (hits == samples) { 590 if (hits == rec->samples) {
724 if (done) 591 if (done)
725 break; 592 break;
726 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1); 593 err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
@@ -741,9 +608,9 @@ static int __cmd_record(int argc, const char **argv)
741 */ 608 */
742 fprintf(stderr, 609 fprintf(stderr,
743 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n", 610 "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
744 (double)bytes_written / 1024.0 / 1024.0, 611 (double)rec->bytes_written / 1024.0 / 1024.0,
745 output_name, 612 output_name,
746 bytes_written / 24); 613 rec->bytes_written / 24);
747 614
748 return 0; 615 return 0;
749 616
@@ -758,58 +625,88 @@ static const char * const record_usage[] = {
758 NULL 625 NULL
759}; 626};
760 627
761static bool force, append_file; 628/*
629 * XXX Ideally would be local to cmd_record() and passed to a perf_record__new
630 * because we need to have access to it in perf_record__exit, that is called
631 * after cmd_record() exits, but since record_options need to be accessible to
632 * builtin-script, leave it here.
633 *
634 * At least we don't ouch it in all the other functions here directly.
635 *
636 * Just say no to tons of global variables, sigh.
637 */
638static struct perf_record record = {
639 .opts = {
640 .target_pid = -1,
641 .target_tid = -1,
642 .mmap_pages = UINT_MAX,
643 .user_freq = UINT_MAX,
644 .user_interval = ULLONG_MAX,
645 .freq = 1000,
646 .sample_id_all_avail = true,
647 },
648 .write_mode = WRITE_FORCE,
649 .file_new = true,
650};
762 651
652/*
653 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
654 * with it and switch to use the library functions in perf_evlist that came
655 * from builtin-record.c, i.e. use perf_record_opts,
656 * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record',
657 * using pipes, etc.
658 */
763const struct option record_options[] = { 659const struct option record_options[] = {
764 OPT_CALLBACK('e', "event", &evsel_list, "event", 660 OPT_CALLBACK('e', "event", &record.evlist, "event",
765 "event selector. use 'perf list' to list available events", 661 "event selector. use 'perf list' to list available events",
766 parse_events_option), 662 parse_events_option),
767 OPT_CALLBACK(0, "filter", &evsel_list, "filter", 663 OPT_CALLBACK(0, "filter", &record.evlist, "filter",
768 "event filter", parse_filter), 664 "event filter", parse_filter),
769 OPT_INTEGER('p', "pid", &target_pid, 665 OPT_INTEGER('p', "pid", &record.opts.target_pid,
770 "record events on existing process id"), 666 "record events on existing process id"),
771 OPT_INTEGER('t', "tid", &target_tid, 667 OPT_INTEGER('t', "tid", &record.opts.target_tid,
772 "record events on existing thread id"), 668 "record events on existing thread id"),
773 OPT_INTEGER('r', "realtime", &realtime_prio, 669 OPT_INTEGER('r', "realtime", &record.realtime_prio,
774 "collect data with this RT SCHED_FIFO priority"), 670 "collect data with this RT SCHED_FIFO priority"),
775 OPT_BOOLEAN('D', "no-delay", &nodelay, 671 OPT_BOOLEAN('D', "no-delay", &record.opts.no_delay,
776 "collect data without buffering"), 672 "collect data without buffering"),
777 OPT_BOOLEAN('R', "raw-samples", &raw_samples, 673 OPT_BOOLEAN('R', "raw-samples", &record.opts.raw_samples,
778 "collect raw sample records from all opened counters"), 674 "collect raw sample records from all opened counters"),
779 OPT_BOOLEAN('a', "all-cpus", &system_wide, 675 OPT_BOOLEAN('a', "all-cpus", &record.opts.system_wide,
780 "system-wide collection from all CPUs"), 676 "system-wide collection from all CPUs"),
781 OPT_BOOLEAN('A', "append", &append_file, 677 OPT_BOOLEAN('A', "append", &record.append_file,
782 "append to the output file to do incremental profiling"), 678 "append to the output file to do incremental profiling"),
783 OPT_STRING('C', "cpu", &cpu_list, "cpu", 679 OPT_STRING('C', "cpu", &record.opts.cpu_list, "cpu",
784 "list of cpus to monitor"), 680 "list of cpus to monitor"),
785 OPT_BOOLEAN('f', "force", &force, 681 OPT_BOOLEAN('f', "force", &record.force,
786 "overwrite existing data file (deprecated)"), 682 "overwrite existing data file (deprecated)"),
787 OPT_U64('c', "count", &user_interval, "event period to sample"), 683 OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
788 OPT_STRING('o', "output", &output_name, "file", 684 OPT_STRING('o', "output", &record.output_name, "file",
789 "output file name"), 685 "output file name"),
790 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 686 OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
791 "child tasks do not inherit counters"), 687 "child tasks do not inherit counters"),
792 OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"), 688 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"), 689 OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
794 OPT_BOOLEAN(0, "group", &group, 690 "number of mmap data pages"),
691 OPT_BOOLEAN(0, "group", &record.opts.group,
795 "put the counters into a counter group"), 692 "put the counters into a counter group"),
796 OPT_BOOLEAN('g', "call-graph", &call_graph, 693 OPT_BOOLEAN('g', "call-graph", &record.opts.call_graph,
797 "do call-graph (stack chain/backtrace) recording"), 694 "do call-graph (stack chain/backtrace) recording"),
798 OPT_INCR('v', "verbose", &verbose, 695 OPT_INCR('v', "verbose", &verbose,
799 "be more verbose (show counter open errors, etc)"), 696 "be more verbose (show counter open errors, etc)"),
800 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), 697 OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
801 OPT_BOOLEAN('s', "stat", &inherit_stat, 698 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
802 "per thread counts"), 699 "per thread counts"),
803 OPT_BOOLEAN('d', "data", &sample_address, 700 OPT_BOOLEAN('d', "data", &record.opts.sample_address,
804 "Sample addresses"), 701 "Sample addresses"),
805 OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"), 702 OPT_BOOLEAN('T', "timestamp", &record.opts.sample_time, "Sample timestamps"),
806 OPT_BOOLEAN('n', "no-samples", &no_samples, 703 OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
807 "don't sample"), 704 "don't sample"),
808 OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache, 705 OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache,
809 "do not update the buildid cache"), 706 "do not update the buildid cache"),
810 OPT_BOOLEAN('B', "no-buildid", &no_buildid, 707 OPT_BOOLEAN('B', "no-buildid", &record.no_buildid,
811 "do not collect buildids in perf.data"), 708 "do not collect buildids in perf.data"),
812 OPT_CALLBACK('G', "cgroup", &evsel_list, "name", 709 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
813 "monitor event in cgroup name only", 710 "monitor event in cgroup name only",
814 parse_cgroups), 711 parse_cgroups),
815 OPT_END() 712 OPT_END()
@@ -819,6 +716,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
819{ 716{
820 int err = -ENOMEM; 717 int err = -ENOMEM;
821 struct perf_evsel *pos; 718 struct perf_evsel *pos;
719 struct perf_evlist *evsel_list;
720 struct perf_record *rec = &record;
822 721
823 perf_header__set_cmdline(argc, argv); 722 perf_header__set_cmdline(argc, argv);
824 723
@@ -826,23 +725,25 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
826 if (evsel_list == NULL) 725 if (evsel_list == NULL)
827 return -ENOMEM; 726 return -ENOMEM;
828 727
728 rec->evlist = evsel_list;
729
829 argc = parse_options(argc, argv, record_options, record_usage, 730 argc = parse_options(argc, argv, record_options, record_usage,
830 PARSE_OPT_STOP_AT_NON_OPTION); 731 PARSE_OPT_STOP_AT_NON_OPTION);
831 if (!argc && target_pid == -1 && target_tid == -1 && 732 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
832 !system_wide && !cpu_list) 733 !rec->opts.system_wide && !rec->opts.cpu_list)
833 usage_with_options(record_usage, record_options); 734 usage_with_options(record_usage, record_options);
834 735
835 if (force && append_file) { 736 if (rec->force && rec->append_file) {
836 fprintf(stderr, "Can't overwrite and append at the same time." 737 fprintf(stderr, "Can't overwrite and append at the same time."
837 " You need to choose between -f and -A"); 738 " You need to choose between -f and -A");
838 usage_with_options(record_usage, record_options); 739 usage_with_options(record_usage, record_options);
839 } else if (append_file) { 740 } else if (rec->append_file) {
840 write_mode = WRITE_APPEND; 741 rec->write_mode = WRITE_APPEND;
841 } else { 742 } else {
842 write_mode = WRITE_FORCE; 743 rec->write_mode = WRITE_FORCE;
843 } 744 }
844 745
845 if (nr_cgroups && !system_wide) { 746 if (nr_cgroups && !rec->opts.system_wide) {
846 fprintf(stderr, "cgroup monitoring only available in" 747 fprintf(stderr, "cgroup monitoring only available in"
847 " system-wide mode\n"); 748 " system-wide mode\n");
848 usage_with_options(record_usage, record_options); 749 usage_with_options(record_usage, record_options);
@@ -860,7 +761,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" 761"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
861"even with a suitable vmlinux or kallsyms file.\n\n"); 762"even with a suitable vmlinux or kallsyms file.\n\n");
862 763
863 if (no_buildid_cache || no_buildid) 764 if (rec->no_buildid_cache || rec->no_buildid)
864 disable_buildid_cache(); 765 disable_buildid_cache();
865 766
866 if (evsel_list->nr_entries == 0 && 767 if (evsel_list->nr_entries == 0 &&
@@ -869,43 +770,37 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
869 goto out_symbol_exit; 770 goto out_symbol_exit;
870 } 771 }
871 772
872 if (target_pid != -1) 773 if (rec->opts.target_pid != -1)
873 target_tid = target_pid; 774 rec->opts.target_tid = rec->opts.target_pid;
874 775
875 if (perf_evlist__create_maps(evsel_list, target_pid, 776 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
876 target_tid, cpu_list) < 0) 777 rec->opts.target_tid, rec->opts.cpu_list) < 0)
877 usage_with_options(record_usage, record_options); 778 usage_with_options(record_usage, record_options);
878 779
879 list_for_each_entry(pos, &evsel_list->entries, node) { 780 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))) 781 if (perf_header__push_event(pos->attr.config, event_name(pos)))
884 goto out_free_fd; 782 goto out_free_fd;
885 } 783 }
886 784
887 if (perf_evlist__alloc_pollfd(evsel_list) < 0) 785 if (rec->opts.user_interval != ULLONG_MAX)
888 goto out_free_fd; 786 rec->opts.default_interval = rec->opts.user_interval;
889 787 if (rec->opts.user_freq != UINT_MAX)
890 if (user_interval != ULLONG_MAX) 788 rec->opts.freq = rec->opts.user_freq;
891 default_interval = user_interval;
892 if (user_freq != UINT_MAX)
893 freq = user_freq;
894 789
895 /* 790 /*
896 * User specified count overrides default frequency. 791 * User specified count overrides default frequency.
897 */ 792 */
898 if (default_interval) 793 if (rec->opts.default_interval)
899 freq = 0; 794 rec->opts.freq = 0;
900 else if (freq) { 795 else if (rec->opts.freq) {
901 default_interval = freq; 796 rec->opts.default_interval = rec->opts.freq;
902 } else { 797 } else {
903 fprintf(stderr, "frequency and count are zero, aborting\n"); 798 fprintf(stderr, "frequency and count are zero, aborting\n");
904 err = -EINVAL; 799 err = -EINVAL;
905 goto out_free_fd; 800 goto out_free_fd;
906 } 801 }
907 802
908 err = __cmd_record(argc, argv); 803 err = __cmd_record(&record, argc, argv);
909out_free_fd: 804out_free_fd:
910 perf_evlist__delete_maps(evsel_list); 805 perf_evlist__delete_maps(evsel_list);
911out_symbol_exit: 806out_symbol_exit:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 4d7c8340c326..ece7c5d3f504 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,8 @@ 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",
325 rep->input_name);
331 goto out_delete; 326 goto out_delete;
332 } 327 }
333 328
@@ -335,7 +330,7 @@ static int __cmd_report(void)
335 perf_evlist__tui_browse_hists(session->evlist, help, 330 perf_evlist__tui_browse_hists(session->evlist, help,
336 NULL, NULL, 0); 331 NULL, NULL, 0);
337 } else 332 } else
338 perf_evlist__tty_browse_hists(session->evlist, help); 333 perf_evlist__tty_browse_hists(session->evlist, rep, help);
339 334
340out_delete: 335out_delete:
341 /* 336 /*
@@ -354,9 +349,9 @@ out_delete:
354} 349}
355 350
356static int 351static int
357parse_callchain_opt(const struct option *opt __used, const char *arg, 352parse_callchain_opt(const struct option *opt, const char *arg, int unset)
358 int unset)
359{ 353{
354 struct perf_report *rep = (struct perf_report *)opt->value;
360 char *tok, *tok2; 355 char *tok, *tok2;
361 char *endptr; 356 char *endptr;
362 357
@@ -364,7 +359,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
364 * --no-call-graph 359 * --no-call-graph
365 */ 360 */
366 if (unset) { 361 if (unset) {
367 dont_use_callchains = true; 362 rep->dont_use_callchains = true;
368 return 0; 363 return 0;
369 } 364 }
370 365
@@ -433,13 +428,34 @@ setup:
433 return 0; 428 return 0;
434} 429}
435 430
436static const char * const report_usage[] = { 431int cmd_report(int argc, const char **argv, const char *prefix __used)
437 "perf report [<options>] <command>", 432{
438 NULL 433 char callchain_default_opt[] = "fractal,0.5,callee";
439}; 434 const char * const report_usage[] = {
440 435 "perf report [<options>] <command>",
441static const struct option options[] = { 436 NULL
442 OPT_STRING('i', "input", &input_name, "file", 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 .input_name = "perf.data",
455 .pretty_printing_style = "normal",
456 };
457 const struct option options[] = {
458 OPT_STRING('i', "input", &report.input_name, "file",
443 "input file name"), 459 "input file name"),
444 OPT_INCR('v', "verbose", &verbose, 460 OPT_INCR('v', "verbose", &verbose,
445 "be more verbose (show symbol address, etc)"), 461 "be more verbose (show symbol address, etc)"),
@@ -449,17 +465,18 @@ static const struct option options[] = {
449 "file", "vmlinux pathname"), 465 "file", "vmlinux pathname"),
450 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, 466 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
451 "file", "kallsyms pathname"), 467 "file", "kallsyms pathname"),
452 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 468 OPT_BOOLEAN('f', "force", &report.force, "don't complain, do it"),
453 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, 469 OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
454 "load module symbols - WARNING: use only with -k and LIVE kernel"), 470 "load module symbols - WARNING: use only with -k and LIVE kernel"),
455 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 471 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
456 "Show a column with the number of samples"), 472 "Show a column with the number of samples"),
457 OPT_BOOLEAN('T', "threads", &show_threads, 473 OPT_BOOLEAN('T', "threads", &report.show_threads,
458 "Show per-thread event counters"), 474 "Show per-thread event counters"),
459 OPT_STRING(0, "pretty", &pretty_printing_style, "key", 475 OPT_STRING(0, "pretty", &report.pretty_printing_style, "key",
460 "pretty printing style key: normal raw"), 476 "pretty printing style key: normal raw"),
461 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 477 OPT_BOOLEAN(0, "tui", &report.use_tui, "Use the TUI interface"),
462 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 478 OPT_BOOLEAN(0, "stdio", &report.use_stdio,
479 "Use the stdio interface"),
463 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 480 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
464 "sort by key(s): pid, comm, dso, symbol, parent"), 481 "sort by key(s): pid, comm, dso, symbol, parent"),
465 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, 482 OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
@@ -468,13 +485,14 @@ static const struct option options[] = {
468 "regex filter to identify parent, see: '--sort parent'"), 485 "regex filter to identify parent, see: '--sort parent'"),
469 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 486 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
470 "Only display entries with parent-match"), 487 "Only display entries with parent-match"),
471 OPT_CALLBACK_DEFAULT('g', "call-graph", NULL, "output_type,min_percent, call_order", 488 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, "output_type,min_percent, call_order",
472 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. " 489 "Display callchains using output_type (graph, flat, fractal, or none) , min percent threshold and callchain order. "
473 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt), 490 "Default: fractal,0.5,callee", &parse_callchain_opt, callchain_default_opt),
474 OPT_BOOLEAN('G', "inverted", &inverted_callchain, "alias for inverted call graph"), 491 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
492 "alias for inverted call graph"),
475 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 493 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
476 "only consider symbols in these dsos"), 494 "only consider symbols in these dsos"),
477 OPT_STRING('C', "comms", &symbol_conf.comm_list_str, "comm[,comm...]", 495 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
478 "only consider symbols in these comms"), 496 "only consider symbols in these comms"),
479 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 497 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
480 "only consider these symbols"), 498 "only consider these symbols"),
@@ -484,12 +502,13 @@ static const struct option options[] = {
484 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 502 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
485 "separator for columns, no spaces will be added between " 503 "separator for columns, no spaces will be added between "
486 "columns '.' is reserved."), 504 "columns '.' is reserved."),
487 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 505 OPT_BOOLEAN('U', "hide-unresolved", &report.hide_unresolved,
488 "Only display entries resolved to a symbol"), 506 "Only display entries resolved to a symbol"),
489 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 507 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
490 "Look for files with symbols relative to this directory"), 508 "Look for files with symbols relative to this directory"),
491 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 509 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
492 OPT_BOOLEAN('I', "show-info", &show_full_info, 510 "list of cpus to profile"),
511 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
493 "Display extended information about perf.data file"), 512 "Display extended information about perf.data file"),
494 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 513 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
495 "Interleave source code with assembly code (default)"), 514 "Interleave source code with assembly code (default)"),
@@ -500,21 +519,19 @@ static const struct option options[] = {
500 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 519 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
501 "Show a column with the sum of periods"), 520 "Show a column with the sum of periods"),
502 OPT_END() 521 OPT_END()
503}; 522 };
504 523
505int cmd_report(int argc, const char **argv, const char *prefix __used)
506{
507 argc = parse_options(argc, argv, options, report_usage, 0); 524 argc = parse_options(argc, argv, options, report_usage, 0);
508 525
509 if (use_stdio) 526 if (report.use_stdio)
510 use_browser = 0; 527 use_browser = 0;
511 else if (use_tui) 528 else if (report.use_tui)
512 use_browser = 1; 529 use_browser = 1;
513 530
514 if (inverted_callchain) 531 if (report.inverted_callchain)
515 callchain_param.order = ORDER_CALLER; 532 callchain_param.order = ORDER_CALLER;
516 533
517 if (strcmp(input_name, "-") != 0) 534 if (strcmp(report.input_name, "-") != 0)
518 setup_browser(true); 535 setup_browser(true);
519 else 536 else
520 use_browser = 0; 537 use_browser = 0;
@@ -525,7 +542,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
525 */ 542 */
526 if (use_browser > 0) { 543 if (use_browser > 0) {
527 symbol_conf.priv_size = sizeof(struct annotation); 544 symbol_conf.priv_size = sizeof(struct annotation);
528 annotate_init = symbol__annotate_init; 545 report.annotate_init = symbol__annotate_init;
529 /* 546 /*
530 * For searching by name on the "Browse map details". 547 * For searching by name on the "Browse map details".
531 * providing it only in verbose mode not to bloat too 548 * providing it only in verbose mode not to bloat too
@@ -572,5 +589,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); 589 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); 590 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
574 591
575 return __cmd_report(); 592 return __cmd_report(&report);
576} 593}
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 5177964943e7..6284ed2317f2 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"
@@ -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
1648 if (perf_session__has_traces(session, "record -R")) { 1650 if (perf_session__has_traces(session, "record -R")) {
1649 err = perf_session__process_events(session, &event_ops); 1651 err = perf_session__process_events(session, &perf_sched);
1650 if (err) 1652 if (err)
1651 die("Failed to process events, error %d", err); 1653 die("Failed to process events, error %d", err);
1652 1654
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 2f62a2952269..619d6dcaa1d9 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -7,6 +7,7 @@
7#include "util/header.h" 7#include "util/header.h"
8#include "util/parse-options.h" 8#include "util/parse-options.h"
9#include "util/session.h" 9#include "util/session.h"
10#include "util/tool.h"
10#include "util/symbol.h" 11#include "util/symbol.h"
11#include "util/thread.h" 12#include "util/thread.h"
12#include "util/trace-event.h" 13#include "util/trace-event.h"
@@ -315,7 +316,7 @@ static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
315 316
316static void print_sample_addr(union perf_event *event, 317static void print_sample_addr(union perf_event *event,
317 struct perf_sample *sample, 318 struct perf_sample *sample,
318 struct perf_session *session, 319 struct machine *machine,
319 struct thread *thread, 320 struct thread *thread,
320 struct perf_event_attr *attr) 321 struct perf_event_attr *attr)
321{ 322{
@@ -328,11 +329,11 @@ static void print_sample_addr(union perf_event *event,
328 if (!sample_addr_correlates_sym(attr)) 329 if (!sample_addr_correlates_sym(attr))
329 return; 330 return;
330 331
331 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 332 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
332 event->ip.pid, sample->addr, &al); 333 sample->addr, &al);
333 if (!al.map) 334 if (!al.map)
334 thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE, 335 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
335 event->ip.pid, sample->addr, &al); 336 sample->addr, &al);
336 337
337 al.cpu = sample->cpu; 338 al.cpu = sample->cpu;
338 al.sym = NULL; 339 al.sym = NULL;
@@ -362,7 +363,7 @@ static void print_sample_addr(union perf_event *event,
362static void process_event(union perf_event *event __unused, 363static void process_event(union perf_event *event __unused,
363 struct perf_sample *sample, 364 struct perf_sample *sample,
364 struct perf_evsel *evsel, 365 struct perf_evsel *evsel,
365 struct perf_session *session, 366 struct machine *machine,
366 struct thread *thread) 367 struct thread *thread)
367{ 368{
368 struct perf_event_attr *attr = &evsel->attr; 369 struct perf_event_attr *attr = &evsel->attr;
@@ -377,15 +378,15 @@ static void process_event(union perf_event *event __unused,
377 sample->raw_size); 378 sample->raw_size);
378 379
379 if (PRINT_FIELD(ADDR)) 380 if (PRINT_FIELD(ADDR))
380 print_sample_addr(event, sample, session, thread, attr); 381 print_sample_addr(event, sample, machine, thread, attr);
381 382
382 if (PRINT_FIELD(IP)) { 383 if (PRINT_FIELD(IP)) {
383 if (!symbol_conf.use_callchain) 384 if (!symbol_conf.use_callchain)
384 printf(" "); 385 printf(" ");
385 else 386 else
386 printf("\n"); 387 printf("\n");
387 perf_session__print_ip(event, sample, session, 388 perf_event__print_ip(event, sample, machine, evsel,
388 PRINT_FIELD(SYM), PRINT_FIELD(DSO)); 389 PRINT_FIELD(SYM), PRINT_FIELD(DSO));
389 } 390 }
390 391
391 printf("\n"); 392 printf("\n");
@@ -434,12 +435,14 @@ static int cleanup_scripting(void)
434 435
435static char const *input_name = "perf.data"; 436static char const *input_name = "perf.data";
436 437
437static int process_sample_event(union perf_event *event, 438static int process_sample_event(struct perf_tool *tool __used,
439 union perf_event *event,
438 struct perf_sample *sample, 440 struct perf_sample *sample,
439 struct perf_evsel *evsel, 441 struct perf_evsel *evsel,
440 struct perf_session *session) 442 struct machine *machine)
441{ 443{
442 struct thread *thread = perf_session__findnew(session, event->ip.pid); 444 struct addr_location al;
445 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
443 446
444 if (thread == NULL) { 447 if (thread == NULL) {
445 pr_debug("problem processing %d event, skipping it.\n", 448 pr_debug("problem processing %d event, skipping it.\n",
@@ -458,16 +461,25 @@ static int process_sample_event(union perf_event *event,
458 return 0; 461 return 0;
459 } 462 }
460 463
464 if (perf_event__preprocess_sample(event, machine, &al, sample, 0) < 0) {
465 pr_err("problem processing %d event, skipping it.\n",
466 event->header.type);
467 return -1;
468 }
469
470 if (al.filtered)
471 return 0;
472
461 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap)) 473 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
462 return 0; 474 return 0;
463 475
464 scripting_ops->process_event(event, sample, evsel, session, thread); 476 scripting_ops->process_event(event, sample, evsel, machine, thread);
465 477
466 session->hists.stats.total_period += sample->period; 478 evsel->hists.stats.total_period += sample->period;
467 return 0; 479 return 0;
468} 480}
469 481
470static struct perf_event_ops event_ops = { 482static struct perf_tool perf_script = {
471 .sample = process_sample_event, 483 .sample = process_sample_event,
472 .mmap = perf_event__process_mmap, 484 .mmap = perf_event__process_mmap,
473 .comm = perf_event__process_comm, 485 .comm = perf_event__process_comm,
@@ -494,7 +506,7 @@ static int __cmd_script(struct perf_session *session)
494 506
495 signal(SIGINT, sig_handler); 507 signal(SIGINT, sig_handler);
496 508
497 ret = perf_session__process_events(session, &event_ops); 509 ret = perf_session__process_events(session, &perf_script);
498 510
499 if (debug_mode) 511 if (debug_mode)
500 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); 512 pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1083,7 +1095,9 @@ static const struct option options[] = {
1083 OPT_CALLBACK('f', "fields", NULL, "str", 1095 OPT_CALLBACK('f', "fields", NULL, "str",
1084 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr", 1096 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
1085 parse_output_fields), 1097 parse_output_fields),
1086 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), 1098 OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
1099 OPT_STRING('c', "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
1100 "only display events for these comms"),
1087 OPT_BOOLEAN('I', "show-info", &show_full_info, 1101 OPT_BOOLEAN('I', "show-info", &show_full_info,
1088 "display extended information from perf.data file"), 1102 "display extended information from perf.data file"),
1089 OPT_END() 1103 OPT_END()
@@ -1261,7 +1275,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1261 if (!script_name) 1275 if (!script_name)
1262 setup_pager(); 1276 setup_pager();
1263 1277
1264 session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops); 1278 session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script);
1265 if (session == NULL) 1279 if (session == NULL)
1266 return -ENOMEM; 1280 return -ENOMEM;
1267 1281
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 955930e0a5c3..cc53de335ced 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1108,22 +1108,13 @@ static const struct option options[] = {
1108 */ 1108 */
1109static int add_default_attributes(void) 1109static int add_default_attributes(void)
1110{ 1110{
1111 struct perf_evsel *pos;
1112 size_t attr_nr = 0;
1113 size_t c;
1114
1115 /* Set attrs if no event is selected and !null_run: */ 1111 /* Set attrs if no event is selected and !null_run: */
1116 if (null_run) 1112 if (null_run)
1117 return 0; 1113 return 0;
1118 1114
1119 if (!evsel_list->nr_entries) { 1115 if (!evsel_list->nr_entries) {
1120 for (c = 0; c < ARRAY_SIZE(default_attrs); c++) { 1116 if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0)
1121 pos = perf_evsel__new(default_attrs + c, c + attr_nr); 1117 return -1;
1122 if (pos == NULL)
1123 return -1;
1124 perf_evlist__add(evsel_list, pos);
1125 }
1126 attr_nr += c;
1127 } 1118 }
1128 1119
1129 /* Detailed events get appended to the event list: */ 1120 /* Detailed events get appended to the event list: */
@@ -1132,38 +1123,21 @@ static int add_default_attributes(void)
1132 return 0; 1123 return 0;
1133 1124
1134 /* Append detailed run extra attributes: */ 1125 /* Append detailed run extra attributes: */
1135 for (c = 0; c < ARRAY_SIZE(detailed_attrs); c++) { 1126 if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0)
1136 pos = perf_evsel__new(detailed_attrs + c, c + attr_nr); 1127 return -1;
1137 if (pos == NULL)
1138 return -1;
1139 perf_evlist__add(evsel_list, pos);
1140 }
1141 attr_nr += c;
1142 1128
1143 if (detailed_run < 2) 1129 if (detailed_run < 2)
1144 return 0; 1130 return 0;
1145 1131
1146 /* Append very detailed run extra attributes: */ 1132 /* Append very detailed run extra attributes: */
1147 for (c = 0; c < ARRAY_SIZE(very_detailed_attrs); c++) { 1133 if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0)
1148 pos = perf_evsel__new(very_detailed_attrs + c, c + attr_nr); 1134 return -1;
1149 if (pos == NULL)
1150 return -1;
1151 perf_evlist__add(evsel_list, pos);
1152 }
1153 1135
1154 if (detailed_run < 3) 1136 if (detailed_run < 3)
1155 return 0; 1137 return 0;
1156 1138
1157 /* Append very, very detailed run extra attributes: */ 1139 /* Append very, very detailed run extra attributes: */
1158 for (c = 0; c < ARRAY_SIZE(very_very_detailed_attrs); c++) { 1140 return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs);
1159 pos = perf_evsel__new(very_very_detailed_attrs + c, c + attr_nr);
1160 if (pos == NULL)
1161 return -1;
1162 perf_evlist__add(evsel_list, pos);
1163 }
1164
1165
1166 return 0;
1167} 1141}
1168 1142
1169int cmd_stat(int argc, const char **argv, const char *prefix __used) 1143int cmd_stat(int argc, const char **argv, const char *prefix __used)
@@ -1267,8 +1241,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1267 1241
1268 list_for_each_entry(pos, &evsel_list->entries, node) { 1242 list_for_each_entry(pos, &evsel_list->entries, node) {
1269 if (perf_evsel__alloc_stat_priv(pos) < 0 || 1243 if (perf_evsel__alloc_stat_priv(pos) < 0 ||
1270 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 || 1244 perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0)
1271 perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
1272 goto out_free_fd; 1245 goto out_free_fd;
1273 } 1246 }
1274 1247
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 831d1baeac37..6173f780dce0 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -7,6 +7,7 @@
7 7
8#include "util/cache.h" 8#include "util/cache.h"
9#include "util/debug.h" 9#include "util/debug.h"
10#include "util/debugfs.h"
10#include "util/evlist.h" 11#include "util/evlist.h"
11#include "util/parse-options.h" 12#include "util/parse-options.h"
12#include "util/parse-events.h" 13#include "util/parse-events.h"
@@ -14,8 +15,6 @@
14#include "util/thread_map.h" 15#include "util/thread_map.h"
15#include "../../include/linux/hw_breakpoint.h" 16#include "../../include/linux/hw_breakpoint.h"
16 17
17static long page_size;
18
19static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 18static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
20{ 19{
21 bool *visited = symbol__priv(sym); 20 bool *visited = symbol__priv(sym);
@@ -31,6 +30,7 @@ static int test__vmlinux_matches_kallsyms(void)
31 struct map *kallsyms_map, *vmlinux_map; 30 struct map *kallsyms_map, *vmlinux_map;
32 struct machine kallsyms, vmlinux; 31 struct machine kallsyms, vmlinux;
33 enum map_type type = MAP__FUNCTION; 32 enum map_type type = MAP__FUNCTION;
33 long page_size = sysconf(_SC_PAGE_SIZE);
34 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; 34 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
35 35
36 /* 36 /*
@@ -247,7 +247,7 @@ static int trace_event__id(const char *evname)
247 247
248 if (asprintf(&filename, 248 if (asprintf(&filename,
249 "%s/syscalls/%s/id", 249 "%s/syscalls/%s/id",
250 debugfs_path, evname) < 0) 250 tracing_events_path, evname) < 0)
251 return -1; 251 return -1;
252 252
253 fd = open(filename, O_RDONLY); 253 fd = open(filename, O_RDONLY);
@@ -841,6 +841,336 @@ static int test__parse_events(void)
841 841
842 return ret; 842 return ret;
843} 843}
844
845static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp,
846 size_t *sizep)
847{
848 cpu_set_t *mask;
849 size_t size;
850 int i, cpu = -1, nrcpus = 1024;
851realloc:
852 mask = CPU_ALLOC(nrcpus);
853 size = CPU_ALLOC_SIZE(nrcpus);
854 CPU_ZERO_S(size, mask);
855
856 if (sched_getaffinity(pid, size, mask) == -1) {
857 CPU_FREE(mask);
858 if (errno == EINVAL && nrcpus < (1024 << 8)) {
859 nrcpus = nrcpus << 2;
860 goto realloc;
861 }
862 perror("sched_getaffinity");
863 return -1;
864 }
865
866 for (i = 0; i < nrcpus; i++) {
867 if (CPU_ISSET_S(i, size, mask)) {
868 if (cpu == -1) {
869 cpu = i;
870 *maskp = mask;
871 *sizep = size;
872 } else
873 CPU_CLR_S(i, size, mask);
874 }
875 }
876
877 if (cpu == -1)
878 CPU_FREE(mask);
879
880 return cpu;
881}
882
883static int test__PERF_RECORD(void)
884{
885 struct perf_record_opts opts = {
886 .target_pid = -1,
887 .target_tid = -1,
888 .no_delay = true,
889 .freq = 10,
890 .mmap_pages = 256,
891 .sample_id_all_avail = true,
892 };
893 cpu_set_t *cpu_mask = NULL;
894 size_t cpu_mask_size = 0;
895 struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
896 struct perf_evsel *evsel;
897 struct perf_sample sample;
898 const char *cmd = "sleep";
899 const char *argv[] = { cmd, "1", NULL, };
900 char *bname;
901 u64 sample_type, prev_time = 0;
902 bool found_cmd_mmap = false,
903 found_libc_mmap = false,
904 found_vdso_mmap = false,
905 found_ld_mmap = false;
906 int err = -1, errs = 0, i, wakeups = 0, sample_size;
907 u32 cpu;
908 int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
909
910 if (evlist == NULL || argv == NULL) {
911 pr_debug("Not enough memory to create evlist\n");
912 goto out;
913 }
914
915 /*
916 * We need at least one evsel in the evlist, use the default
917 * one: "cycles".
918 */
919 err = perf_evlist__add_default(evlist);
920 if (err < 0) {
921 pr_debug("Not enough memory to create evsel\n");
922 goto out_delete_evlist;
923 }
924
925 /*
926 * Create maps of threads and cpus to monitor. In this case
927 * we start with all threads and cpus (-1, -1) but then in
928 * perf_evlist__prepare_workload we'll fill in the only thread
929 * we're monitoring, the one forked there.
930 */
931 err = perf_evlist__create_maps(evlist, opts.target_pid,
932 opts.target_tid, opts.cpu_list);
933 if (err < 0) {
934 pr_debug("Not enough memory to create thread/cpu maps\n");
935 goto out_delete_evlist;
936 }
937
938 /*
939 * Prepare the workload in argv[] to run, it'll fork it, and then wait
940 * for perf_evlist__start_workload() to exec it. This is done this way
941 * so that we have time to open the evlist (calling sys_perf_event_open
942 * on all the fds) and then mmap them.
943 */
944 err = perf_evlist__prepare_workload(evlist, &opts, argv);
945 if (err < 0) {
946 pr_debug("Couldn't run the workload!\n");
947 goto out_delete_evlist;
948 }
949
950 /*
951 * Config the evsels, setting attr->comm on the first one, etc.
952 */
953 evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
954 evsel->attr.sample_type |= PERF_SAMPLE_CPU;
955 evsel->attr.sample_type |= PERF_SAMPLE_TID;
956 evsel->attr.sample_type |= PERF_SAMPLE_TIME;
957 perf_evlist__config_attrs(evlist, &opts);
958
959 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask,
960 &cpu_mask_size);
961 if (err < 0) {
962 pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno));
963 goto out_delete_evlist;
964 }
965
966 cpu = err;
967
968 /*
969 * So that we can check perf_sample.cpu on all the samples.
970 */
971 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) {
972 pr_debug("sched_setaffinity: %s\n", strerror(errno));
973 goto out_free_cpu_mask;
974 }
975
976 /*
977 * Call sys_perf_event_open on all the fds on all the evsels,
978 * grouping them if asked to.
979 */
980 err = perf_evlist__open(evlist, opts.group);
981 if (err < 0) {
982 pr_debug("perf_evlist__open: %s\n", strerror(errno));
983 goto out_delete_evlist;
984 }
985
986 /*
987 * mmap the first fd on a given CPU and ask for events for the other
988 * fds in the same CPU to be injected in the same mmap ring buffer
989 * (using ioctl(PERF_EVENT_IOC_SET_OUTPUT)).
990 */
991 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
992 if (err < 0) {
993 pr_debug("perf_evlist__mmap: %s\n", strerror(errno));
994 goto out_delete_evlist;
995 }
996
997 /*
998 * We'll need these two to parse the PERF_SAMPLE_* fields in each
999 * event.
1000 */
1001 sample_type = perf_evlist__sample_type(evlist);
1002 sample_size = __perf_evsel__sample_size(sample_type);
1003
1004 /*
1005 * Now that all is properly set up, enable the events, they will
1006 * count just on workload.pid, which will start...
1007 */
1008 perf_evlist__enable(evlist);
1009
1010 /*
1011 * Now!
1012 */
1013 perf_evlist__start_workload(evlist);
1014
1015 while (1) {
1016 int before = total_events;
1017
1018 for (i = 0; i < evlist->nr_mmaps; i++) {
1019 union perf_event *event;
1020
1021 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
1022 const u32 type = event->header.type;
1023 const char *name = perf_event__name(type);
1024
1025 ++total_events;
1026 if (type < PERF_RECORD_MAX)
1027 nr_events[type]++;
1028
1029 err = perf_event__parse_sample(event, sample_type,
1030 sample_size, true,
1031 &sample, false);
1032 if (err < 0) {
1033 if (verbose)
1034 perf_event__fprintf(event, stderr);
1035 pr_debug("Couldn't parse sample\n");
1036 goto out_err;
1037 }
1038
1039 if (verbose) {
1040 pr_info("%" PRIu64" %d ", sample.time, sample.cpu);
1041 perf_event__fprintf(event, stderr);
1042 }
1043
1044 if (prev_time > sample.time) {
1045 pr_debug("%s going backwards in time, prev=%" PRIu64 ", curr=%" PRIu64 "\n",
1046 name, prev_time, sample.time);
1047 ++errs;
1048 }
1049
1050 prev_time = sample.time;
1051
1052 if (sample.cpu != cpu) {
1053 pr_debug("%s with unexpected cpu, expected %d, got %d\n",
1054 name, cpu, sample.cpu);
1055 ++errs;
1056 }
1057
1058 if ((pid_t)sample.pid != evlist->workload.pid) {
1059 pr_debug("%s with unexpected pid, expected %d, got %d\n",
1060 name, evlist->workload.pid, sample.pid);
1061 ++errs;
1062 }
1063
1064 if ((pid_t)sample.tid != evlist->workload.pid) {
1065 pr_debug("%s with unexpected tid, expected %d, got %d\n",
1066 name, evlist->workload.pid, sample.tid);
1067 ++errs;
1068 }
1069
1070 if ((type == PERF_RECORD_COMM ||
1071 type == PERF_RECORD_MMAP ||
1072 type == PERF_RECORD_FORK ||
1073 type == PERF_RECORD_EXIT) &&
1074 (pid_t)event->comm.pid != evlist->workload.pid) {
1075 pr_debug("%s with unexpected pid/tid\n", name);
1076 ++errs;
1077 }
1078
1079 if ((type == PERF_RECORD_COMM ||
1080 type == PERF_RECORD_MMAP) &&
1081 event->comm.pid != event->comm.tid) {
1082 pr_debug("%s with different pid/tid!\n", name);
1083 ++errs;
1084 }
1085
1086 switch (type) {
1087 case PERF_RECORD_COMM:
1088 if (strcmp(event->comm.comm, cmd)) {
1089 pr_debug("%s with unexpected comm!\n", name);
1090 ++errs;
1091 }
1092 break;
1093 case PERF_RECORD_EXIT:
1094 goto found_exit;
1095 case PERF_RECORD_MMAP:
1096 bname = strrchr(event->mmap.filename, '/');
1097 if (bname != NULL) {
1098 if (!found_cmd_mmap)
1099 found_cmd_mmap = !strcmp(bname + 1, cmd);
1100 if (!found_libc_mmap)
1101 found_libc_mmap = !strncmp(bname + 1, "libc", 4);
1102 if (!found_ld_mmap)
1103 found_ld_mmap = !strncmp(bname + 1, "ld", 2);
1104 } else if (!found_vdso_mmap)
1105 found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]");
1106 break;
1107
1108 case PERF_RECORD_SAMPLE:
1109 /* Just ignore samples for now */
1110 break;
1111 default:
1112 pr_debug("Unexpected perf_event->header.type %d!\n",
1113 type);
1114 ++errs;
1115 }
1116 }
1117 }
1118
1119 /*
1120 * We don't use poll here because at least at 3.1 times the
1121 * PERF_RECORD_{!SAMPLE} events don't honour
1122 * perf_event_attr.wakeup_events, just PERF_EVENT_SAMPLE does.
1123 */
1124 if (total_events == before && false)
1125 poll(evlist->pollfd, evlist->nr_fds, -1);
1126
1127 sleep(1);
1128 if (++wakeups > 5) {
1129 pr_debug("No PERF_RECORD_EXIT event!\n");
1130 break;
1131 }
1132 }
1133
1134found_exit:
1135 if (nr_events[PERF_RECORD_COMM] > 1) {
1136 pr_debug("Excessive number of PERF_RECORD_COMM events!\n");
1137 ++errs;
1138 }
1139
1140 if (nr_events[PERF_RECORD_COMM] == 0) {
1141 pr_debug("Missing PERF_RECORD_COMM for %s!\n", cmd);
1142 ++errs;
1143 }
1144
1145 if (!found_cmd_mmap) {
1146 pr_debug("PERF_RECORD_MMAP for %s missing!\n", cmd);
1147 ++errs;
1148 }
1149
1150 if (!found_libc_mmap) {
1151 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "libc");
1152 ++errs;
1153 }
1154
1155 if (!found_ld_mmap) {
1156 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "ld");
1157 ++errs;
1158 }
1159
1160 if (!found_vdso_mmap) {
1161 pr_debug("PERF_RECORD_MMAP for %s missing!\n", "[vdso]");
1162 ++errs;
1163 }
1164out_err:
1165 perf_evlist__munmap(evlist);
1166out_free_cpu_mask:
1167 CPU_FREE(cpu_mask);
1168out_delete_evlist:
1169 perf_evlist__delete(evlist);
1170out:
1171 return (err < 0 || errs > 0) ? -1 : 0;
1172}
1173
844static struct test { 1174static struct test {
845 const char *desc; 1175 const char *desc;
846 int (*func)(void); 1176 int (*func)(void);
@@ -866,45 +1196,89 @@ static struct test {
866 .func = test__parse_events, 1196 .func = test__parse_events,
867 }, 1197 },
868 { 1198 {
1199 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1200 .func = test__PERF_RECORD,
1201 },
1202 {
869 .func = NULL, 1203 .func = NULL,
870 }, 1204 },
871}; 1205};
872 1206
873static int __cmd_test(void) 1207static bool perf_test__matches(int curr, int argc, const char *argv[])
874{ 1208{
875 int i = 0; 1209 int i;
1210
1211 if (argc == 0)
1212 return true;
876 1213
877 page_size = sysconf(_SC_PAGE_SIZE); 1214 for (i = 0; i < argc; ++i) {
1215 char *end;
1216 long nr = strtoul(argv[i], &end, 10);
1217
1218 if (*end == '\0') {
1219 if (nr == curr + 1)
1220 return true;
1221 continue;
1222 }
1223
1224 if (strstr(tests[curr].desc, argv[i]))
1225 return true;
1226 }
1227
1228 return false;
1229}
1230
1231static int __cmd_test(int argc, const char *argv[])
1232{
1233 int i = 0;
878 1234
879 while (tests[i].func) { 1235 while (tests[i].func) {
880 int err; 1236 int curr = i++, err;
881 pr_info("%2d: %s:", i + 1, tests[i].desc); 1237
1238 if (!perf_test__matches(curr, argc, argv))
1239 continue;
1240
1241 pr_info("%2d: %s:", i, tests[curr].desc);
882 pr_debug("\n--- start ---\n"); 1242 pr_debug("\n--- start ---\n");
883 err = tests[i].func(); 1243 err = tests[curr].func();
884 pr_debug("---- end ----\n%s:", tests[i].desc); 1244 pr_debug("---- end ----\n%s:", tests[curr].desc);
885 pr_info(" %s\n", err ? "FAILED!\n" : "Ok"); 1245 pr_info(" %s\n", err ? "FAILED!\n" : "Ok");
886 ++i;
887 } 1246 }
888 1247
889 return 0; 1248 return 0;
890} 1249}
891 1250
892static const char * const test_usage[] = { 1251static int perf_test__list(int argc, const char **argv)
893 "perf test [<options>]", 1252{
894 NULL, 1253 int i = 0;
895};
896 1254
897static const struct option test_options[] = { 1255 while (tests[i].func) {
1256 int curr = i++;
1257
1258 if (argc > 1 && !strstr(tests[curr].desc, argv[1]))
1259 continue;
1260
1261 pr_info("%2d: %s\n", i, tests[curr].desc);
1262 }
1263
1264 return 0;
1265}
1266
1267int cmd_test(int argc, const char **argv, const char *prefix __used)
1268{
1269 const char * const test_usage[] = {
1270 "perf test [<options>] [{list <test-name-fragment>|[<test-name-fragments>|<test-numbers>]}]",
1271 NULL,
1272 };
1273 const struct option test_options[] = {
898 OPT_INTEGER('v', "verbose", &verbose, 1274 OPT_INTEGER('v', "verbose", &verbose,
899 "be more verbose (show symbol address, etc)"), 1275 "be more verbose (show symbol address, etc)"),
900 OPT_END() 1276 OPT_END()
901}; 1277 };
902 1278
903int cmd_test(int argc, const char **argv, const char *prefix __used)
904{
905 argc = parse_options(argc, argv, test_options, test_usage, 0); 1279 argc = parse_options(argc, argv, test_options, test_usage, 0);
906 if (argc) 1280 if (argc >= 1 && !strcmp(argv[0], "list"))
907 usage_with_options(test_usage, test_options); 1281 return perf_test__list(argc, argv);
908 1282
909 symbol_conf.priv_size = sizeof(int); 1283 symbol_conf.priv_size = sizeof(int);
910 symbol_conf.sort_by_name = true; 1284 symbol_conf.sort_by_name = true;
@@ -915,5 +1289,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
915 1289
916 setup_pager(); 1290 setup_pager();
917 1291
918 return __cmd_test(); 1292 return __cmd_test(argc, argv);
919} 1293}
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index aa26f4d66d10..135376a37f97 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -19,6 +19,7 @@
19#include "util/color.h" 19#include "util/color.h"
20#include <linux/list.h> 20#include <linux/list.h>
21#include "util/cache.h" 21#include "util/cache.h"
22#include "util/evsel.h"
22#include <linux/rbtree.h> 23#include <linux/rbtree.h>
23#include "util/symbol.h" 24#include "util/symbol.h"
24#include "util/callchain.h" 25#include "util/callchain.h"
@@ -31,6 +32,7 @@
31#include "util/event.h" 32#include "util/event.h"
32#include "util/session.h" 33#include "util/session.h"
33#include "util/svghelper.h" 34#include "util/svghelper.h"
35#include "util/tool.h"
34 36
35#define SUPPORT_OLD_POWER_EVENTS 1 37#define SUPPORT_OLD_POWER_EVENTS 1
36#define PWR_EVENT_EXIT -1 38#define PWR_EVENT_EXIT -1
@@ -273,25 +275,28 @@ static int cpus_cstate_state[MAX_CPUS];
273static u64 cpus_pstate_start_times[MAX_CPUS]; 275static u64 cpus_pstate_start_times[MAX_CPUS];
274static u64 cpus_pstate_state[MAX_CPUS]; 276static u64 cpus_pstate_state[MAX_CPUS];
275 277
276static int process_comm_event(union perf_event *event, 278static int process_comm_event(struct perf_tool *tool __used,
279 union perf_event *event,
277 struct perf_sample *sample __used, 280 struct perf_sample *sample __used,
278 struct perf_session *session __used) 281 struct machine *machine __used)
279{ 282{
280 pid_set_comm(event->comm.tid, event->comm.comm); 283 pid_set_comm(event->comm.tid, event->comm.comm);
281 return 0; 284 return 0;
282} 285}
283 286
284static int process_fork_event(union perf_event *event, 287static int process_fork_event(struct perf_tool *tool __used,
288 union perf_event *event,
285 struct perf_sample *sample __used, 289 struct perf_sample *sample __used,
286 struct perf_session *session __used) 290 struct machine *machine __used)
287{ 291{
288 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); 292 pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
289 return 0; 293 return 0;
290} 294}
291 295
292static int process_exit_event(union perf_event *event, 296static int process_exit_event(struct perf_tool *tool __used,
297 union perf_event *event,
293 struct perf_sample *sample __used, 298 struct perf_sample *sample __used,
294 struct perf_session *session __used) 299 struct machine *machine __used)
295{ 300{
296 pid_exit(event->fork.pid, event->fork.time); 301 pid_exit(event->fork.pid, event->fork.time);
297 return 0; 302 return 0;
@@ -486,14 +491,15 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
486} 491}
487 492
488 493
489static int process_sample_event(union perf_event *event __used, 494static int process_sample_event(struct perf_tool *tool __used,
495 union perf_event *event __used,
490 struct perf_sample *sample, 496 struct perf_sample *sample,
491 struct perf_evsel *evsel __used, 497 struct perf_evsel *evsel,
492 struct perf_session *session) 498 struct machine *machine __used)
493{ 499{
494 struct trace_entry *te; 500 struct trace_entry *te;
495 501
496 if (session->sample_type & PERF_SAMPLE_TIME) { 502 if (evsel->attr.sample_type & PERF_SAMPLE_TIME) {
497 if (!first_time || first_time > sample->time) 503 if (!first_time || first_time > sample->time)
498 first_time = sample->time; 504 first_time = sample->time;
499 if (last_time < sample->time) 505 if (last_time < sample->time)
@@ -501,7 +507,7 @@ static int process_sample_event(union perf_event *event __used,
501 } 507 }
502 508
503 te = (void *)sample->raw_data; 509 te = (void *)sample->raw_data;
504 if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) { 510 if ((evsel->attr.sample_type & PERF_SAMPLE_RAW) && sample->raw_size > 0) {
505 char *event_str; 511 char *event_str;
506#ifdef SUPPORT_OLD_POWER_EVENTS 512#ifdef SUPPORT_OLD_POWER_EVENTS
507 struct power_entry_old *peo; 513 struct power_entry_old *peo;
@@ -974,7 +980,7 @@ static void write_svg_file(const char *filename)
974 svg_close(); 980 svg_close();
975} 981}
976 982
977static struct perf_event_ops event_ops = { 983static struct perf_tool perf_timechart = {
978 .comm = process_comm_event, 984 .comm = process_comm_event,
979 .fork = process_fork_event, 985 .fork = process_fork_event,
980 .exit = process_exit_event, 986 .exit = process_exit_event,
@@ -985,7 +991,7 @@ static struct perf_event_ops event_ops = {
985static int __cmd_timechart(void) 991static int __cmd_timechart(void)
986{ 992{
987 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 993 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
988 0, false, &event_ops); 994 0, false, &perf_timechart);
989 int ret = -EINVAL; 995 int ret = -EINVAL;
990 996
991 if (session == NULL) 997 if (session == NULL)
@@ -994,7 +1000,7 @@ static int __cmd_timechart(void)
994 if (!perf_session__has_traces(session, "timechart record")) 1000 if (!perf_session__has_traces(session, "timechart record"))
995 goto out_delete; 1001 goto out_delete;
996 1002
997 ret = perf_session__process_events(session, &event_ops); 1003 ret = perf_session__process_events(session, &perf_timechart);
998 if (ret) 1004 if (ret)
999 goto out_delete; 1005 goto out_delete;
1000 1006
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9cdedb58134..c3836b966ccf 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -64,44 +64,6 @@
64#include <linux/unistd.h> 64#include <linux/unistd.h>
65#include <linux/types.h> 65#include <linux/types.h>
66 66
67static struct perf_top top = {
68 .count_filter = 5,
69 .delay_secs = 2,
70 .target_pid = -1,
71 .target_tid = -1,
72 .freq = 1000, /* 1 KHz */
73};
74
75static bool system_wide = false;
76
77static bool use_tui, use_stdio;
78
79static bool sort_has_symbols;
80
81static bool dont_use_callchains;
82static char callchain_default_opt[] = "fractal,0.5,callee";
83
84
85static int default_interval = 0;
86
87static bool kptr_restrict_warned;
88static bool vmlinux_warned;
89static bool inherit = false;
90static int realtime_prio = 0;
91static bool group = false;
92static bool sample_id_all_avail = true;
93static unsigned int mmap_pages = 128;
94
95static bool dump_symtab = false;
96
97static struct winsize winsize;
98
99static const char *sym_filter = NULL;
100static int sym_pcnt_filter = 5;
101
102/*
103 * Source functions
104 */
105 67
106void get_term_dimensions(struct winsize *ws) 68void get_term_dimensions(struct winsize *ws)
107{ 69{
@@ -125,21 +87,23 @@ void get_term_dimensions(struct winsize *ws)
125 ws->ws_col = 80; 87 ws->ws_col = 80;
126} 88}
127 89
128static void update_print_entries(struct winsize *ws) 90static void perf_top__update_print_entries(struct perf_top *top)
129{ 91{
130 top.print_entries = ws->ws_row; 92 top->print_entries = top->winsize.ws_row;
131 93
132 if (top.print_entries > 9) 94 if (top->print_entries > 9)
133 top.print_entries -= 9; 95 top->print_entries -= 9;
134} 96}
135 97
136static void sig_winch_handler(int sig __used) 98static void perf_top__sig_winch(int sig __used, siginfo_t *info __used, void *arg)
137{ 99{
138 get_term_dimensions(&winsize); 100 struct perf_top *top = arg;
139 update_print_entries(&winsize); 101
102 get_term_dimensions(&top->winsize);
103 perf_top__update_print_entries(top);
140} 104}
141 105
142static int parse_source(struct hist_entry *he) 106static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
143{ 107{
144 struct symbol *sym; 108 struct symbol *sym;
145 struct annotation *notes; 109 struct annotation *notes;
@@ -170,7 +134,7 @@ static int parse_source(struct hist_entry *he)
170 134
171 pthread_mutex_lock(&notes->lock); 135 pthread_mutex_lock(&notes->lock);
172 136
173 if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { 137 if (symbol__alloc_hist(sym) < 0) {
174 pthread_mutex_unlock(&notes->lock); 138 pthread_mutex_unlock(&notes->lock);
175 pr_err("Not enough memory for annotating '%s' symbol!\n", 139 pr_err("Not enough memory for annotating '%s' symbol!\n",
176 sym->name); 140 sym->name);
@@ -181,7 +145,7 @@ static int parse_source(struct hist_entry *he)
181 err = symbol__annotate(sym, map, 0); 145 err = symbol__annotate(sym, map, 0);
182 if (err == 0) { 146 if (err == 0) {
183out_assign: 147out_assign:
184 top.sym_filter_entry = he; 148 top->sym_filter_entry = he;
185 } 149 }
186 150
187 pthread_mutex_unlock(&notes->lock); 151 pthread_mutex_unlock(&notes->lock);
@@ -194,14 +158,16 @@ static void __zero_source_counters(struct hist_entry *he)
194 symbol__annotate_zero_histograms(sym); 158 symbol__annotate_zero_histograms(sym);
195} 159}
196 160
197static void record_precise_ip(struct hist_entry *he, int counter, u64 ip) 161static void perf_top__record_precise_ip(struct perf_top *top,
162 struct hist_entry *he,
163 int counter, u64 ip)
198{ 164{
199 struct annotation *notes; 165 struct annotation *notes;
200 struct symbol *sym; 166 struct symbol *sym;
201 167
202 if (he == NULL || he->ms.sym == NULL || 168 if (he == NULL || he->ms.sym == NULL ||
203 ((top.sym_filter_entry == NULL || 169 ((top->sym_filter_entry == NULL ||
204 top.sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1)) 170 top->sym_filter_entry->ms.sym != he->ms.sym) && use_browser != 1))
205 return; 171 return;
206 172
207 sym = he->ms.sym; 173 sym = he->ms.sym;
@@ -210,8 +176,7 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
210 if (pthread_mutex_trylock(&notes->lock)) 176 if (pthread_mutex_trylock(&notes->lock))
211 return; 177 return;
212 178
213 if (notes->src == NULL && 179 if (notes->src == NULL && symbol__alloc_hist(sym) < 0) {
214 symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
215 pthread_mutex_unlock(&notes->lock); 180 pthread_mutex_unlock(&notes->lock);
216 pr_err("Not enough memory for annotating '%s' symbol!\n", 181 pr_err("Not enough memory for annotating '%s' symbol!\n",
217 sym->name); 182 sym->name);
@@ -225,8 +190,9 @@ static void record_precise_ip(struct hist_entry *he, int counter, u64 ip)
225 pthread_mutex_unlock(&notes->lock); 190 pthread_mutex_unlock(&notes->lock);
226} 191}
227 192
228static void show_details(struct hist_entry *he) 193static void perf_top__show_details(struct perf_top *top)
229{ 194{
195 struct hist_entry *he = top->sym_filter_entry;
230 struct annotation *notes; 196 struct annotation *notes;
231 struct symbol *symbol; 197 struct symbol *symbol;
232 int more; 198 int more;
@@ -242,15 +208,15 @@ static void show_details(struct hist_entry *he)
242 if (notes->src == NULL) 208 if (notes->src == NULL)
243 goto out_unlock; 209 goto out_unlock;
244 210
245 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); 211 printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name);
246 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 212 printf(" Events Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
247 213
248 more = symbol__annotate_printf(symbol, he->ms.map, top.sym_evsel->idx, 214 more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
249 0, sym_pcnt_filter, top.print_entries, 4); 215 0, top->sym_pcnt_filter, top->print_entries, 4);
250 if (top.zero) 216 if (top->zero)
251 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); 217 symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
252 else 218 else
253 symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx); 219 symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx);
254 if (more != 0) 220 if (more != 0)
255 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 221 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
256out_unlock: 222out_unlock:
@@ -259,11 +225,9 @@ out_unlock:
259 225
260static const char CONSOLE_CLEAR[] = ""; 226static const char CONSOLE_CLEAR[] = "";
261 227
262static struct hist_entry * 228static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
263 perf_session__add_hist_entry(struct perf_session *session, 229 struct addr_location *al,
264 struct addr_location *al, 230 struct perf_sample *sample)
265 struct perf_sample *sample,
266 struct perf_evsel *evsel)
267{ 231{
268 struct hist_entry *he; 232 struct hist_entry *he;
269 233
@@ -271,50 +235,51 @@ static struct hist_entry *
271 if (he == NULL) 235 if (he == NULL)
272 return NULL; 236 return NULL;
273 237
274 session->hists.stats.total_period += sample->period; 238 evsel->hists.stats.total_period += sample->period;
275 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 239 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
276 return he; 240 return he;
277} 241}
278 242
279static void print_sym_table(void) 243static void perf_top__print_sym_table(struct perf_top *top)
280{ 244{
281 char bf[160]; 245 char bf[160];
282 int printed = 0; 246 int printed = 0;
283 const int win_width = winsize.ws_col - 1; 247 const int win_width = top->winsize.ws_col - 1;
284 248
285 puts(CONSOLE_CLEAR); 249 puts(CONSOLE_CLEAR);
286 250
287 perf_top__header_snprintf(&top, bf, sizeof(bf)); 251 perf_top__header_snprintf(top, bf, sizeof(bf));
288 printf("%s\n", bf); 252 printf("%s\n", bf);
289 253
290 perf_top__reset_sample_counters(&top); 254 perf_top__reset_sample_counters(top);
291 255
292 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 256 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
293 257
294 if (top.sym_evsel->hists.stats.nr_lost_warned != 258 if (top->sym_evsel->hists.stats.nr_lost_warned !=
295 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) { 259 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
296 top.sym_evsel->hists.stats.nr_lost_warned = 260 top->sym_evsel->hists.stats.nr_lost_warned =
297 top.sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 261 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
298 color_fprintf(stdout, PERF_COLOR_RED, 262 color_fprintf(stdout, PERF_COLOR_RED,
299 "WARNING: LOST %d chunks, Check IO/CPU overload", 263 "WARNING: LOST %d chunks, Check IO/CPU overload",
300 top.sym_evsel->hists.stats.nr_lost_warned); 264 top->sym_evsel->hists.stats.nr_lost_warned);
301 ++printed; 265 ++printed;
302 } 266 }
303 267
304 if (top.sym_filter_entry) { 268 if (top->sym_filter_entry) {
305 show_details(top.sym_filter_entry); 269 perf_top__show_details(top);
306 return; 270 return;
307 } 271 }
308 272
309 hists__collapse_resort_threaded(&top.sym_evsel->hists); 273 hists__collapse_resort_threaded(&top->sym_evsel->hists);
310 hists__output_resort_threaded(&top.sym_evsel->hists); 274 hists__output_resort_threaded(&top->sym_evsel->hists);
311 hists__decay_entries_threaded(&top.sym_evsel->hists, 275 hists__decay_entries_threaded(&top->sym_evsel->hists,
312 top.hide_user_symbols, 276 top->hide_user_symbols,
313 top.hide_kernel_symbols); 277 top->hide_kernel_symbols);
314 hists__output_recalc_col_len(&top.sym_evsel->hists, winsize.ws_row - 3); 278 hists__output_recalc_col_len(&top->sym_evsel->hists,
279 top->winsize.ws_row - 3);
315 putchar('\n'); 280 putchar('\n');
316 hists__fprintf(&top.sym_evsel->hists, NULL, false, false, 281 hists__fprintf(&top->sym_evsel->hists, NULL, false, false,
317 winsize.ws_row - 4 - printed, win_width, stdout); 282 top->winsize.ws_row - 4 - printed, win_width, stdout);
318} 283}
319 284
320static void prompt_integer(int *target, const char *msg) 285static void prompt_integer(int *target, const char *msg)
@@ -352,17 +317,17 @@ static void prompt_percent(int *target, const char *msg)
352 *target = tmp; 317 *target = tmp;
353} 318}
354 319
355static void prompt_symbol(struct hist_entry **target, const char *msg) 320static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
356{ 321{
357 char *buf = malloc(0), *p; 322 char *buf = malloc(0), *p;
358 struct hist_entry *syme = *target, *n, *found = NULL; 323 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
359 struct rb_node *next; 324 struct rb_node *next;
360 size_t dummy = 0; 325 size_t dummy = 0;
361 326
362 /* zero counters of active symbol */ 327 /* zero counters of active symbol */
363 if (syme) { 328 if (syme) {
364 __zero_source_counters(syme); 329 __zero_source_counters(syme);
365 *target = NULL; 330 top->sym_filter_entry = NULL;
366 } 331 }
367 332
368 fprintf(stdout, "\n%s: ", msg); 333 fprintf(stdout, "\n%s: ", msg);
@@ -373,7 +338,7 @@ static void prompt_symbol(struct hist_entry **target, const char *msg)
373 if (p) 338 if (p)
374 *p = 0; 339 *p = 0;
375 340
376 next = rb_first(&top.sym_evsel->hists.entries); 341 next = rb_first(&top->sym_evsel->hists.entries);
377 while (next) { 342 while (next) {
378 n = rb_entry(next, struct hist_entry, rb_node); 343 n = rb_entry(next, struct hist_entry, rb_node);
379 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) { 344 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
@@ -388,45 +353,45 @@ static void prompt_symbol(struct hist_entry **target, const char *msg)
388 sleep(1); 353 sleep(1);
389 return; 354 return;
390 } else 355 } else
391 parse_source(found); 356 perf_top__parse_source(top, found);
392 357
393out_free: 358out_free:
394 free(buf); 359 free(buf);
395} 360}
396 361
397static void print_mapped_keys(void) 362static void perf_top__print_mapped_keys(struct perf_top *top)
398{ 363{
399 char *name = NULL; 364 char *name = NULL;
400 365
401 if (top.sym_filter_entry) { 366 if (top->sym_filter_entry) {
402 struct symbol *sym = top.sym_filter_entry->ms.sym; 367 struct symbol *sym = top->sym_filter_entry->ms.sym;
403 name = sym->name; 368 name = sym->name;
404 } 369 }
405 370
406 fprintf(stdout, "\nMapped keys:\n"); 371 fprintf(stdout, "\nMapped keys:\n");
407 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top.delay_secs); 372 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", top->delay_secs);
408 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top.print_entries); 373 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", top->print_entries);
409 374
410 if (top.evlist->nr_entries > 1) 375 if (top->evlist->nr_entries > 1)
411 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top.sym_evsel)); 376 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(top->sym_evsel));
412 377
413 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top.count_filter); 378 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", top->count_filter);
414 379
415 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 380 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", top->sym_pcnt_filter);
416 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 381 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
417 fprintf(stdout, "\t[S] stop annotation.\n"); 382 fprintf(stdout, "\t[S] stop annotation.\n");
418 383
419 fprintf(stdout, 384 fprintf(stdout,
420 "\t[K] hide kernel_symbols symbols. \t(%s)\n", 385 "\t[K] hide kernel_symbols symbols. \t(%s)\n",
421 top.hide_kernel_symbols ? "yes" : "no"); 386 top->hide_kernel_symbols ? "yes" : "no");
422 fprintf(stdout, 387 fprintf(stdout,
423 "\t[U] hide user symbols. \t(%s)\n", 388 "\t[U] hide user symbols. \t(%s)\n",
424 top.hide_user_symbols ? "yes" : "no"); 389 top->hide_user_symbols ? "yes" : "no");
425 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top.zero ? 1 : 0); 390 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", top->zero ? 1 : 0);
426 fprintf(stdout, "\t[qQ] quit.\n"); 391 fprintf(stdout, "\t[qQ] quit.\n");
427} 392}
428 393
429static int key_mapped(int c) 394static int perf_top__key_mapped(struct perf_top *top, int c)
430{ 395{
431 switch (c) { 396 switch (c) {
432 case 'd': 397 case 'd':
@@ -442,7 +407,7 @@ static int key_mapped(int c)
442 case 'S': 407 case 'S':
443 return 1; 408 return 1;
444 case 'E': 409 case 'E':
445 return top.evlist->nr_entries > 1 ? 1 : 0; 410 return top->evlist->nr_entries > 1 ? 1 : 0;
446 default: 411 default:
447 break; 412 break;
448 } 413 }
@@ -450,13 +415,13 @@ static int key_mapped(int c)
450 return 0; 415 return 0;
451} 416}
452 417
453static void handle_keypress(int c) 418static void perf_top__handle_keypress(struct perf_top *top, int c)
454{ 419{
455 if (!key_mapped(c)) { 420 if (!perf_top__key_mapped(top, c)) {
456 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 421 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
457 struct termios tc, save; 422 struct termios tc, save;
458 423
459 print_mapped_keys(); 424 perf_top__print_mapped_keys(top);
460 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 425 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
461 fflush(stdout); 426 fflush(stdout);
462 427
@@ -471,81 +436,86 @@ static void handle_keypress(int c)
471 c = getc(stdin); 436 c = getc(stdin);
472 437
473 tcsetattr(0, TCSAFLUSH, &save); 438 tcsetattr(0, TCSAFLUSH, &save);
474 if (!key_mapped(c)) 439 if (!perf_top__key_mapped(top, c))
475 return; 440 return;
476 } 441 }
477 442
478 switch (c) { 443 switch (c) {
479 case 'd': 444 case 'd':
480 prompt_integer(&top.delay_secs, "Enter display delay"); 445 prompt_integer(&top->delay_secs, "Enter display delay");
481 if (top.delay_secs < 1) 446 if (top->delay_secs < 1)
482 top.delay_secs = 1; 447 top->delay_secs = 1;
483 break; 448 break;
484 case 'e': 449 case 'e':
485 prompt_integer(&top.print_entries, "Enter display entries (lines)"); 450 prompt_integer(&top->print_entries, "Enter display entries (lines)");
486 if (top.print_entries == 0) { 451 if (top->print_entries == 0) {
487 sig_winch_handler(SIGWINCH); 452 struct sigaction act = {
488 signal(SIGWINCH, sig_winch_handler); 453 .sa_sigaction = perf_top__sig_winch,
454 .sa_flags = SA_SIGINFO,
455 };
456 perf_top__sig_winch(SIGWINCH, NULL, top);
457 sigaction(SIGWINCH, &act, NULL);
489 } else 458 } else
490 signal(SIGWINCH, SIG_DFL); 459 signal(SIGWINCH, SIG_DFL);
491 break; 460 break;
492 case 'E': 461 case 'E':
493 if (top.evlist->nr_entries > 1) { 462 if (top->evlist->nr_entries > 1) {
494 /* Select 0 as the default event: */ 463 /* Select 0 as the default event: */
495 int counter = 0; 464 int counter = 0;
496 465
497 fprintf(stderr, "\nAvailable events:"); 466 fprintf(stderr, "\nAvailable events:");
498 467
499 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 468 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
500 fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel)); 469 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel));
501 470
502 prompt_integer(&counter, "Enter details event counter"); 471 prompt_integer(&counter, "Enter details event counter");
503 472
504 if (counter >= top.evlist->nr_entries) { 473 if (counter >= top->evlist->nr_entries) {
505 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 474 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
506 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel)); 475 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel));
507 sleep(1); 476 sleep(1);
508 break; 477 break;
509 } 478 }
510 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 479 list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
511 if (top.sym_evsel->idx == counter) 480 if (top->sym_evsel->idx == counter)
512 break; 481 break;
513 } else 482 } else
514 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 483 top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
515 break; 484 break;
516 case 'f': 485 case 'f':
517 prompt_integer(&top.count_filter, "Enter display event count filter"); 486 prompt_integer(&top->count_filter, "Enter display event count filter");
518 break; 487 break;
519 case 'F': 488 case 'F':
520 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)"); 489 prompt_percent(&top->sym_pcnt_filter,
490 "Enter details display event filter (percent)");
521 break; 491 break;
522 case 'K': 492 case 'K':
523 top.hide_kernel_symbols = !top.hide_kernel_symbols; 493 top->hide_kernel_symbols = !top->hide_kernel_symbols;
524 break; 494 break;
525 case 'q': 495 case 'q':
526 case 'Q': 496 case 'Q':
527 printf("exiting.\n"); 497 printf("exiting.\n");
528 if (dump_symtab) 498 if (top->dump_symtab)
529 perf_session__fprintf_dsos(top.session, stderr); 499 perf_session__fprintf_dsos(top->session, stderr);
530 exit(0); 500 exit(0);
531 case 's': 501 case 's':
532 prompt_symbol(&top.sym_filter_entry, "Enter details symbol"); 502 perf_top__prompt_symbol(top, "Enter details symbol");
533 break; 503 break;
534 case 'S': 504 case 'S':
535 if (!top.sym_filter_entry) 505 if (!top->sym_filter_entry)
536 break; 506 break;
537 else { 507 else {
538 struct hist_entry *syme = top.sym_filter_entry; 508 struct hist_entry *syme = top->sym_filter_entry;
539 509
540 top.sym_filter_entry = NULL; 510 top->sym_filter_entry = NULL;
541 __zero_source_counters(syme); 511 __zero_source_counters(syme);
542 } 512 }
543 break; 513 break;
544 case 'U': 514 case 'U':
545 top.hide_user_symbols = !top.hide_user_symbols; 515 top->hide_user_symbols = !top->hide_user_symbols;
546 break; 516 break;
547 case 'z': 517 case 'z':
548 top.zero = !top.zero; 518 top->zero = !top->zero;
549 break; 519 break;
550 default: 520 default:
551 break; 521 break;
@@ -563,28 +533,30 @@ static void perf_top__sort_new_samples(void *arg)
563 hists__collapse_resort_threaded(&t->sym_evsel->hists); 533 hists__collapse_resort_threaded(&t->sym_evsel->hists);
564 hists__output_resort_threaded(&t->sym_evsel->hists); 534 hists__output_resort_threaded(&t->sym_evsel->hists);
565 hists__decay_entries_threaded(&t->sym_evsel->hists, 535 hists__decay_entries_threaded(&t->sym_evsel->hists,
566 top.hide_user_symbols, 536 t->hide_user_symbols,
567 top.hide_kernel_symbols); 537 t->hide_kernel_symbols);
568} 538}
569 539
570static void *display_thread_tui(void *arg __used) 540static void *display_thread_tui(void *arg)
571{ 541{
542 struct perf_top *top = arg;
572 const char *help = "For a higher level overview, try: perf top --sort comm,dso"; 543 const char *help = "For a higher level overview, try: perf top --sort comm,dso";
573 544
574 perf_top__sort_new_samples(&top); 545 perf_top__sort_new_samples(top);
575 perf_evlist__tui_browse_hists(top.evlist, help, 546 perf_evlist__tui_browse_hists(top->evlist, help,
576 perf_top__sort_new_samples, 547 perf_top__sort_new_samples,
577 &top, top.delay_secs); 548 top, top->delay_secs);
578 549
579 exit_browser(0); 550 exit_browser(0);
580 exit(0); 551 exit(0);
581 return NULL; 552 return NULL;
582} 553}
583 554
584static void *display_thread(void *arg __used) 555static void *display_thread(void *arg)
585{ 556{
586 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 557 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
587 struct termios tc, save; 558 struct termios tc, save;
559 struct perf_top *top = arg;
588 int delay_msecs, c; 560 int delay_msecs, c;
589 561
590 tcgetattr(0, &save); 562 tcgetattr(0, &save);
@@ -595,13 +567,13 @@ static void *display_thread(void *arg __used)
595 567
596 pthread__unblock_sigwinch(); 568 pthread__unblock_sigwinch();
597repeat: 569repeat:
598 delay_msecs = top.delay_secs * 1000; 570 delay_msecs = top->delay_secs * 1000;
599 tcsetattr(0, TCSANOW, &tc); 571 tcsetattr(0, TCSANOW, &tc);
600 /* trash return*/ 572 /* trash return*/
601 getc(stdin); 573 getc(stdin);
602 574
603 while (1) { 575 while (1) {
604 print_sym_table(); 576 perf_top__print_sym_table(top);
605 /* 577 /*
606 * Either timeout expired or we got an EINTR due to SIGWINCH, 578 * Either timeout expired or we got an EINTR due to SIGWINCH,
607 * refresh screen in both cases. 579 * refresh screen in both cases.
@@ -621,7 +593,7 @@ process_hotkey:
621 c = getc(stdin); 593 c = getc(stdin);
622 tcsetattr(0, TCSAFLUSH, &save); 594 tcsetattr(0, TCSAFLUSH, &save);
623 595
624 handle_keypress(c); 596 perf_top__handle_keypress(top, c);
625 goto repeat; 597 goto repeat;
626 598
627 return NULL; 599 return NULL;
@@ -673,47 +645,17 @@ static int symbol_filter(struct map *map __used, struct symbol *sym)
673 return 0; 645 return 0;
674} 646}
675 647
676static void perf_event__process_sample(const union perf_event *event, 648static void perf_event__process_sample(struct perf_tool *tool,
649 const union perf_event *event,
677 struct perf_evsel *evsel, 650 struct perf_evsel *evsel,
678 struct perf_sample *sample, 651 struct perf_sample *sample,
679 struct perf_session *session) 652 struct machine *machine)
680{ 653{
654 struct perf_top *top = container_of(tool, struct perf_top, tool);
681 struct symbol *parent = NULL; 655 struct symbol *parent = NULL;
682 u64 ip = event->ip.ip; 656 u64 ip = event->ip.ip;
683 struct addr_location al; 657 struct addr_location al;
684 struct machine *machine;
685 int err; 658 int err;
686 u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
687
688 ++top.samples;
689
690 switch (origin) {
691 case PERF_RECORD_MISC_USER:
692 ++top.us_samples;
693 if (top.hide_user_symbols)
694 return;
695 machine = perf_session__find_host_machine(session);
696 break;
697 case PERF_RECORD_MISC_KERNEL:
698 ++top.kernel_samples;
699 if (top.hide_kernel_symbols)
700 return;
701 machine = perf_session__find_host_machine(session);
702 break;
703 case PERF_RECORD_MISC_GUEST_KERNEL:
704 ++top.guest_kernel_samples;
705 machine = perf_session__find_machine(session, event->ip.pid);
706 break;
707 case PERF_RECORD_MISC_GUEST_USER:
708 ++top.guest_us_samples;
709 /*
710 * TODO: we don't process guest user from host side
711 * except simple counting.
712 */
713 return;
714 default:
715 return;
716 }
717 659
718 if (!machine && perf_guest) { 660 if (!machine && perf_guest) {
719 pr_err("Can't find guest [%d]'s kernel information\n", 661 pr_err("Can't find guest [%d]'s kernel information\n",
@@ -722,14 +664,14 @@ static void perf_event__process_sample(const union perf_event *event,
722 } 664 }
723 665
724 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) 666 if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
725 top.exact_samples++; 667 top->exact_samples++;
726 668
727 if (perf_event__preprocess_sample(event, session, &al, sample, 669 if (perf_event__preprocess_sample(event, machine, &al, sample,
728 symbol_filter) < 0 || 670 symbol_filter) < 0 ||
729 al.filtered) 671 al.filtered)
730 return; 672 return;
731 673
732 if (!kptr_restrict_warned && 674 if (!top->kptr_restrict_warned &&
733 symbol_conf.kptr_restrict && 675 symbol_conf.kptr_restrict &&
734 al.cpumode == PERF_RECORD_MISC_KERNEL) { 676 al.cpumode == PERF_RECORD_MISC_KERNEL) {
735 ui__warning( 677 ui__warning(
@@ -740,7 +682,7 @@ static void perf_event__process_sample(const union perf_event *event,
740 " modules" : ""); 682 " modules" : "");
741 if (use_browser <= 0) 683 if (use_browser <= 0)
742 sleep(5); 684 sleep(5);
743 kptr_restrict_warned = true; 685 top->kptr_restrict_warned = true;
744 } 686 }
745 687
746 if (al.sym == NULL) { 688 if (al.sym == NULL) {
@@ -756,7 +698,7 @@ static void perf_event__process_sample(const union perf_event *event,
756 * --hide-kernel-symbols, even if the user specifies an 698 * --hide-kernel-symbols, even if the user specifies an
757 * invalid --vmlinux ;-) 699 * invalid --vmlinux ;-)
758 */ 700 */
759 if (!kptr_restrict_warned && !vmlinux_warned && 701 if (!top->kptr_restrict_warned && !top->vmlinux_warned &&
760 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 702 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
761 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 703 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
762 if (symbol_conf.vmlinux_name) { 704 if (symbol_conf.vmlinux_name) {
@@ -769,7 +711,7 @@ static void perf_event__process_sample(const union perf_event *event,
769 711
770 if (use_browser <= 0) 712 if (use_browser <= 0)
771 sleep(5); 713 sleep(5);
772 vmlinux_warned = true; 714 top->vmlinux_warned = true;
773 } 715 }
774 } 716 }
775 717
@@ -778,70 +720,109 @@ static void perf_event__process_sample(const union perf_event *event,
778 720
779 if ((sort__has_parent || symbol_conf.use_callchain) && 721 if ((sort__has_parent || symbol_conf.use_callchain) &&
780 sample->callchain) { 722 sample->callchain) {
781 err = perf_session__resolve_callchain(session, al.thread, 723 err = machine__resolve_callchain(machine, evsel, al.thread,
782 sample->callchain, &parent); 724 sample->callchain, &parent);
783 if (err) 725 if (err)
784 return; 726 return;
785 } 727 }
786 728
787 he = perf_session__add_hist_entry(session, &al, sample, evsel); 729 he = perf_evsel__add_hist_entry(evsel, &al, sample);
788 if (he == NULL) { 730 if (he == NULL) {
789 pr_err("Problem incrementing symbol period, skipping event\n"); 731 pr_err("Problem incrementing symbol period, skipping event\n");
790 return; 732 return;
791 } 733 }
792 734
793 if (symbol_conf.use_callchain) { 735 if (symbol_conf.use_callchain) {
794 err = callchain_append(he->callchain, &session->callchain_cursor, 736 err = callchain_append(he->callchain, &evsel->hists.callchain_cursor,
795 sample->period); 737 sample->period);
796 if (err) 738 if (err)
797 return; 739 return;
798 } 740 }
799 741
800 if (sort_has_symbols) 742 if (top->sort_has_symbols)
801 record_precise_ip(he, evsel->idx, ip); 743 perf_top__record_precise_ip(top, he, evsel->idx, ip);
802 } 744 }
803 745
804 return; 746 return;
805} 747}
806 748
807static void perf_session__mmap_read_idx(struct perf_session *self, int idx) 749static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
808{ 750{
809 struct perf_sample sample; 751 struct perf_sample sample;
810 struct perf_evsel *evsel; 752 struct perf_evsel *evsel;
753 struct perf_session *session = top->session;
811 union perf_event *event; 754 union perf_event *event;
755 struct machine *machine;
756 u8 origin;
812 int ret; 757 int ret;
813 758
814 while ((event = perf_evlist__mmap_read(top.evlist, idx)) != NULL) { 759 while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
815 ret = perf_session__parse_sample(self, event, &sample); 760 ret = perf_session__parse_sample(session, event, &sample);
816 if (ret) { 761 if (ret) {
817 pr_err("Can't parse sample, err = %d\n", ret); 762 pr_err("Can't parse sample, err = %d\n", ret);
818 continue; 763 continue;
819 } 764 }
820 765
821 evsel = perf_evlist__id2evsel(self->evlist, sample.id); 766 evsel = perf_evlist__id2evsel(session->evlist, sample.id);
822 assert(evsel != NULL); 767 assert(evsel != NULL);
823 768
769 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
770
824 if (event->header.type == PERF_RECORD_SAMPLE) 771 if (event->header.type == PERF_RECORD_SAMPLE)
825 perf_event__process_sample(event, evsel, &sample, self); 772 ++top->samples;
826 else if (event->header.type < PERF_RECORD_MAX) { 773
774 switch (origin) {
775 case PERF_RECORD_MISC_USER:
776 ++top->us_samples;
777 if (top->hide_user_symbols)
778 continue;
779 machine = perf_session__find_host_machine(session);
780 break;
781 case PERF_RECORD_MISC_KERNEL:
782 ++top->kernel_samples;
783 if (top->hide_kernel_symbols)
784 continue;
785 machine = perf_session__find_host_machine(session);
786 break;
787 case PERF_RECORD_MISC_GUEST_KERNEL:
788 ++top->guest_kernel_samples;
789 machine = perf_session__find_machine(session, event->ip.pid);
790 break;
791 case PERF_RECORD_MISC_GUEST_USER:
792 ++top->guest_us_samples;
793 /*
794 * TODO: we don't process guest user from host side
795 * except simple counting.
796 */
797 /* Fall thru */
798 default:
799 continue;
800 }
801
802
803 if (event->header.type == PERF_RECORD_SAMPLE) {
804 perf_event__process_sample(&top->tool, event, evsel,
805 &sample, machine);
806 } else if (event->header.type < PERF_RECORD_MAX) {
827 hists__inc_nr_events(&evsel->hists, event->header.type); 807 hists__inc_nr_events(&evsel->hists, event->header.type);
828 perf_event__process(event, &sample, self); 808 perf_event__process(&top->tool, event, &sample, machine);
829 } else 809 } else
830 ++self->hists.stats.nr_unknown_events; 810 ++session->hists.stats.nr_unknown_events;
831 } 811 }
832} 812}
833 813
834static void perf_session__mmap_read(struct perf_session *self) 814static void perf_top__mmap_read(struct perf_top *top)
835{ 815{
836 int i; 816 int i;
837 817
838 for (i = 0; i < top.evlist->nr_mmaps; i++) 818 for (i = 0; i < top->evlist->nr_mmaps; i++)
839 perf_session__mmap_read_idx(self, i); 819 perf_top__mmap_read_idx(top, i);
840} 820}
841 821
842static void start_counters(struct perf_evlist *evlist) 822static void perf_top__start_counters(struct perf_top *top)
843{ 823{
844 struct perf_evsel *counter, *first; 824 struct perf_evsel *counter, *first;
825 struct perf_evlist *evlist = top->evlist;
845 826
846 first = list_entry(evlist->entries.next, struct perf_evsel, node); 827 first = list_entry(evlist->entries.next, struct perf_evsel, node);
847 828
@@ -849,15 +830,15 @@ static void start_counters(struct perf_evlist *evlist)
849 struct perf_event_attr *attr = &counter->attr; 830 struct perf_event_attr *attr = &counter->attr;
850 struct xyarray *group_fd = NULL; 831 struct xyarray *group_fd = NULL;
851 832
852 if (group && counter != first) 833 if (top->group && counter != first)
853 group_fd = first->fd; 834 group_fd = first->fd;
854 835
855 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 836 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
856 837
857 if (top.freq) { 838 if (top->freq) {
858 attr->sample_type |= PERF_SAMPLE_PERIOD; 839 attr->sample_type |= PERF_SAMPLE_PERIOD;
859 attr->freq = 1; 840 attr->freq = 1;
860 attr->sample_freq = top.freq; 841 attr->sample_freq = top->freq;
861 } 842 }
862 843
863 if (evlist->nr_entries > 1) { 844 if (evlist->nr_entries > 1) {
@@ -870,23 +851,23 @@ static void start_counters(struct perf_evlist *evlist)
870 851
871 attr->mmap = 1; 852 attr->mmap = 1;
872 attr->comm = 1; 853 attr->comm = 1;
873 attr->inherit = inherit; 854 attr->inherit = top->inherit;
874retry_sample_id: 855retry_sample_id:
875 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 856 attr->sample_id_all = top->sample_id_all_avail ? 1 : 0;
876try_again: 857try_again:
877 if (perf_evsel__open(counter, top.evlist->cpus, 858 if (perf_evsel__open(counter, top->evlist->cpus,
878 top.evlist->threads, group, 859 top->evlist->threads, top->group,
879 group_fd) < 0) { 860 group_fd) < 0) {
880 int err = errno; 861 int err = errno;
881 862
882 if (err == EPERM || err == EACCES) { 863 if (err == EPERM || err == EACCES) {
883 ui__error_paranoid(); 864 ui__error_paranoid();
884 goto out_err; 865 goto out_err;
885 } else if (err == EINVAL && sample_id_all_avail) { 866 } else if (err == EINVAL && top->sample_id_all_avail) {
886 /* 867 /*
887 * Old kernel, no attr->sample_id_type_all field 868 * Old kernel, no attr->sample_id_type_all field
888 */ 869 */
889 sample_id_all_avail = false; 870 top->sample_id_all_avail = false;
890 goto retry_sample_id; 871 goto retry_sample_id;
891 } 872 }
892 /* 873 /*
@@ -920,7 +901,7 @@ try_again:
920 } 901 }
921 } 902 }
922 903
923 if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) { 904 if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
924 ui__warning("Failed to mmap with %d (%s)\n", 905 ui__warning("Failed to mmap with %d (%s)\n",
925 errno, strerror(errno)); 906 errno, strerror(errno));
926 goto out_err; 907 goto out_err;
@@ -933,14 +914,14 @@ out_err:
933 exit(0); 914 exit(0);
934} 915}
935 916
936static int setup_sample_type(void) 917static int perf_top__setup_sample_type(struct perf_top *top)
937{ 918{
938 if (!sort_has_symbols) { 919 if (!top->sort_has_symbols) {
939 if (symbol_conf.use_callchain) { 920 if (symbol_conf.use_callchain) {
940 ui__warning("Selected -g but \"sym\" not present in --sort/-s."); 921 ui__warning("Selected -g but \"sym\" not present in --sort/-s.");
941 return -EINVAL; 922 return -EINVAL;
942 } 923 }
943 } else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE) { 924 } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
944 if (callchain_register_param(&callchain_param) < 0) { 925 if (callchain_register_param(&callchain_param) < 0) {
945 ui__warning("Can't register callchain params.\n"); 926 ui__warning("Can't register callchain params.\n");
946 return -EINVAL; 927 return -EINVAL;
@@ -950,7 +931,7 @@ static int setup_sample_type(void)
950 return 0; 931 return 0;
951} 932}
952 933
953static int __cmd_top(void) 934static int __cmd_top(struct perf_top *top)
954{ 935{
955 pthread_t thread; 936 pthread_t thread;
956 int ret; 937 int ret;
@@ -958,39 +939,40 @@ static int __cmd_top(void)
958 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 939 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
959 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 940 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
960 */ 941 */
961 top.session = perf_session__new(NULL, O_WRONLY, false, false, NULL); 942 top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
962 if (top.session == NULL) 943 if (top->session == NULL)
963 return -ENOMEM; 944 return -ENOMEM;
964 945
965 ret = setup_sample_type(); 946 ret = perf_top__setup_sample_type(top);
966 if (ret) 947 if (ret)
967 goto out_delete; 948 goto out_delete;
968 949
969 if (top.target_tid != -1) 950 if (top->target_tid != -1)
970 perf_event__synthesize_thread_map(top.evlist->threads, 951 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
971 perf_event__process, top.session); 952 perf_event__process,
953 &top->session->host_machine);
972 else 954 else
973 perf_event__synthesize_threads(perf_event__process, top.session); 955 perf_event__synthesize_threads(&top->tool, perf_event__process,
974 956 &top->session->host_machine);
975 start_counters(top.evlist); 957 perf_top__start_counters(top);
976 top.session->evlist = top.evlist; 958 top->session->evlist = top->evlist;
977 perf_session__update_sample_type(top.session); 959 perf_session__update_sample_type(top->session);
978 960
979 /* Wait for a minimal set of events before starting the snapshot */ 961 /* Wait for a minimal set of events before starting the snapshot */
980 poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 962 poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
981 963
982 perf_session__mmap_read(top.session); 964 perf_top__mmap_read(top);
983 965
984 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 966 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
985 display_thread), NULL)) { 967 display_thread), top)) {
986 printf("Could not create display thread.\n"); 968 printf("Could not create display thread.\n");
987 exit(-1); 969 exit(-1);
988 } 970 }
989 971
990 if (realtime_prio) { 972 if (top->realtime_prio) {
991 struct sched_param param; 973 struct sched_param param;
992 974
993 param.sched_priority = realtime_prio; 975 param.sched_priority = top->realtime_prio;
994 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 976 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
995 printf("Could not set realtime priority.\n"); 977 printf("Could not set realtime priority.\n");
996 exit(-1); 978 exit(-1);
@@ -998,25 +980,25 @@ static int __cmd_top(void)
998 } 980 }
999 981
1000 while (1) { 982 while (1) {
1001 u64 hits = top.samples; 983 u64 hits = top->samples;
1002 984
1003 perf_session__mmap_read(top.session); 985 perf_top__mmap_read(top);
1004 986
1005 if (hits == top.samples) 987 if (hits == top->samples)
1006 ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100); 988 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
1007 } 989 }
1008 990
1009out_delete: 991out_delete:
1010 perf_session__delete(top.session); 992 perf_session__delete(top->session);
1011 top.session = NULL; 993 top->session = NULL;
1012 994
1013 return 0; 995 return 0;
1014} 996}
1015 997
1016static int 998static int
1017parse_callchain_opt(const struct option *opt __used, const char *arg, 999parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1018 int unset)
1019{ 1000{
1001 struct perf_top *top = (struct perf_top *)opt->value;
1020 char *tok, *tok2; 1002 char *tok, *tok2;
1021 char *endptr; 1003 char *endptr;
1022 1004
@@ -1024,7 +1006,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
1024 * --no-call-graph 1006 * --no-call-graph
1025 */ 1007 */
1026 if (unset) { 1008 if (unset) {
1027 dont_use_callchains = true; 1009 top->dont_use_callchains = true;
1028 return 0; 1010 return 0;
1029 } 1011 }
1030 1012
@@ -1052,9 +1034,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
1052 symbol_conf.use_callchain = false; 1034 symbol_conf.use_callchain = false;
1053 1035
1054 return 0; 1036 return 0;
1055 } 1037 } else
1056
1057 else
1058 return -1; 1038 return -1;
1059 1039
1060 /* get the min percentage */ 1040 /* get the min percentage */
@@ -1098,17 +1078,32 @@ static const char * const top_usage[] = {
1098 NULL 1078 NULL
1099}; 1079};
1100 1080
1101static const struct option options[] = { 1081int cmd_top(int argc, const char **argv, const char *prefix __used)
1082{
1083 struct perf_evsel *pos;
1084 int status = -ENOMEM;
1085 struct perf_top top = {
1086 .count_filter = 5,
1087 .delay_secs = 2,
1088 .target_pid = -1,
1089 .target_tid = -1,
1090 .freq = 1000, /* 1 KHz */
1091 .sample_id_all_avail = true,
1092 .mmap_pages = 128,
1093 .sym_pcnt_filter = 5,
1094 };
1095 char callchain_default_opt[] = "fractal,0.5,callee";
1096 const struct option options[] = {
1102 OPT_CALLBACK('e', "event", &top.evlist, "event", 1097 OPT_CALLBACK('e', "event", &top.evlist, "event",
1103 "event selector. use 'perf list' to list available events", 1098 "event selector. use 'perf list' to list available events",
1104 parse_events_option), 1099 parse_events_option),
1105 OPT_INTEGER('c', "count", &default_interval, 1100 OPT_INTEGER('c', "count", &top.default_interval,
1106 "event period to sample"), 1101 "event period to sample"),
1107 OPT_INTEGER('p', "pid", &top.target_pid, 1102 OPT_INTEGER('p', "pid", &top.target_pid,
1108 "profile events on existing process id"), 1103 "profile events on existing process id"),
1109 OPT_INTEGER('t', "tid", &top.target_tid, 1104 OPT_INTEGER('t', "tid", &top.target_tid,
1110 "profile events on existing thread id"), 1105 "profile events on existing thread id"),
1111 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1106 OPT_BOOLEAN('a', "all-cpus", &top.system_wide,
1112 "system-wide collection from all CPUs"), 1107 "system-wide collection from all CPUs"),
1113 OPT_STRING('C', "cpu", &top.cpu_list, "cpu", 1108 OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
1114 "list of cpus to monitor"), 1109 "list of cpus to monitor"),
@@ -1116,20 +1111,20 @@ static const struct option options[] = {
1116 "file", "vmlinux pathname"), 1111 "file", "vmlinux pathname"),
1117 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1112 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1118 "hide kernel symbols"), 1113 "hide kernel symbols"),
1119 OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"), 1114 OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"),
1120 OPT_INTEGER('r', "realtime", &realtime_prio, 1115 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1121 "collect data with this RT SCHED_FIFO priority"), 1116 "collect data with this RT SCHED_FIFO priority"),
1122 OPT_INTEGER('d', "delay", &top.delay_secs, 1117 OPT_INTEGER('d', "delay", &top.delay_secs,
1123 "number of seconds to delay between refreshes"), 1118 "number of seconds to delay between refreshes"),
1124 OPT_BOOLEAN('D', "dump-symtab", &dump_symtab, 1119 OPT_BOOLEAN('D', "dump-symtab", &top.dump_symtab,
1125 "dump the symbol table used for profiling"), 1120 "dump the symbol table used for profiling"),
1126 OPT_INTEGER('f', "count-filter", &top.count_filter, 1121 OPT_INTEGER('f', "count-filter", &top.count_filter,
1127 "only display functions with more events than this"), 1122 "only display functions with more events than this"),
1128 OPT_BOOLEAN('g', "group", &group, 1123 OPT_BOOLEAN('g', "group", &top.group,
1129 "put the counters into a counter group"), 1124 "put the counters into a counter group"),
1130 OPT_BOOLEAN('i', "inherit", &inherit, 1125 OPT_BOOLEAN('i', "inherit", &top.inherit,
1131 "child tasks inherit counters"), 1126 "child tasks inherit counters"),
1132 OPT_STRING(0, "sym-annotate", &sym_filter, "symbol name", 1127 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1133 "symbol to annotate"), 1128 "symbol to annotate"),
1134 OPT_BOOLEAN('z', "zero", &top.zero, 1129 OPT_BOOLEAN('z', "zero", &top.zero,
1135 "zero history across updates"), 1130 "zero history across updates"),
@@ -1139,15 +1134,15 @@ static const struct option options[] = {
1139 "display this many functions"), 1134 "display this many functions"),
1140 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1135 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
1141 "hide user symbols"), 1136 "hide user symbols"),
1142 OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"), 1137 OPT_BOOLEAN(0, "tui", &top.use_tui, "Use the TUI interface"),
1143 OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"), 1138 OPT_BOOLEAN(0, "stdio", &top.use_stdio, "Use the stdio interface"),
1144 OPT_INCR('v', "verbose", &verbose, 1139 OPT_INCR('v', "verbose", &verbose,
1145 "be more verbose (show counter open errors, etc)"), 1140 "be more verbose (show counter open errors, etc)"),
1146 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1141 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1147 "sort by key(s): pid, comm, dso, symbol, parent"), 1142 "sort by key(s): pid, comm, dso, symbol, parent"),
1148 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1143 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1149 "Show a column with the number of samples"), 1144 "Show a column with the number of samples"),
1150 OPT_CALLBACK_DEFAULT('G', "call-graph", NULL, "output_type,min_percent, call_order", 1145 OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order",
1151 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. " 1146 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. "
1152 "Default: fractal,0.5,callee", &parse_callchain_opt, 1147 "Default: fractal,0.5,callee", &parse_callchain_opt,
1153 callchain_default_opt), 1148 callchain_default_opt),
@@ -1166,12 +1161,7 @@ static const struct option options[] = {
1166 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1161 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1167 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1162 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1168 OPT_END() 1163 OPT_END()
1169}; 1164 };
1170
1171int cmd_top(int argc, const char **argv, const char *prefix __used)
1172{
1173 struct perf_evsel *pos;
1174 int status = -ENOMEM;
1175 1165
1176 top.evlist = perf_evlist__new(NULL, NULL); 1166 top.evlist = perf_evlist__new(NULL, NULL);
1177 if (top.evlist == NULL) 1167 if (top.evlist == NULL)
@@ -1188,9 +1178,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1188 1178
1189 setup_sorting(top_usage, options); 1179 setup_sorting(top_usage, options);
1190 1180
1191 if (use_stdio) 1181 if (top.use_stdio)
1192 use_browser = 0; 1182 use_browser = 0;
1193 else if (use_tui) 1183 else if (top.use_tui)
1194 use_browser = 1; 1184 use_browser = 1;
1195 1185
1196 setup_browser(false); 1186 setup_browser(false);
@@ -1215,38 +1205,31 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1215 return -ENOMEM; 1205 return -ENOMEM;
1216 } 1206 }
1217 1207
1208 symbol_conf.nr_events = top.evlist->nr_entries;
1209
1218 if (top.delay_secs < 1) 1210 if (top.delay_secs < 1)
1219 top.delay_secs = 1; 1211 top.delay_secs = 1;
1220 1212
1221 /* 1213 /*
1222 * User specified count overrides default frequency. 1214 * User specified count overrides default frequency.
1223 */ 1215 */
1224 if (default_interval) 1216 if (top.default_interval)
1225 top.freq = 0; 1217 top.freq = 0;
1226 else if (top.freq) { 1218 else if (top.freq) {
1227 default_interval = top.freq; 1219 top.default_interval = top.freq;
1228 } else { 1220 } else {
1229 fprintf(stderr, "frequency and count are zero, aborting\n"); 1221 fprintf(stderr, "frequency and count are zero, aborting\n");
1230 exit(EXIT_FAILURE); 1222 exit(EXIT_FAILURE);
1231 } 1223 }
1232 1224
1233 list_for_each_entry(pos, &top.evlist->entries, node) { 1225 list_for_each_entry(pos, &top.evlist->entries, node) {
1234 if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr,
1235 top.evlist->threads->nr) < 0)
1236 goto out_free_fd;
1237 /* 1226 /*
1238 * Fill in the ones not specifically initialized via -c: 1227 * Fill in the ones not specifically initialized via -c:
1239 */ 1228 */
1240 if (pos->attr.sample_period) 1229 if (!pos->attr.sample_period)
1241 continue; 1230 pos->attr.sample_period = top.default_interval;
1242
1243 pos->attr.sample_period = default_interval;
1244 } 1231 }
1245 1232
1246 if (perf_evlist__alloc_pollfd(top.evlist) < 0 ||
1247 perf_evlist__alloc_mmap(top.evlist) < 0)
1248 goto out_free_fd;
1249
1250 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 1233 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
1251 1234
1252 symbol_conf.priv_size = sizeof(struct annotation); 1235 symbol_conf.priv_size = sizeof(struct annotation);
@@ -1263,16 +1246,20 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1263 * Avoid annotation data structures overhead when symbols aren't on the 1246 * Avoid annotation data structures overhead when symbols aren't on the
1264 * sort list. 1247 * sort list.
1265 */ 1248 */
1266 sort_has_symbols = sort_sym.list.next != NULL; 1249 top.sort_has_symbols = sort_sym.list.next != NULL;
1267 1250
1268 get_term_dimensions(&winsize); 1251 get_term_dimensions(&top.winsize);
1269 if (top.print_entries == 0) { 1252 if (top.print_entries == 0) {
1270 update_print_entries(&winsize); 1253 struct sigaction act = {
1271 signal(SIGWINCH, sig_winch_handler); 1254 .sa_sigaction = perf_top__sig_winch,
1255 .sa_flags = SA_SIGINFO,
1256 };
1257 perf_top__update_print_entries(&top);
1258 sigaction(SIGWINCH, &act, NULL);
1272 } 1259 }
1273 1260
1274 status = __cmd_top(); 1261 status = __cmd_top(&top);
1275out_free_fd: 1262
1276 perf_evlist__delete(top.evlist); 1263 perf_evlist__delete(top.evlist);
1277 1264
1278 return status; 1265 return status;
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 73d0cac8b67e..2b2e225a4d4c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -29,8 +29,6 @@ struct pager_config {
29 int val; 29 int val;
30}; 30};
31 31
32static char debugfs_mntpt[MAXPATHLEN];
33
34static int pager_command_config(const char *var, const char *value, void *data) 32static int pager_command_config(const char *var, const char *value, void *data)
35{ 33{
36 struct pager_config *c = data; 34 struct pager_config *c = data;
@@ -81,15 +79,6 @@ static void commit_pager_choice(void)
81 } 79 }
82} 80}
83 81
84static void set_debugfs_path(void)
85{
86 char *path;
87
88 path = getenv(PERF_DEBUGFS_ENVIRONMENT);
89 snprintf(debugfs_path, MAXPATHLEN, "%s/%s", path ?: debugfs_mntpt,
90 "tracing/events");
91}
92
93static int handle_options(const char ***argv, int *argc, int *envchanged) 82static int handle_options(const char ***argv, int *argc, int *envchanged)
94{ 83{
95 int handled = 0; 84 int handled = 0;
@@ -161,15 +150,14 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
161 fprintf(stderr, "No directory given for --debugfs-dir.\n"); 150 fprintf(stderr, "No directory given for --debugfs-dir.\n");
162 usage(perf_usage_string); 151 usage(perf_usage_string);
163 } 152 }
164 strncpy(debugfs_mntpt, (*argv)[1], MAXPATHLEN); 153 debugfs_set_path((*argv)[1]);
165 debugfs_mntpt[MAXPATHLEN - 1] = '\0';
166 if (envchanged) 154 if (envchanged)
167 *envchanged = 1; 155 *envchanged = 1;
168 (*argv)++; 156 (*argv)++;
169 (*argc)--; 157 (*argc)--;
170 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) { 158 } else if (!prefixcmp(cmd, CMD_DEBUGFS_DIR)) {
171 strncpy(debugfs_mntpt, cmd + strlen(CMD_DEBUGFS_DIR), MAXPATHLEN); 159 debugfs_set_path(cmd + strlen(CMD_DEBUGFS_DIR));
172 debugfs_mntpt[MAXPATHLEN - 1] = '\0'; 160 fprintf(stderr, "dir: %s\n", debugfs_mountpoint);
173 if (envchanged) 161 if (envchanged)
174 *envchanged = 1; 162 *envchanged = 1;
175 } else { 163 } else {
@@ -281,7 +269,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
281 if (use_pager == -1 && p->option & USE_PAGER) 269 if (use_pager == -1 && p->option & USE_PAGER)
282 use_pager = 1; 270 use_pager = 1;
283 commit_pager_choice(); 271 commit_pager_choice();
284 set_debugfs_path();
285 272
286 status = p->fn(argc, argv, prefix); 273 status = p->fn(argc, argv, prefix);
287 exit_browser(status); 274 exit_browser(status);
@@ -416,17 +403,6 @@ static int run_argv(int *argcp, const char ***argv)
416 return done_alias; 403 return done_alias;
417} 404}
418 405
419/* mini /proc/mounts parser: searching for "^blah /mount/point debugfs" */
420static void get_debugfs_mntpt(void)
421{
422 const char *path = debugfs_mount(NULL);
423
424 if (path)
425 strncpy(debugfs_mntpt, path, sizeof(debugfs_mntpt));
426 else
427 debugfs_mntpt[0] = '\0';
428}
429
430static void pthread__block_sigwinch(void) 406static void pthread__block_sigwinch(void)
431{ 407{
432 sigset_t set; 408 sigset_t set;
@@ -453,7 +429,7 @@ int main(int argc, const char **argv)
453 if (!cmd) 429 if (!cmd)
454 cmd = "perf-help"; 430 cmd = "perf-help";
455 /* get debugfs mount point from /proc/mounts */ 431 /* get debugfs mount point from /proc/mounts */
456 get_debugfs_mntpt(); 432 debugfs_mount(NULL);
457 /* 433 /*
458 * "perf-xxxx" is the same as "perf xxxx", but we obviously: 434 * "perf-xxxx" is the same as "perf xxxx", but we obviously:
459 * 435 *
@@ -476,7 +452,6 @@ int main(int argc, const char **argv)
476 argc--; 452 argc--;
477 handle_options(&argv, &argc, NULL); 453 handle_options(&argv, &argc, NULL);
478 commit_pager_choice(); 454 commit_pager_choice();
479 set_debugfs_path();
480 set_buildid_dir(); 455 set_buildid_dir();
481 456
482 if (argc > 0) { 457 if (argc > 0) {
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 914c895510f7..ea804f5a8cc2 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -185,4 +185,27 @@ extern const char perf_version_string[];
185 185
186void pthread__unblock_sigwinch(void); 186void pthread__unblock_sigwinch(void);
187 187
188struct perf_record_opts {
189 pid_t target_pid;
190 pid_t target_tid;
191 bool call_graph;
192 bool group;
193 bool inherit_stat;
194 bool no_delay;
195 bool no_inherit;
196 bool no_samples;
197 bool pipe_output;
198 bool raw_samples;
199 bool sample_address;
200 bool sample_time;
201 bool sample_id_all_avail;
202 bool system_wide;
203 unsigned int freq;
204 unsigned int mmap_pages;
205 unsigned int user_freq;
206 u64 default_interval;
207 u64 user_interval;
208 const char *cpu_list;
209};
210
188#endif 211#endif
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 119e996035c8..376e643f7066 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -25,17 +25,17 @@ int symbol__annotate_init(struct map *map __used, struct symbol *sym)
25 return 0; 25 return 0;
26} 26}
27 27
28int symbol__alloc_hist(struct symbol *sym, int nevents) 28int symbol__alloc_hist(struct symbol *sym)
29{ 29{
30 struct annotation *notes = symbol__annotation(sym); 30 struct annotation *notes = symbol__annotation(sym);
31 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + 31 size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
32 (sym->end - sym->start) * sizeof(u64)); 32 (sym->end - sym->start) * sizeof(u64));
33 33
34 notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist); 34 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
35 if (notes->src == NULL) 35 if (notes->src == NULL)
36 return -1; 36 return -1;
37 notes->src->sizeof_sym_hist = sizeof_sym_hist; 37 notes->src->sizeof_sym_hist = sizeof_sym_hist;
38 notes->src->nr_histograms = nevents; 38 notes->src->nr_histograms = symbol_conf.nr_events;
39 INIT_LIST_HEAD(&notes->src->source); 39 INIT_LIST_HEAD(&notes->src->source);
40 return 0; 40 return 0;
41} 41}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index d9072523d342..efa5dc82bfae 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -72,7 +72,7 @@ static inline struct annotation *symbol__annotation(struct symbol *sym)
72 72
73int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 73int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
74 int evidx, u64 addr); 74 int evidx, u64 addr);
75int symbol__alloc_hist(struct symbol *sym, int nevents); 75int symbol__alloc_hist(struct symbol *sym);
76void symbol__annotate_zero_histograms(struct symbol *sym); 76void symbol__annotate_zero_histograms(struct symbol *sym);
77 77
78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
@@ -99,8 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used,
99} 99}
100#else 100#else
101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 101int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
102 int nr_events, void(*timer)(void *arg), void *arg, 102 void(*timer)(void *arg), void *arg, int delay_secs);
103 int delay_secs);
104#endif 103#endif
105 104
106extern const char *disassembler_style; 105extern const char *disassembler_style;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index a91cd99f26ea..dff9c7a725f4 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -13,15 +13,18 @@
13#include "symbol.h" 13#include "symbol.h"
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include "debug.h" 15#include "debug.h"
16#include "session.h"
17#include "tool.h"
16 18
17static int build_id__mark_dso_hit(union perf_event *event, 19static int build_id__mark_dso_hit(struct perf_tool *tool __used,
20 union perf_event *event,
18 struct perf_sample *sample __used, 21 struct perf_sample *sample __used,
19 struct perf_evsel *evsel __used, 22 struct perf_evsel *evsel __used,
20 struct perf_session *session) 23 struct machine *machine)
21{ 24{
22 struct addr_location al; 25 struct addr_location al;
23 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 26 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
24 struct thread *thread = perf_session__findnew(session, event->ip.pid); 27 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
25 28
26 if (thread == NULL) { 29 if (thread == NULL) {
27 pr_err("problem processing %d event, skipping it.\n", 30 pr_err("problem processing %d event, skipping it.\n",
@@ -29,8 +32,8 @@ static int build_id__mark_dso_hit(union perf_event *event,
29 return -1; 32 return -1;
30 } 33 }
31 34
32 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
33 event->ip.pid, event->ip.ip, &al); 36 event->ip.ip, &al);
34 37
35 if (al.map != NULL) 38 if (al.map != NULL)
36 al.map->dso->hit = 1; 39 al.map->dso->hit = 1;
@@ -38,25 +41,26 @@ static int build_id__mark_dso_hit(union perf_event *event,
38 return 0; 41 return 0;
39} 42}
40 43
41static int perf_event__exit_del_thread(union perf_event *event, 44static int perf_event__exit_del_thread(struct perf_tool *tool __used,
45 union perf_event *event,
42 struct perf_sample *sample __used, 46 struct perf_sample *sample __used,
43 struct perf_session *session) 47 struct machine *machine)
44{ 48{
45 struct thread *thread = perf_session__findnew(session, event->fork.tid); 49 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
46 50
47 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 51 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
48 event->fork.ppid, event->fork.ptid); 52 event->fork.ppid, event->fork.ptid);
49 53
50 if (thread) { 54 if (thread) {
51 rb_erase(&thread->rb_node, &session->threads); 55 rb_erase(&thread->rb_node, &machine->threads);
52 session->last_match = NULL; 56 machine->last_match = NULL;
53 thread__delete(thread); 57 thread__delete(thread);
54 } 58 }
55 59
56 return 0; 60 return 0;
57} 61}
58 62
59struct perf_event_ops build_id__mark_dso_hit_ops = { 63struct perf_tool build_id__mark_dso_hit_ops = {
60 .sample = build_id__mark_dso_hit, 64 .sample = build_id__mark_dso_hit,
61 .mmap = perf_event__process_mmap, 65 .mmap = perf_event__process_mmap,
62 .fork = perf_event__process_task, 66 .fork = perf_event__process_task,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 5dafb00eaa06..a993ba87d996 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -3,7 +3,7 @@
3 3
4#include "session.h" 4#include "session.h"
5 5
6extern struct perf_event_ops build_id__mark_dso_hit_ops; 6extern struct perf_tool build_id__mark_dso_hit_ops;
7 7
8char *dso__build_id_filename(struct dso *self, char *bf, size_t size); 8char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
9 9
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 9b4ff16cac96..7f9c0f1ae3a9 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -101,6 +101,9 @@ int callchain_append(struct callchain_root *root,
101int callchain_merge(struct callchain_cursor *cursor, 101int callchain_merge(struct callchain_cursor *cursor,
102 struct callchain_root *dst, struct callchain_root *src); 102 struct callchain_root *dst, struct callchain_root *src);
103 103
104struct ip_callchain;
105union perf_event;
106
104bool ip_callchain__valid(struct ip_callchain *chain, 107bool ip_callchain__valid(struct ip_callchain *chain,
105 const union perf_event *event); 108 const union perf_event *event);
106/* 109/*
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 96bee5c46008..dbe2f16b1a1a 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -3,7 +3,6 @@
3#include "parse-options.h" 3#include "parse-options.h"
4#include "evsel.h" 4#include "evsel.h"
5#include "cgroup.h" 5#include "cgroup.h"
6#include "debugfs.h" /* MAX_PATH, STR() */
7#include "evlist.h" 6#include "evlist.h"
8 7
9int nr_cgroups; 8int nr_cgroups;
@@ -12,7 +11,7 @@ static int
12cgroupfs_find_mountpoint(char *buf, size_t maxlen) 11cgroupfs_find_mountpoint(char *buf, size_t maxlen)
13{ 12{
14 FILE *fp; 13 FILE *fp;
15 char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1]; 14 char mountpoint[PATH_MAX + 1], tokens[PATH_MAX + 1], type[PATH_MAX + 1];
16 char *token, *saved_ptr = NULL; 15 char *token, *saved_ptr = NULL;
17 int found = 0; 16 int found = 0;
18 17
@@ -25,8 +24,8 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
25 * and inspect every cgroupfs mount point to find one that has 24 * and inspect every cgroupfs mount point to find one that has
26 * perf_event subsystem 25 * perf_event subsystem
27 */ 26 */
28 while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %" 27 while (fscanf(fp, "%*s %"STR(PATH_MAX)"s %"STR(PATH_MAX)"s %"
29 STR(MAX_PATH)"s %*d %*d\n", 28 STR(PATH_MAX)"s %*d %*d\n",
30 mountpoint, type, tokens) == 3) { 29 mountpoint, type, tokens) == 3) {
31 30
32 if (!strcmp(type, "cgroup")) { 31 if (!strcmp(type, "cgroup")) {
@@ -57,15 +56,15 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
57 56
58static int open_cgroup(char *name) 57static int open_cgroup(char *name)
59{ 58{
60 char path[MAX_PATH+1]; 59 char path[PATH_MAX + 1];
61 char mnt[MAX_PATH+1]; 60 char mnt[PATH_MAX + 1];
62 int fd; 61 int fd;
63 62
64 63
65 if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1)) 64 if (cgroupfs_find_mountpoint(mnt, PATH_MAX + 1))
66 return -1; 65 return -1;
67 66
68 snprintf(path, MAX_PATH, "%s/%s", mnt, name); 67 snprintf(path, PATH_MAX, "%s/%s", mnt, name);
69 68
70 fd = open(path, O_RDONLY); 69 fd = open(path, O_RDONLY);
71 if (fd == -1) 70 if (fd == -1)
diff --git a/tools/perf/util/debugfs.c b/tools/perf/util/debugfs.c
index a88fefc0cc0a..ffc35e748e89 100644
--- a/tools/perf/util/debugfs.c
+++ b/tools/perf/util/debugfs.c
@@ -2,8 +2,12 @@
2#include "debugfs.h" 2#include "debugfs.h"
3#include "cache.h" 3#include "cache.h"
4 4
5#include <linux/kernel.h>
6#include <sys/mount.h>
7
5static int debugfs_premounted; 8static int debugfs_premounted;
6static char debugfs_mountpoint[MAX_PATH+1]; 9char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug";
10char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
7 11
8static const char *debugfs_known_mountpoints[] = { 12static const char *debugfs_known_mountpoints[] = {
9 "/sys/kernel/debug/", 13 "/sys/kernel/debug/",
@@ -62,11 +66,9 @@ const char *debugfs_find_mountpoint(void)
62 /* give up and parse /proc/mounts */ 66 /* give up and parse /proc/mounts */
63 fp = fopen("/proc/mounts", "r"); 67 fp = fopen("/proc/mounts", "r");
64 if (fp == NULL) 68 if (fp == NULL)
65 die("Can't open /proc/mounts for read"); 69 return NULL;
66 70
67 while (fscanf(fp, "%*s %" 71 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
68 STR(MAX_PATH)
69 "s %99s %*s %*d %*d\n",
70 debugfs_mountpoint, type) == 2) { 72 debugfs_mountpoint, type) == 2) {
71 if (strcmp(type, "debugfs") == 0) 73 if (strcmp(type, "debugfs") == 0)
72 break; 74 break;
@@ -106,6 +108,12 @@ int debugfs_valid_entry(const char *path)
106 return 0; 108 return 0;
107} 109}
108 110
111static void debugfs_set_tracing_events_path(const char *mountpoint)
112{
113 snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s",
114 mountpoint, "tracing/events");
115}
116
109/* mount the debugfs somewhere if it's not mounted */ 117/* mount the debugfs somewhere if it's not mounted */
110 118
111char *debugfs_mount(const char *mountpoint) 119char *debugfs_mount(const char *mountpoint)
@@ -113,7 +121,7 @@ char *debugfs_mount(const char *mountpoint)
113 /* see if it's already mounted */ 121 /* see if it's already mounted */
114 if (debugfs_find_mountpoint()) { 122 if (debugfs_find_mountpoint()) {
115 debugfs_premounted = 1; 123 debugfs_premounted = 1;
116 return debugfs_mountpoint; 124 goto out;
117 } 125 }
118 126
119 /* if not mounted and no argument */ 127 /* if not mounted and no argument */
@@ -129,12 +137,19 @@ char *debugfs_mount(const char *mountpoint)
129 return NULL; 137 return NULL;
130 138
131 /* save the mountpoint */ 139 /* save the mountpoint */
132 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
133 debugfs_found = 1; 140 debugfs_found = 1;
134 141 strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
142out:
143 debugfs_set_tracing_events_path(debugfs_mountpoint);
135 return debugfs_mountpoint; 144 return debugfs_mountpoint;
136} 145}
137 146
147void debugfs_set_path(const char *mountpoint)
148{
149 snprintf(debugfs_mountpoint, sizeof(debugfs_mountpoint), "%s", mountpoint);
150 debugfs_set_tracing_events_path(mountpoint);
151}
152
138/* umount the debugfs */ 153/* umount the debugfs */
139 154
140int debugfs_umount(void) 155int debugfs_umount(void)
@@ -158,7 +173,7 @@ int debugfs_umount(void)
158 173
159int debugfs_write(const char *entry, const char *value) 174int debugfs_write(const char *entry, const char *value)
160{ 175{
161 char path[MAX_PATH+1]; 176 char path[PATH_MAX + 1];
162 int ret, count; 177 int ret, count;
163 int fd; 178 int fd;
164 179
@@ -203,7 +218,7 @@ int debugfs_write(const char *entry, const char *value)
203 */ 218 */
204int debugfs_read(const char *entry, char *buffer, size_t size) 219int debugfs_read(const char *entry, char *buffer, size_t size)
205{ 220{
206 char path[MAX_PATH+1]; 221 char path[PATH_MAX + 1];
207 int ret; 222 int ret;
208 int fd; 223 int fd;
209 224
diff --git a/tools/perf/util/debugfs.h b/tools/perf/util/debugfs.h
index 83a02879745f..4a878f735eb0 100644
--- a/tools/perf/util/debugfs.h
+++ b/tools/perf/util/debugfs.h
@@ -1,25 +1,18 @@
1#ifndef __DEBUGFS_H__ 1#ifndef __DEBUGFS_H__
2#define __DEBUGFS_H__ 2#define __DEBUGFS_H__
3 3
4#include <sys/mount.h> 4const char *debugfs_find_mountpoint(void);
5int debugfs_valid_mountpoint(const char *debugfs);
6int debugfs_valid_entry(const char *path);
7char *debugfs_mount(const char *mountpoint);
8int debugfs_umount(void);
9void debugfs_set_path(const char *mountpoint);
10int debugfs_write(const char *entry, const char *value);
11int debugfs_read(const char *entry, char *buffer, size_t size);
12void debugfs_force_cleanup(void);
13int debugfs_make_path(const char *element, char *buffer, int size);
5 14
6#ifndef MAX_PATH 15extern char debugfs_mountpoint[];
7# define MAX_PATH 256 16extern char tracing_events_path[];
8#endif
9
10#ifndef STR
11# define _STR(x) #x
12# define STR(x) _STR(x)
13#endif
14
15extern const char *debugfs_find_mountpoint(void);
16extern int debugfs_valid_mountpoint(const char *debugfs);
17extern int debugfs_valid_entry(const char *path);
18extern char *debugfs_mount(const char *mountpoint);
19extern int debugfs_umount(void);
20extern int debugfs_write(const char *entry, const char *value);
21extern int debugfs_read(const char *entry, char *buffer, size_t size);
22extern void debugfs_force_cleanup(void);
23extern int debugfs_make_path(const char *element, char *buffer, int size);
24 17
25#endif /* __DEBUGFS_H__ */ 18#endif /* __DEBUGFS_H__ */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 437f8ca679a0..97c479bcb0dc 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,7 +1,6 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include "event.h" 2#include "event.h"
3#include "debug.h" 3#include "debug.h"
4#include "session.h"
5#include "sort.h" 4#include "sort.h"
6#include "string.h" 5#include "string.h"
7#include "strlist.h" 6#include "strlist.h"
@@ -44,9 +43,10 @@ static struct perf_sample synth_sample = {
44 .period = 1, 43 .period = 1,
45}; 44};
46 45
47static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid, 46static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
47 union perf_event *event, pid_t pid,
48 int full, perf_event__handler_t process, 48 int full, perf_event__handler_t process,
49 struct perf_session *session) 49 struct machine *machine)
50{ 50{
51 char filename[PATH_MAX]; 51 char filename[PATH_MAX];
52 char bf[BUFSIZ]; 52 char bf[BUFSIZ];
@@ -92,14 +92,14 @@ out_race:
92 92
93 event->comm.header.type = PERF_RECORD_COMM; 93 event->comm.header.type = PERF_RECORD_COMM;
94 size = ALIGN(size, sizeof(u64)); 94 size = ALIGN(size, sizeof(u64));
95 memset(event->comm.comm + size, 0, session->id_hdr_size); 95 memset(event->comm.comm + size, 0, machine->id_hdr_size);
96 event->comm.header.size = (sizeof(event->comm) - 96 event->comm.header.size = (sizeof(event->comm) -
97 (sizeof(event->comm.comm) - size) + 97 (sizeof(event->comm.comm) - size) +
98 session->id_hdr_size); 98 machine->id_hdr_size);
99 if (!full) { 99 if (!full) {
100 event->comm.tid = pid; 100 event->comm.tid = pid;
101 101
102 process(event, &synth_sample, session); 102 process(tool, event, &synth_sample, machine);
103 goto out; 103 goto out;
104 } 104 }
105 105
@@ -117,7 +117,7 @@ out_race:
117 117
118 event->comm.tid = pid; 118 event->comm.tid = pid;
119 119
120 process(event, &synth_sample, session); 120 process(tool, event, &synth_sample, machine);
121 } 121 }
122 122
123 closedir(tasks); 123 closedir(tasks);
@@ -127,10 +127,11 @@ out:
127 return tgid; 127 return tgid;
128} 128}
129 129
130static int perf_event__synthesize_mmap_events(union perf_event *event, 130static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
131 union perf_event *event,
131 pid_t pid, pid_t tgid, 132 pid_t pid, pid_t tgid,
132 perf_event__handler_t process, 133 perf_event__handler_t process,
133 struct perf_session *session) 134 struct machine *machine)
134{ 135{
135 char filename[PATH_MAX]; 136 char filename[PATH_MAX];
136 FILE *fp; 137 FILE *fp;
@@ -193,12 +194,12 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
193 event->mmap.len -= event->mmap.start; 194 event->mmap.len -= event->mmap.start;
194 event->mmap.header.size = (sizeof(event->mmap) - 195 event->mmap.header.size = (sizeof(event->mmap) -
195 (sizeof(event->mmap.filename) - size)); 196 (sizeof(event->mmap.filename) - size));
196 memset(event->mmap.filename + size, 0, session->id_hdr_size); 197 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
197 event->mmap.header.size += session->id_hdr_size; 198 event->mmap.header.size += machine->id_hdr_size;
198 event->mmap.pid = tgid; 199 event->mmap.pid = tgid;
199 event->mmap.tid = pid; 200 event->mmap.tid = pid;
200 201
201 process(event, &synth_sample, session); 202 process(tool, event, &synth_sample, machine);
202 } 203 }
203 } 204 }
204 205
@@ -206,14 +207,14 @@ static int perf_event__synthesize_mmap_events(union perf_event *event,
206 return 0; 207 return 0;
207} 208}
208 209
209int perf_event__synthesize_modules(perf_event__handler_t process, 210int perf_event__synthesize_modules(struct perf_tool *tool,
210 struct perf_session *session, 211 perf_event__handler_t process,
211 struct machine *machine) 212 struct machine *machine)
212{ 213{
213 struct rb_node *nd; 214 struct rb_node *nd;
214 struct map_groups *kmaps = &machine->kmaps; 215 struct map_groups *kmaps = &machine->kmaps;
215 union perf_event *event = zalloc((sizeof(event->mmap) + 216 union perf_event *event = zalloc((sizeof(event->mmap) +
216 session->id_hdr_size)); 217 machine->id_hdr_size));
217 if (event == NULL) { 218 if (event == NULL) {
218 pr_debug("Not enough memory synthesizing mmap event " 219 pr_debug("Not enough memory synthesizing mmap event "
219 "for kernel modules\n"); 220 "for kernel modules\n");
@@ -243,15 +244,15 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
243 event->mmap.header.type = PERF_RECORD_MMAP; 244 event->mmap.header.type = PERF_RECORD_MMAP;
244 event->mmap.header.size = (sizeof(event->mmap) - 245 event->mmap.header.size = (sizeof(event->mmap) -
245 (sizeof(event->mmap.filename) - size)); 246 (sizeof(event->mmap.filename) - size));
246 memset(event->mmap.filename + size, 0, session->id_hdr_size); 247 memset(event->mmap.filename + size, 0, machine->id_hdr_size);
247 event->mmap.header.size += session->id_hdr_size; 248 event->mmap.header.size += machine->id_hdr_size;
248 event->mmap.start = pos->start; 249 event->mmap.start = pos->start;
249 event->mmap.len = pos->end - pos->start; 250 event->mmap.len = pos->end - pos->start;
250 event->mmap.pid = machine->pid; 251 event->mmap.pid = machine->pid;
251 252
252 memcpy(event->mmap.filename, pos->dso->long_name, 253 memcpy(event->mmap.filename, pos->dso->long_name,
253 pos->dso->long_name_len + 1); 254 pos->dso->long_name_len + 1);
254 process(event, &synth_sample, session); 255 process(tool, event, &synth_sample, machine);
255 } 256 }
256 257
257 free(event); 258 free(event);
@@ -261,28 +262,30 @@ int perf_event__synthesize_modules(perf_event__handler_t process,
261static int __event__synthesize_thread(union perf_event *comm_event, 262static int __event__synthesize_thread(union perf_event *comm_event,
262 union perf_event *mmap_event, 263 union perf_event *mmap_event,
263 pid_t pid, perf_event__handler_t process, 264 pid_t pid, perf_event__handler_t process,
264 struct perf_session *session) 265 struct perf_tool *tool,
266 struct machine *machine)
265{ 267{
266 pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process, 268 pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, 1,
267 session); 269 process, machine);
268 if (tgid == -1) 270 if (tgid == -1)
269 return -1; 271 return -1;
270 return perf_event__synthesize_mmap_events(mmap_event, pid, tgid, 272 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
271 process, session); 273 process, machine);
272} 274}
273 275
274int perf_event__synthesize_thread_map(struct thread_map *threads, 276int perf_event__synthesize_thread_map(struct perf_tool *tool,
277 struct thread_map *threads,
275 perf_event__handler_t process, 278 perf_event__handler_t process,
276 struct perf_session *session) 279 struct machine *machine)
277{ 280{
278 union perf_event *comm_event, *mmap_event; 281 union perf_event *comm_event, *mmap_event;
279 int err = -1, thread; 282 int err = -1, thread;
280 283
281 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 284 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
282 if (comm_event == NULL) 285 if (comm_event == NULL)
283 goto out; 286 goto out;
284 287
285 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 288 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
286 if (mmap_event == NULL) 289 if (mmap_event == NULL)
287 goto out_free_comm; 290 goto out_free_comm;
288 291
@@ -290,7 +293,7 @@ int perf_event__synthesize_thread_map(struct thread_map *threads,
290 for (thread = 0; thread < threads->nr; ++thread) { 293 for (thread = 0; thread < threads->nr; ++thread) {
291 if (__event__synthesize_thread(comm_event, mmap_event, 294 if (__event__synthesize_thread(comm_event, mmap_event,
292 threads->map[thread], 295 threads->map[thread],
293 process, session)) { 296 process, tool, machine)) {
294 err = -1; 297 err = -1;
295 break; 298 break;
296 } 299 }
@@ -302,19 +305,20 @@ out:
302 return err; 305 return err;
303} 306}
304 307
305int perf_event__synthesize_threads(perf_event__handler_t process, 308int perf_event__synthesize_threads(struct perf_tool *tool,
306 struct perf_session *session) 309 perf_event__handler_t process,
310 struct machine *machine)
307{ 311{
308 DIR *proc; 312 DIR *proc;
309 struct dirent dirent, *next; 313 struct dirent dirent, *next;
310 union perf_event *comm_event, *mmap_event; 314 union perf_event *comm_event, *mmap_event;
311 int err = -1; 315 int err = -1;
312 316
313 comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); 317 comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
314 if (comm_event == NULL) 318 if (comm_event == NULL)
315 goto out; 319 goto out;
316 320
317 mmap_event = malloc(sizeof(mmap_event->mmap) + session->id_hdr_size); 321 mmap_event = malloc(sizeof(mmap_event->mmap) + machine->id_hdr_size);
318 if (mmap_event == NULL) 322 if (mmap_event == NULL)
319 goto out_free_comm; 323 goto out_free_comm;
320 324
@@ -330,7 +334,7 @@ int perf_event__synthesize_threads(perf_event__handler_t process,
330 continue; 334 continue;
331 335
332 __event__synthesize_thread(comm_event, mmap_event, pid, 336 __event__synthesize_thread(comm_event, mmap_event, pid,
333 process, session); 337 process, tool, machine);
334 } 338 }
335 339
336 closedir(proc); 340 closedir(proc);
@@ -365,8 +369,8 @@ static int find_symbol_cb(void *arg, const char *name, char type,
365 return 1; 369 return 1;
366} 370}
367 371
368int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 372int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
369 struct perf_session *session, 373 perf_event__handler_t process,
370 struct machine *machine, 374 struct machine *machine,
371 const char *symbol_name) 375 const char *symbol_name)
372{ 376{
@@ -383,7 +387,7 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
383 */ 387 */
384 struct process_symbol_args args = { .name = symbol_name, }; 388 struct process_symbol_args args = { .name = symbol_name, };
385 union perf_event *event = zalloc((sizeof(event->mmap) + 389 union perf_event *event = zalloc((sizeof(event->mmap) +
386 session->id_hdr_size)); 390 machine->id_hdr_size));
387 if (event == NULL) { 391 if (event == NULL) {
388 pr_debug("Not enough memory synthesizing mmap event " 392 pr_debug("Not enough memory synthesizing mmap event "
389 "for kernel modules\n"); 393 "for kernel modules\n");
@@ -417,25 +421,32 @@ int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
417 size = ALIGN(size, sizeof(u64)); 421 size = ALIGN(size, sizeof(u64));
418 event->mmap.header.type = PERF_RECORD_MMAP; 422 event->mmap.header.type = PERF_RECORD_MMAP;
419 event->mmap.header.size = (sizeof(event->mmap) - 423 event->mmap.header.size = (sizeof(event->mmap) -
420 (sizeof(event->mmap.filename) - size) + session->id_hdr_size); 424 (sizeof(event->mmap.filename) - size) + machine->id_hdr_size);
421 event->mmap.pgoff = args.start; 425 event->mmap.pgoff = args.start;
422 event->mmap.start = map->start; 426 event->mmap.start = map->start;
423 event->mmap.len = map->end - event->mmap.start; 427 event->mmap.len = map->end - event->mmap.start;
424 event->mmap.pid = machine->pid; 428 event->mmap.pid = machine->pid;
425 429
426 err = process(event, &synth_sample, session); 430 err = process(tool, event, &synth_sample, machine);
427 free(event); 431 free(event);
428 432
429 return err; 433 return err;
430} 434}
431 435
432int perf_event__process_comm(union perf_event *event, 436size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
437{
438 return fprintf(fp, ": %s:%d\n", event->comm.comm, event->comm.tid);
439}
440
441int perf_event__process_comm(struct perf_tool *tool __used,
442 union perf_event *event,
433 struct perf_sample *sample __used, 443 struct perf_sample *sample __used,
434 struct perf_session *session) 444 struct machine *machine)
435{ 445{
436 struct thread *thread = perf_session__findnew(session, event->comm.tid); 446 struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
437 447
438 dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid); 448 if (dump_trace)
449 perf_event__fprintf_comm(event, stdout);
439 450
440 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { 451 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
441 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); 452 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
@@ -445,13 +456,13 @@ int perf_event__process_comm(union perf_event *event,
445 return 0; 456 return 0;
446} 457}
447 458
448int perf_event__process_lost(union perf_event *event, 459int perf_event__process_lost(struct perf_tool *tool __used,
460 union perf_event *event,
449 struct perf_sample *sample __used, 461 struct perf_sample *sample __used,
450 struct perf_session *session) 462 struct machine *machine __used)
451{ 463{
452 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", 464 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
453 event->lost.id, event->lost.lost); 465 event->lost.id, event->lost.lost);
454 session->hists.stats.total_lost += event->lost.lost;
455 return 0; 466 return 0;
456} 467}
457 468
@@ -468,21 +479,15 @@ static void perf_event__set_kernel_mmap_len(union perf_event *event,
468 maps[MAP__FUNCTION]->end = ~0ULL; 479 maps[MAP__FUNCTION]->end = ~0ULL;
469} 480}
470 481
471static int perf_event__process_kernel_mmap(union perf_event *event, 482static int perf_event__process_kernel_mmap(struct perf_tool *tool __used,
472 struct perf_session *session) 483 union perf_event *event,
484 struct machine *machine)
473{ 485{
474 struct map *map; 486 struct map *map;
475 char kmmap_prefix[PATH_MAX]; 487 char kmmap_prefix[PATH_MAX];
476 struct machine *machine;
477 enum dso_kernel_type kernel_type; 488 enum dso_kernel_type kernel_type;
478 bool is_kernel_mmap; 489 bool is_kernel_mmap;
479 490
480 machine = perf_session__findnew_machine(session, event->mmap.pid);
481 if (!machine) {
482 pr_err("Can't find id %d's machine\n", event->mmap.pid);
483 goto out_problem;
484 }
485
486 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); 491 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
487 if (machine__is_host(machine)) 492 if (machine__is_host(machine))
488 kernel_type = DSO_TYPE_KERNEL; 493 kernel_type = DSO_TYPE_KERNEL;
@@ -549,9 +554,9 @@ static int perf_event__process_kernel_mmap(union perf_event *event,
549 * time /proc/sys/kernel/kptr_restrict was non zero. 554 * time /proc/sys/kernel/kptr_restrict was non zero.
550 */ 555 */
551 if (event->mmap.pgoff != 0) { 556 if (event->mmap.pgoff != 0) {
552 perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, 557 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
553 symbol_name, 558 symbol_name,
554 event->mmap.pgoff); 559 event->mmap.pgoff);
555 } 560 }
556 561
557 if (machine__is_default_guest(machine)) { 562 if (machine__is_default_guest(machine)) {
@@ -567,32 +572,35 @@ out_problem:
567 return -1; 572 return -1;
568} 573}
569 574
570int perf_event__process_mmap(union perf_event *event, 575size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
576{
577 return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
578 event->mmap.pid, event->mmap.tid, event->mmap.start,
579 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
580}
581
582int perf_event__process_mmap(struct perf_tool *tool,
583 union perf_event *event,
571 struct perf_sample *sample __used, 584 struct perf_sample *sample __used,
572 struct perf_session *session) 585 struct machine *machine)
573{ 586{
574 struct machine *machine;
575 struct thread *thread; 587 struct thread *thread;
576 struct map *map; 588 struct map *map;
577 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 589 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
578 int ret = 0; 590 int ret = 0;
579 591
580 dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", 592 if (dump_trace)
581 event->mmap.pid, event->mmap.tid, event->mmap.start, 593 perf_event__fprintf_mmap(event, stdout);
582 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
583 594
584 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || 595 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
585 cpumode == PERF_RECORD_MISC_KERNEL) { 596 cpumode == PERF_RECORD_MISC_KERNEL) {
586 ret = perf_event__process_kernel_mmap(event, session); 597 ret = perf_event__process_kernel_mmap(tool, event, machine);
587 if (ret < 0) 598 if (ret < 0)
588 goto out_problem; 599 goto out_problem;
589 return 0; 600 return 0;
590 } 601 }
591 602
592 machine = perf_session__find_host_machine(session); 603 thread = machine__findnew_thread(machine, event->mmap.pid);
593 if (machine == NULL)
594 goto out_problem;
595 thread = perf_session__findnew(session, event->mmap.pid);
596 if (thread == NULL) 604 if (thread == NULL)
597 goto out_problem; 605 goto out_problem;
598 map = map__new(&machine->user_dsos, event->mmap.start, 606 map = map__new(&machine->user_dsos, event->mmap.start,
@@ -610,18 +618,26 @@ out_problem:
610 return 0; 618 return 0;
611} 619}
612 620
613int perf_event__process_task(union perf_event *event, 621size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
622{
623 return fprintf(fp, "(%d:%d):(%d:%d)\n",
624 event->fork.pid, event->fork.tid,
625 event->fork.ppid, event->fork.ptid);
626}
627
628int perf_event__process_task(struct perf_tool *tool __used,
629 union perf_event *event,
614 struct perf_sample *sample __used, 630 struct perf_sample *sample __used,
615 struct perf_session *session) 631 struct machine *machine)
616{ 632{
617 struct thread *thread = perf_session__findnew(session, event->fork.tid); 633 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
618 struct thread *parent = perf_session__findnew(session, event->fork.ptid); 634 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
619 635
620 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 636 if (dump_trace)
621 event->fork.ppid, event->fork.ptid); 637 perf_event__fprintf_task(event, stdout);
622 638
623 if (event->header.type == PERF_RECORD_EXIT) { 639 if (event->header.type == PERF_RECORD_EXIT) {
624 perf_session__remove_thread(session, thread); 640 machine__remove_thread(machine, thread);
625 return 0; 641 return 0;
626 } 642 }
627 643
@@ -634,22 +650,45 @@ int perf_event__process_task(union perf_event *event,
634 return 0; 650 return 0;
635} 651}
636 652
637int perf_event__process(union perf_event *event, struct perf_sample *sample, 653size_t perf_event__fprintf(union perf_event *event, FILE *fp)
638 struct perf_session *session)
639{ 654{
655 size_t ret = fprintf(fp, "PERF_RECORD_%s",
656 perf_event__name(event->header.type));
657
640 switch (event->header.type) { 658 switch (event->header.type) {
641 case PERF_RECORD_COMM: 659 case PERF_RECORD_COMM:
642 perf_event__process_comm(event, sample, session); 660 ret += perf_event__fprintf_comm(event, fp);
661 break;
662 case PERF_RECORD_FORK:
663 case PERF_RECORD_EXIT:
664 ret += perf_event__fprintf_task(event, fp);
643 break; 665 break;
644 case PERF_RECORD_MMAP: 666 case PERF_RECORD_MMAP:
645 perf_event__process_mmap(event, sample, session); 667 ret += perf_event__fprintf_mmap(event, fp);
668 break;
669 default:
670 ret += fprintf(fp, "\n");
671 }
672
673 return ret;
674}
675
676int perf_event__process(struct perf_tool *tool, union perf_event *event,
677 struct perf_sample *sample, struct machine *machine)
678{
679 switch (event->header.type) {
680 case PERF_RECORD_COMM:
681 perf_event__process_comm(tool, event, sample, machine);
682 break;
683 case PERF_RECORD_MMAP:
684 perf_event__process_mmap(tool, event, sample, machine);
646 break; 685 break;
647 case PERF_RECORD_FORK: 686 case PERF_RECORD_FORK:
648 case PERF_RECORD_EXIT: 687 case PERF_RECORD_EXIT:
649 perf_event__process_task(event, sample, session); 688 perf_event__process_task(tool, event, sample, machine);
650 break; 689 break;
651 case PERF_RECORD_LOST: 690 case PERF_RECORD_LOST:
652 perf_event__process_lost(event, sample, session); 691 perf_event__process_lost(tool, event, sample, machine);
653 default: 692 default:
654 break; 693 break;
655 } 694 }
@@ -658,36 +697,29 @@ int perf_event__process(union perf_event *event, struct perf_sample *sample,
658} 697}
659 698
660void thread__find_addr_map(struct thread *self, 699void thread__find_addr_map(struct thread *self,
661 struct perf_session *session, u8 cpumode, 700 struct machine *machine, u8 cpumode,
662 enum map_type type, pid_t pid, u64 addr, 701 enum map_type type, u64 addr,
663 struct addr_location *al) 702 struct addr_location *al)
664{ 703{
665 struct map_groups *mg = &self->mg; 704 struct map_groups *mg = &self->mg;
666 struct machine *machine = NULL;
667 705
668 al->thread = self; 706 al->thread = self;
669 al->addr = addr; 707 al->addr = addr;
670 al->cpumode = cpumode; 708 al->cpumode = cpumode;
671 al->filtered = false; 709 al->filtered = false;
672 710
711 if (machine == NULL) {
712 al->map = NULL;
713 return;
714 }
715
673 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 716 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
674 al->level = 'k'; 717 al->level = 'k';
675 machine = perf_session__find_host_machine(session);
676 if (machine == NULL) {
677 al->map = NULL;
678 return;
679 }
680 mg = &machine->kmaps; 718 mg = &machine->kmaps;
681 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 719 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
682 al->level = '.'; 720 al->level = '.';
683 machine = perf_session__find_host_machine(session);
684 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 721 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
685 al->level = 'g'; 722 al->level = 'g';
686 machine = perf_session__find_machine(session, pid);
687 if (machine == NULL) {
688 al->map = NULL;
689 return;
690 }
691 mg = &machine->kmaps; 723 mg = &machine->kmaps;
692 } else { 724 } else {
693 /* 725 /*
@@ -733,13 +765,12 @@ try_again:
733 al->addr = al->map->map_ip(al->map, al->addr); 765 al->addr = al->map->map_ip(al->map, al->addr);
734} 766}
735 767
736void thread__find_addr_location(struct thread *self, 768void thread__find_addr_location(struct thread *thread, struct machine *machine,
737 struct perf_session *session, u8 cpumode, 769 u8 cpumode, enum map_type type, u64 addr,
738 enum map_type type, pid_t pid, u64 addr,
739 struct addr_location *al, 770 struct addr_location *al,
740 symbol_filter_t filter) 771 symbol_filter_t filter)
741{ 772{
742 thread__find_addr_map(self, session, cpumode, type, pid, addr, al); 773 thread__find_addr_map(thread, machine, cpumode, type, addr, al);
743 if (al->map != NULL) 774 if (al->map != NULL)
744 al->sym = map__find_symbol(al->map, al->addr, filter); 775 al->sym = map__find_symbol(al->map, al->addr, filter);
745 else 776 else
@@ -747,13 +778,13 @@ void thread__find_addr_location(struct thread *self,
747} 778}
748 779
749int perf_event__preprocess_sample(const union perf_event *event, 780int perf_event__preprocess_sample(const union perf_event *event,
750 struct perf_session *session, 781 struct machine *machine,
751 struct addr_location *al, 782 struct addr_location *al,
752 struct perf_sample *sample, 783 struct perf_sample *sample,
753 symbol_filter_t filter) 784 symbol_filter_t filter)
754{ 785{
755 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 786 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
756 struct thread *thread = perf_session__findnew(session, event->ip.pid); 787 struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
757 788
758 if (thread == NULL) 789 if (thread == NULL)
759 return -1; 790 return -1;
@@ -764,18 +795,18 @@ int perf_event__preprocess_sample(const union perf_event *event,
764 795
765 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 796 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
766 /* 797 /*
767 * Have we already created the kernel maps for the host machine? 798 * Have we already created the kernel maps for this machine?
768 * 799 *
769 * This should have happened earlier, when we processed the kernel MMAP 800 * This should have happened earlier, when we processed the kernel MMAP
770 * events, but for older perf.data files there was no such thing, so do 801 * events, but for older perf.data files there was no such thing, so do
771 * it now. 802 * it now.
772 */ 803 */
773 if (cpumode == PERF_RECORD_MISC_KERNEL && 804 if (cpumode == PERF_RECORD_MISC_KERNEL &&
774 session->host_machine.vmlinux_maps[MAP__FUNCTION] == NULL) 805 machine->vmlinux_maps[MAP__FUNCTION] == NULL)
775 machine__create_kernel_maps(&session->host_machine); 806 machine__create_kernel_maps(machine);
776 807
777 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION, 808 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
778 event->ip.pid, event->ip.ip, al); 809 event->ip.ip, al);
779 dump_printf(" ...... dso: %s\n", 810 dump_printf(" ...... dso: %s\n",
780 al->map ? al->map->dso->long_name : 811 al->map ? al->map->dso->long_name :
781 al->level == 'H' ? "[hypervisor]" : "<not found>"); 812 al->level == 'H' ? "[hypervisor]" : "<not found>");
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 357a85b85248..0d80201ce844 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -2,6 +2,7 @@
2#define __PERF_RECORD_H 2#define __PERF_RECORD_H
3 3
4#include <limits.h> 4#include <limits.h>
5#include <stdio.h>
5 6
6#include "../perf.h" 7#include "../perf.h"
7#include "map.h" 8#include "map.h"
@@ -141,43 +142,54 @@ union perf_event {
141 142
142void perf_event__print_totals(void); 143void perf_event__print_totals(void);
143 144
144struct perf_session; 145struct perf_tool;
145struct thread_map; 146struct thread_map;
146 147
147typedef int (*perf_event__handler_synth_t)(union perf_event *event, 148typedef int (*perf_event__handler_t)(struct perf_tool *tool,
148 struct perf_session *session); 149 union perf_event *event,
149typedef int (*perf_event__handler_t)(union perf_event *event,
150 struct perf_sample *sample, 150 struct perf_sample *sample,
151 struct perf_session *session); 151 struct machine *machine);
152 152
153int perf_event__synthesize_thread_map(struct thread_map *threads, 153int perf_event__synthesize_thread_map(struct perf_tool *tool,
154 struct thread_map *threads,
154 perf_event__handler_t process, 155 perf_event__handler_t process,
155 struct perf_session *session); 156 struct machine *machine);
156int perf_event__synthesize_threads(perf_event__handler_t process, 157int perf_event__synthesize_threads(struct perf_tool *tool,
157 struct perf_session *session); 158 perf_event__handler_t process,
158int perf_event__synthesize_kernel_mmap(perf_event__handler_t process, 159 struct machine *machine);
159 struct perf_session *session, 160int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
161 perf_event__handler_t process,
160 struct machine *machine, 162 struct machine *machine,
161 const char *symbol_name); 163 const char *symbol_name);
162 164
163int perf_event__synthesize_modules(perf_event__handler_t process, 165int perf_event__synthesize_modules(struct perf_tool *tool,
164 struct perf_session *session, 166 perf_event__handler_t process,
165 struct machine *machine); 167 struct machine *machine);
166 168
167int perf_event__process_comm(union perf_event *event, struct perf_sample *sample, 169int perf_event__process_comm(struct perf_tool *tool,
168 struct perf_session *session); 170 union perf_event *event,
169int perf_event__process_lost(union perf_event *event, struct perf_sample *sample, 171 struct perf_sample *sample,
170 struct perf_session *session); 172 struct machine *machine);
171int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample, 173int perf_event__process_lost(struct perf_tool *tool,
172 struct perf_session *session); 174 union perf_event *event,
173int perf_event__process_task(union perf_event *event, struct perf_sample *sample, 175 struct perf_sample *sample,
174 struct perf_session *session); 176 struct machine *machine);
175int perf_event__process(union perf_event *event, struct perf_sample *sample, 177int perf_event__process_mmap(struct perf_tool *tool,
176 struct perf_session *session); 178 union perf_event *event,
179 struct perf_sample *sample,
180 struct machine *machine);
181int perf_event__process_task(struct perf_tool *tool,
182 union perf_event *event,
183 struct perf_sample *sample,
184 struct machine *machine);
185int perf_event__process(struct perf_tool *tool,
186 union perf_event *event,
187 struct perf_sample *sample,
188 struct machine *machine);
177 189
178struct addr_location; 190struct addr_location;
179int perf_event__preprocess_sample(const union perf_event *self, 191int perf_event__preprocess_sample(const union perf_event *self,
180 struct perf_session *session, 192 struct machine *machine,
181 struct addr_location *al, 193 struct addr_location *al,
182 struct perf_sample *sample, 194 struct perf_sample *sample,
183 symbol_filter_t filter); 195 symbol_filter_t filter);
@@ -188,4 +200,9 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
188 int sample_size, bool sample_id_all, 200 int sample_size, bool sample_id_all,
189 struct perf_sample *sample, bool swapped); 201 struct perf_sample *sample, bool swapped);
190 202
203size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
204size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
205size_t perf_event__fprintf_task(union perf_event *event, FILE *fp);
206size_t perf_event__fprintf(union perf_event *event, FILE *fp);
207
191#endif /* __PERF_RECORD_H */ 208#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index fbb4b4ab9cc6..8b19e7a1e881 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -6,12 +6,16 @@
6 * 6 *
7 * Released under the GPL v2. (and only v2, not any later version) 7 * Released under the GPL v2. (and only v2, not any later version)
8 */ 8 */
9#include "util.h"
10#include "debugfs.h"
9#include <poll.h> 11#include <poll.h>
10#include "cpumap.h" 12#include "cpumap.h"
11#include "thread_map.h" 13#include "thread_map.h"
12#include "evlist.h" 14#include "evlist.h"
13#include "evsel.h" 15#include "evsel.h"
14#include "util.h" 16#include <unistd.h>
17
18#include "parse-events.h"
15 19
16#include <sys/mman.h> 20#include <sys/mman.h>
17 21
@@ -30,6 +34,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
30 INIT_HLIST_HEAD(&evlist->heads[i]); 34 INIT_HLIST_HEAD(&evlist->heads[i]);
31 INIT_LIST_HEAD(&evlist->entries); 35 INIT_LIST_HEAD(&evlist->entries);
32 perf_evlist__set_maps(evlist, cpus, threads); 36 perf_evlist__set_maps(evlist, cpus, threads);
37 evlist->workload.pid = -1;
33} 38}
34 39
35struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 40struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -43,6 +48,22 @@ struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
43 return evlist; 48 return evlist;
44} 49}
45 50
51void perf_evlist__config_attrs(struct perf_evlist *evlist,
52 struct perf_record_opts *opts)
53{
54 struct perf_evsel *evsel;
55
56 if (evlist->cpus->map[0] < 0)
57 opts->no_inherit = true;
58
59 list_for_each_entry(evsel, &evlist->entries, node) {
60 perf_evsel__config(evsel, opts);
61
62 if (evlist->nr_entries > 1)
63 evsel->attr.sample_type |= PERF_SAMPLE_ID;
64 }
65}
66
46static void perf_evlist__purge(struct perf_evlist *evlist) 67static void perf_evlist__purge(struct perf_evlist *evlist)
47{ 68{
48 struct perf_evsel *pos, *n; 69 struct perf_evsel *pos, *n;
@@ -76,6 +97,14 @@ void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
76 ++evlist->nr_entries; 97 ++evlist->nr_entries;
77} 98}
78 99
100static void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
101 struct list_head *list,
102 int nr_entries)
103{
104 list_splice_tail(list, &evlist->entries);
105 evlist->nr_entries += nr_entries;
106}
107
79int perf_evlist__add_default(struct perf_evlist *evlist) 108int perf_evlist__add_default(struct perf_evlist *evlist)
80{ 109{
81 struct perf_event_attr attr = { 110 struct perf_event_attr attr = {
@@ -100,6 +129,126 @@ error:
100 return -ENOMEM; 129 return -ENOMEM;
101} 130}
102 131
132int perf_evlist__add_attrs(struct perf_evlist *evlist,
133 struct perf_event_attr *attrs, size_t nr_attrs)
134{
135 struct perf_evsel *evsel, *n;
136 LIST_HEAD(head);
137 size_t i;
138
139 for (i = 0; i < nr_attrs; i++) {
140 evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
141 if (evsel == NULL)
142 goto out_delete_partial_list;
143 list_add_tail(&evsel->node, &head);
144 }
145
146 perf_evlist__splice_list_tail(evlist, &head, nr_attrs);
147
148 return 0;
149
150out_delete_partial_list:
151 list_for_each_entry_safe(evsel, n, &head, node)
152 perf_evsel__delete(evsel);
153 return -1;
154}
155
156static int trace_event__id(const char *evname)
157{
158 char *filename, *colon;
159 int err = -1, fd;
160
161 if (asprintf(&filename, "%s/%s/id", tracing_events_path, evname) < 0)
162 return -1;
163
164 colon = strrchr(filename, ':');
165 if (colon != NULL)
166 *colon = '/';
167
168 fd = open(filename, O_RDONLY);
169 if (fd >= 0) {
170 char id[16];
171 if (read(fd, id, sizeof(id)) > 0)
172 err = atoi(id);
173 close(fd);
174 }
175
176 free(filename);
177 return err;
178}
179
180int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
181 const char *tracepoints[],
182 size_t nr_tracepoints)
183{
184 int err;
185 size_t i;
186 struct perf_event_attr *attrs = zalloc(nr_tracepoints * sizeof(*attrs));
187
188 if (attrs == NULL)
189 return -1;
190
191 for (i = 0; i < nr_tracepoints; i++) {
192 err = trace_event__id(tracepoints[i]);
193
194 if (err < 0)
195 goto out_free_attrs;
196
197 attrs[i].type = PERF_TYPE_TRACEPOINT;
198 attrs[i].config = err;
199 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
200 PERF_SAMPLE_CPU);
201 attrs[i].sample_period = 1;
202 }
203
204 err = perf_evlist__add_attrs(evlist, attrs, nr_tracepoints);
205out_free_attrs:
206 free(attrs);
207 return err;
208}
209
210static struct perf_evsel *
211 perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
212{
213 struct perf_evsel *evsel;
214
215 list_for_each_entry(evsel, &evlist->entries, node) {
216 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
217 (int)evsel->attr.config == id)
218 return evsel;
219 }
220
221 return NULL;
222}
223
224int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
225 const struct perf_evsel_str_handler *assocs,
226 size_t nr_assocs)
227{
228 struct perf_evsel *evsel;
229 int err;
230 size_t i;
231
232 for (i = 0; i < nr_assocs; i++) {
233 err = trace_event__id(assocs[i].name);
234 if (err < 0)
235 goto out;
236
237 evsel = perf_evlist__find_tracepoint_by_id(evlist, err);
238 if (evsel == NULL)
239 continue;
240
241 err = -EEXIST;
242 if (evsel->handler.func != NULL)
243 goto out;
244 evsel->handler.func = assocs[i].handler;
245 }
246
247 err = 0;
248out:
249 return err;
250}
251
103void perf_evlist__disable(struct perf_evlist *evlist) 252void perf_evlist__disable(struct perf_evlist *evlist)
104{ 253{
105 int cpu, thread; 254 int cpu, thread;
@@ -126,7 +275,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
126 } 275 }
127} 276}
128 277
129int perf_evlist__alloc_pollfd(struct perf_evlist *evlist) 278static int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
130{ 279{
131 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries; 280 int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
132 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds); 281 evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
@@ -282,7 +431,7 @@ void perf_evlist__munmap(struct perf_evlist *evlist)
282 evlist->mmap = NULL; 431 evlist->mmap = NULL;
283} 432}
284 433
285int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 434static int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
286{ 435{
287 evlist->nr_mmaps = evlist->cpus->nr; 436 evlist->nr_mmaps = evlist->cpus->nr;
288 if (evlist->cpus->map[0] == -1) 437 if (evlist->cpus->map[0] == -1)
@@ -400,14 +549,20 @@ out_unmap:
400 * 549 *
401 * Using perf_evlist__read_on_cpu does this automatically. 550 * Using perf_evlist__read_on_cpu does this automatically.
402 */ 551 */
403int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) 552int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
553 bool overwrite)
404{ 554{
405 unsigned int page_size = sysconf(_SC_PAGE_SIZE); 555 unsigned int page_size = sysconf(_SC_PAGE_SIZE);
406 int mask = pages * page_size - 1;
407 struct perf_evsel *evsel; 556 struct perf_evsel *evsel;
408 const struct cpu_map *cpus = evlist->cpus; 557 const struct cpu_map *cpus = evlist->cpus;
409 const struct thread_map *threads = evlist->threads; 558 const struct thread_map *threads = evlist->threads;
410 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE); 559 int prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), mask;
560
561 /* 512 kiB: default amount of unprivileged mlocked memory */
562 if (pages == UINT_MAX)
563 pages = (512 * 1024) / page_size;
564
565 mask = pages * page_size - 1;
411 566
412 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 567 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
413 return -ENOMEM; 568 return -ENOMEM;
@@ -512,6 +667,38 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
512 return first->attr.sample_type; 667 return first->attr.sample_type;
513} 668}
514 669
670u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist)
671{
672 struct perf_evsel *first;
673 struct perf_sample *data;
674 u64 sample_type;
675 u16 size = 0;
676
677 first = list_entry(evlist->entries.next, struct perf_evsel, node);
678
679 if (!first->attr.sample_id_all)
680 goto out;
681
682 sample_type = first->attr.sample_type;
683
684 if (sample_type & PERF_SAMPLE_TID)
685 size += sizeof(data->tid) * 2;
686
687 if (sample_type & PERF_SAMPLE_TIME)
688 size += sizeof(data->time);
689
690 if (sample_type & PERF_SAMPLE_ID)
691 size += sizeof(data->id);
692
693 if (sample_type & PERF_SAMPLE_STREAM_ID)
694 size += sizeof(data->stream_id);
695
696 if (sample_type & PERF_SAMPLE_CPU)
697 size += sizeof(data->cpu) * 2;
698out:
699 return size;
700}
701
515bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist) 702bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
516{ 703{
517 struct perf_evsel *pos, *first; 704 struct perf_evsel *pos, *first;
@@ -569,3 +756,97 @@ out_err:
569 756
570 return err; 757 return err;
571} 758}
759
760int perf_evlist__prepare_workload(struct perf_evlist *evlist,
761 struct perf_record_opts *opts,
762 const char *argv[])
763{
764 int child_ready_pipe[2], go_pipe[2];
765 char bf;
766
767 if (pipe(child_ready_pipe) < 0) {
768 perror("failed to create 'ready' pipe");
769 return -1;
770 }
771
772 if (pipe(go_pipe) < 0) {
773 perror("failed to create 'go' pipe");
774 goto out_close_ready_pipe;
775 }
776
777 evlist->workload.pid = fork();
778 if (evlist->workload.pid < 0) {
779 perror("failed to fork");
780 goto out_close_pipes;
781 }
782
783 if (!evlist->workload.pid) {
784 if (opts->pipe_output)
785 dup2(2, 1);
786
787 close(child_ready_pipe[0]);
788 close(go_pipe[1]);
789 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
790
791 /*
792 * Do a dummy execvp to get the PLT entry resolved,
793 * so we avoid the resolver overhead on the real
794 * execvp call.
795 */
796 execvp("", (char **)argv);
797
798 /*
799 * Tell the parent we're ready to go
800 */
801 close(child_ready_pipe[1]);
802
803 /*
804 * Wait until the parent tells us to go.
805 */
806 if (read(go_pipe[0], &bf, 1) == -1)
807 perror("unable to read pipe");
808
809 execvp(argv[0], (char **)argv);
810
811 perror(argv[0]);
812 kill(getppid(), SIGUSR1);
813 exit(-1);
814 }
815
816 if (!opts->system_wide && opts->target_tid == -1 && opts->target_pid == -1)
817 evlist->threads->map[0] = evlist->workload.pid;
818
819 close(child_ready_pipe[1]);
820 close(go_pipe[0]);
821 /*
822 * wait for child to settle
823 */
824 if (read(child_ready_pipe[0], &bf, 1) == -1) {
825 perror("unable to read pipe");
826 goto out_close_pipes;
827 }
828
829 evlist->workload.cork_fd = go_pipe[1];
830 close(child_ready_pipe[0]);
831 return 0;
832
833out_close_pipes:
834 close(go_pipe[0]);
835 close(go_pipe[1]);
836out_close_ready_pipe:
837 close(child_ready_pipe[0]);
838 close(child_ready_pipe[1]);
839 return -1;
840}
841
842int perf_evlist__start_workload(struct perf_evlist *evlist)
843{
844 if (evlist->workload.cork_fd > 0) {
845 /*
846 * Remove the cork, let it rip!
847 */
848 return close(evlist->workload.cork_fd);
849 }
850
851 return 0;
852}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 1779ffef7828..8922aeed0467 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -2,12 +2,16 @@
2#define __PERF_EVLIST_H 1 2#define __PERF_EVLIST_H 1
3 3
4#include <linux/list.h> 4#include <linux/list.h>
5#include <stdio.h>
5#include "../perf.h" 6#include "../perf.h"
6#include "event.h" 7#include "event.h"
8#include "util.h"
9#include <unistd.h>
7 10
8struct pollfd; 11struct pollfd;
9struct thread_map; 12struct thread_map;
10struct cpu_map; 13struct cpu_map;
14struct perf_record_opts;
11 15
12#define PERF_EVLIST__HLIST_BITS 8 16#define PERF_EVLIST__HLIST_BITS 8
13#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS) 17#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
@@ -19,6 +23,10 @@ struct perf_evlist {
19 int nr_fds; 23 int nr_fds;
20 int nr_mmaps; 24 int nr_mmaps;
21 int mmap_len; 25 int mmap_len;
26 struct {
27 int cork_fd;
28 pid_t pid;
29 } workload;
22 bool overwrite; 30 bool overwrite;
23 union perf_event event_copy; 31 union perf_event event_copy;
24 struct perf_mmap *mmap; 32 struct perf_mmap *mmap;
@@ -28,6 +36,11 @@ struct perf_evlist {
28 struct perf_evsel *selected; 36 struct perf_evsel *selected;
29}; 37};
30 38
39struct perf_evsel_str_handler {
40 const char *name;
41 void *handler;
42};
43
31struct perf_evsel; 44struct perf_evsel;
32 45
33struct perf_evlist *perf_evlist__new(struct cpu_map *cpus, 46struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
@@ -39,11 +52,26 @@ void perf_evlist__delete(struct perf_evlist *evlist);
39 52
40void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry); 53void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
41int perf_evlist__add_default(struct perf_evlist *evlist); 54int perf_evlist__add_default(struct perf_evlist *evlist);
55int perf_evlist__add_attrs(struct perf_evlist *evlist,
56 struct perf_event_attr *attrs, size_t nr_attrs);
57int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
58 const char *tracepoints[], size_t nr_tracepoints);
59int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
60 const struct perf_evsel_str_handler *assocs,
61 size_t nr_assocs);
62
63#define perf_evlist__add_attrs_array(evlist, array) \
64 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array))
65
66#define perf_evlist__add_tracepoints_array(evlist, array) \
67 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
68
69#define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
70 perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
42 71
43void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel, 72void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
44 int cpu, int thread, u64 id); 73 int cpu, int thread, u64 id);
45 74
46int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
47void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd); 75void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
48 76
49struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 77struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
@@ -52,8 +80,16 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
52 80
53int perf_evlist__open(struct perf_evlist *evlist, bool group); 81int perf_evlist__open(struct perf_evlist *evlist, bool group);
54 82
55int perf_evlist__alloc_mmap(struct perf_evlist *evlist); 83void perf_evlist__config_attrs(struct perf_evlist *evlist,
56int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite); 84 struct perf_record_opts *opts);
85
86int perf_evlist__prepare_workload(struct perf_evlist *evlist,
87 struct perf_record_opts *opts,
88 const char *argv[]);
89int perf_evlist__start_workload(struct perf_evlist *evlist);
90
91int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
92 bool overwrite);
57void perf_evlist__munmap(struct perf_evlist *evlist); 93void perf_evlist__munmap(struct perf_evlist *evlist);
58 94
59void perf_evlist__disable(struct perf_evlist *evlist); 95void perf_evlist__disable(struct perf_evlist *evlist);
@@ -77,6 +113,7 @@ int perf_evlist__set_filters(struct perf_evlist *evlist);
77 113
78u64 perf_evlist__sample_type(const struct perf_evlist *evlist); 114u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
79bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist); 115bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
116u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
80 117
81bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist); 118bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
82bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist); 119bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d7915d4e77cb..ee68d6944e61 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -63,6 +63,76 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
63 return evsel; 63 return evsel;
64} 64}
65 65
66void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts)
67{
68 struct perf_event_attr *attr = &evsel->attr;
69 int track = !evsel->idx; /* only the first counter needs these */
70
71 attr->sample_id_all = opts->sample_id_all_avail ? 1 : 0;
72 attr->inherit = !opts->no_inherit;
73 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
74 PERF_FORMAT_TOTAL_TIME_RUNNING |
75 PERF_FORMAT_ID;
76
77 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
78
79 /*
80 * We default some events to a 1 default interval. But keep
81 * it a weak assumption overridable by the user.
82 */
83 if (!attr->sample_period || (opts->user_freq != UINT_MAX &&
84 opts->user_interval != ULLONG_MAX)) {
85 if (opts->freq) {
86 attr->sample_type |= PERF_SAMPLE_PERIOD;
87 attr->freq = 1;
88 attr->sample_freq = opts->freq;
89 } else {
90 attr->sample_period = opts->default_interval;
91 }
92 }
93
94 if (opts->no_samples)
95 attr->sample_freq = 0;
96
97 if (opts->inherit_stat)
98 attr->inherit_stat = 1;
99
100 if (opts->sample_address) {
101 attr->sample_type |= PERF_SAMPLE_ADDR;
102 attr->mmap_data = track;
103 }
104
105 if (opts->call_graph)
106 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
107
108 if (opts->system_wide)
109 attr->sample_type |= PERF_SAMPLE_CPU;
110
111 if (opts->sample_id_all_avail &&
112 (opts->sample_time || opts->system_wide ||
113 !opts->no_inherit || opts->cpu_list))
114 attr->sample_type |= PERF_SAMPLE_TIME;
115
116 if (opts->raw_samples) {
117 attr->sample_type |= PERF_SAMPLE_TIME;
118 attr->sample_type |= PERF_SAMPLE_RAW;
119 attr->sample_type |= PERF_SAMPLE_CPU;
120 }
121
122 if (opts->no_delay) {
123 attr->watermark = 0;
124 attr->wakeup_events = 1;
125 }
126
127 attr->mmap = track;
128 attr->comm = track;
129
130 if (opts->target_pid == -1 && opts->target_tid == -1 && !opts->system_wide) {
131 attr->disabled = 1;
132 attr->enable_on_exec = 1;
133 }
134}
135
66int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 136int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
67{ 137{
68 int cpu, thread; 138 int cpu, thread;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b1d15e6f7ae3..326b8e4d5035 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -61,12 +61,17 @@ struct perf_evsel {
61 off_t id_offset; 61 off_t id_offset;
62 }; 62 };
63 struct cgroup_sel *cgrp; 63 struct cgroup_sel *cgrp;
64 struct {
65 void *func;
66 void *data;
67 } handler;
64 bool supported; 68 bool supported;
65}; 69};
66 70
67struct cpu_map; 71struct cpu_map;
68struct thread_map; 72struct thread_map;
69struct perf_evlist; 73struct perf_evlist;
74struct perf_record_opts;
70 75
71struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx); 76struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
72void perf_evsel__init(struct perf_evsel *evsel, 77void perf_evsel__init(struct perf_evsel *evsel,
@@ -74,6 +79,9 @@ void perf_evsel__init(struct perf_evsel *evsel,
74void perf_evsel__exit(struct perf_evsel *evsel); 79void perf_evsel__exit(struct perf_evsel *evsel);
75void perf_evsel__delete(struct perf_evsel *evsel); 80void perf_evsel__delete(struct perf_evsel *evsel);
76 81
82void perf_evsel__config(struct perf_evsel *evsel,
83 struct perf_record_opts *opts);
84
77int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 85int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
78int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 86int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
79int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 87int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 33c17a2b2a81..5b01449152ef 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2041,6 +2041,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
2041 lseek(fd, tmp, SEEK_SET); 2041 lseek(fd, tmp, SEEK_SET);
2042 } 2042 }
2043 2043
2044 symbol_conf.nr_events = nr_attrs;
2045
2044 if (f_header.event_types.size) { 2046 if (f_header.event_types.size) {
2045 lseek(fd, f_header.event_types.offset, SEEK_SET); 2047 lseek(fd, f_header.event_types.offset, SEEK_SET);
2046 events = malloc(f_header.event_types.size); 2048 events = malloc(f_header.event_types.size);
@@ -2068,9 +2070,9 @@ out_delete_evlist:
2068 return -ENOMEM; 2070 return -ENOMEM;
2069} 2071}
2070 2072
2071int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 2073int perf_event__synthesize_attr(struct perf_tool *tool,
2072 perf_event__handler_t process, 2074 struct perf_event_attr *attr, u16 ids, u64 *id,
2073 struct perf_session *session) 2075 perf_event__handler_t process)
2074{ 2076{
2075 union perf_event *ev; 2077 union perf_event *ev;
2076 size_t size; 2078 size_t size;
@@ -2092,22 +2094,23 @@ int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
2092 ev->attr.header.type = PERF_RECORD_HEADER_ATTR; 2094 ev->attr.header.type = PERF_RECORD_HEADER_ATTR;
2093 ev->attr.header.size = size; 2095 ev->attr.header.size = size;
2094 2096
2095 err = process(ev, NULL, session); 2097 err = process(tool, ev, NULL, NULL);
2096 2098
2097 free(ev); 2099 free(ev);
2098 2100
2099 return err; 2101 return err;
2100} 2102}
2101 2103
2102int perf_session__synthesize_attrs(struct perf_session *session, 2104int perf_event__synthesize_attrs(struct perf_tool *tool,
2105 struct perf_session *session,
2103 perf_event__handler_t process) 2106 perf_event__handler_t process)
2104{ 2107{
2105 struct perf_evsel *attr; 2108 struct perf_evsel *attr;
2106 int err = 0; 2109 int err = 0;
2107 2110
2108 list_for_each_entry(attr, &session->evlist->entries, node) { 2111 list_for_each_entry(attr, &session->evlist->entries, node) {
2109 err = perf_event__synthesize_attr(&attr->attr, attr->ids, 2112 err = perf_event__synthesize_attr(tool, &attr->attr, attr->ids,
2110 attr->id, process, session); 2113 attr->id, process);
2111 if (err) { 2114 if (err) {
2112 pr_debug("failed to create perf header attribute\n"); 2115 pr_debug("failed to create perf header attribute\n");
2113 return err; 2116 return err;
@@ -2118,23 +2121,23 @@ int perf_session__synthesize_attrs(struct perf_session *session,
2118} 2121}
2119 2122
2120int perf_event__process_attr(union perf_event *event, 2123int perf_event__process_attr(union perf_event *event,
2121 struct perf_session *session) 2124 struct perf_evlist **pevlist)
2122{ 2125{
2123 unsigned int i, ids, n_ids; 2126 unsigned int i, ids, n_ids;
2124 struct perf_evsel *evsel; 2127 struct perf_evsel *evsel;
2128 struct perf_evlist *evlist = *pevlist;
2125 2129
2126 if (session->evlist == NULL) { 2130 if (evlist == NULL) {
2127 session->evlist = perf_evlist__new(NULL, NULL); 2131 *pevlist = evlist = perf_evlist__new(NULL, NULL);
2128 if (session->evlist == NULL) 2132 if (evlist == NULL)
2129 return -ENOMEM; 2133 return -ENOMEM;
2130 } 2134 }
2131 2135
2132 evsel = perf_evsel__new(&event->attr.attr, 2136 evsel = perf_evsel__new(&event->attr.attr, evlist->nr_entries);
2133 session->evlist->nr_entries);
2134 if (evsel == NULL) 2137 if (evsel == NULL)
2135 return -ENOMEM; 2138 return -ENOMEM;
2136 2139
2137 perf_evlist__add(session->evlist, evsel); 2140 perf_evlist__add(evlist, evsel);
2138 2141
2139 ids = event->header.size; 2142 ids = event->header.size;
2140 ids -= (void *)&event->attr.id - (void *)event; 2143 ids -= (void *)&event->attr.id - (void *)event;
@@ -2148,18 +2151,16 @@ int perf_event__process_attr(union perf_event *event,
2148 return -ENOMEM; 2151 return -ENOMEM;
2149 2152
2150 for (i = 0; i < n_ids; i++) { 2153 for (i = 0; i < n_ids; i++) {
2151 perf_evlist__id_add(session->evlist, evsel, 0, i, 2154 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
2152 event->attr.id[i]);
2153 } 2155 }
2154 2156
2155 perf_session__update_sample_type(session);
2156
2157 return 0; 2157 return 0;
2158} 2158}
2159 2159
2160int perf_event__synthesize_event_type(u64 event_id, char *name, 2160int perf_event__synthesize_event_type(struct perf_tool *tool,
2161 u64 event_id, char *name,
2161 perf_event__handler_t process, 2162 perf_event__handler_t process,
2162 struct perf_session *session) 2163 struct machine *machine)
2163{ 2164{
2164 union perf_event ev; 2165 union perf_event ev;
2165 size_t size = 0; 2166 size_t size = 0;
@@ -2177,13 +2178,14 @@ int perf_event__synthesize_event_type(u64 event_id, char *name,
2177 ev.event_type.header.size = sizeof(ev.event_type) - 2178 ev.event_type.header.size = sizeof(ev.event_type) -
2178 (sizeof(ev.event_type.event_type.name) - size); 2179 (sizeof(ev.event_type.event_type.name) - size);
2179 2180
2180 err = process(&ev, NULL, session); 2181 err = process(tool, &ev, NULL, machine);
2181 2182
2182 return err; 2183 return err;
2183} 2184}
2184 2185
2185int perf_event__synthesize_event_types(perf_event__handler_t process, 2186int perf_event__synthesize_event_types(struct perf_tool *tool,
2186 struct perf_session *session) 2187 perf_event__handler_t process,
2188 struct machine *machine)
2187{ 2189{
2188 struct perf_trace_event_type *type; 2190 struct perf_trace_event_type *type;
2189 int i, err = 0; 2191 int i, err = 0;
@@ -2191,9 +2193,9 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2191 for (i = 0; i < event_count; i++) { 2193 for (i = 0; i < event_count; i++) {
2192 type = &events[i]; 2194 type = &events[i];
2193 2195
2194 err = perf_event__synthesize_event_type(type->event_id, 2196 err = perf_event__synthesize_event_type(tool, type->event_id,
2195 type->name, process, 2197 type->name, process,
2196 session); 2198 machine);
2197 if (err) { 2199 if (err) {
2198 pr_debug("failed to create perf header event type\n"); 2200 pr_debug("failed to create perf header event type\n");
2199 return err; 2201 return err;
@@ -2203,8 +2205,8 @@ int perf_event__synthesize_event_types(perf_event__handler_t process,
2203 return err; 2205 return err;
2204} 2206}
2205 2207
2206int perf_event__process_event_type(union perf_event *event, 2208int perf_event__process_event_type(struct perf_tool *tool __unused,
2207 struct perf_session *session __unused) 2209 union perf_event *event)
2208{ 2210{
2209 if (perf_header__push_event(event->event_type.event_type.event_id, 2211 if (perf_header__push_event(event->event_type.event_type.event_id,
2210 event->event_type.event_type.name) < 0) 2212 event->event_type.event_type.name) < 0)
@@ -2213,9 +2215,9 @@ int perf_event__process_event_type(union perf_event *event,
2213 return 0; 2215 return 0;
2214} 2216}
2215 2217
2216int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 2218int perf_event__synthesize_tracing_data(struct perf_tool *tool, int fd,
2217 perf_event__handler_t process, 2219 struct perf_evlist *evlist,
2218 struct perf_session *session __unused) 2220 perf_event__handler_t process)
2219{ 2221{
2220 union perf_event ev; 2222 union perf_event ev;
2221 struct tracing_data *tdata; 2223 struct tracing_data *tdata;
@@ -2246,7 +2248,7 @@ int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
2246 ev.tracing_data.header.size = sizeof(ev.tracing_data); 2248 ev.tracing_data.header.size = sizeof(ev.tracing_data);
2247 ev.tracing_data.size = aligned_size; 2249 ev.tracing_data.size = aligned_size;
2248 2250
2249 process(&ev, NULL, session); 2251 process(tool, &ev, NULL, NULL);
2250 2252
2251 /* 2253 /*
2252 * The put function will copy all the tracing data 2254 * The put function will copy all the tracing data
@@ -2288,10 +2290,10 @@ int perf_event__process_tracing_data(union perf_event *event,
2288 return size_read + padding; 2290 return size_read + padding;
2289} 2291}
2290 2292
2291int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 2293int perf_event__synthesize_build_id(struct perf_tool *tool,
2294 struct dso *pos, u16 misc,
2292 perf_event__handler_t process, 2295 perf_event__handler_t process,
2293 struct machine *machine, 2296 struct machine *machine)
2294 struct perf_session *session)
2295{ 2297{
2296 union perf_event ev; 2298 union perf_event ev;
2297 size_t len; 2299 size_t len;
@@ -2311,12 +2313,13 @@ int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
2311 ev.build_id.header.size = sizeof(ev.build_id) + len; 2313 ev.build_id.header.size = sizeof(ev.build_id) + len;
2312 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len); 2314 memcpy(&ev.build_id.filename, pos->long_name, pos->long_name_len);
2313 2315
2314 err = process(&ev, NULL, session); 2316 err = process(tool, &ev, NULL, machine);
2315 2317
2316 return err; 2318 return err;
2317} 2319}
2318 2320
2319int perf_event__process_build_id(union perf_event *event, 2321int perf_event__process_build_id(struct perf_tool *tool __used,
2322 union perf_event *event,
2320 struct perf_session *session) 2323 struct perf_session *session)
2321{ 2324{
2322 __event_process_build_id(&event->build_id, 2325 __event_process_build_id(&event->build_id,
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 3d5a742f4a2a..09365b32098e 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -68,6 +68,7 @@ struct perf_header {
68}; 68};
69 69
70struct perf_evlist; 70struct perf_evlist;
71struct perf_session;
71 72
72int perf_session__read_header(struct perf_session *session, int fd); 73int perf_session__read_header(struct perf_session *session, int fd);
73int perf_session__write_header(struct perf_session *session, 74int perf_session__write_header(struct perf_session *session,
@@ -96,32 +97,36 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
96 const char *name, bool is_kallsyms); 97 const char *name, bool is_kallsyms);
97int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir); 98int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
98 99
99int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id, 100int perf_event__synthesize_attr(struct perf_tool *tool,
100 perf_event__handler_t process, 101 struct perf_event_attr *attr, u16 ids, u64 *id,
101 struct perf_session *session); 102 perf_event__handler_t process);
102int perf_session__synthesize_attrs(struct perf_session *session, 103int perf_event__synthesize_attrs(struct perf_tool *tool,
103 perf_event__handler_t process); 104 struct perf_session *session,
104int perf_event__process_attr(union perf_event *event, struct perf_session *session); 105 perf_event__handler_t process);
106int perf_event__process_attr(union perf_event *event, struct perf_evlist **pevlist);
105 107
106int perf_event__synthesize_event_type(u64 event_id, char *name, 108int perf_event__synthesize_event_type(struct perf_tool *tool,
109 u64 event_id, char *name,
107 perf_event__handler_t process, 110 perf_event__handler_t process,
108 struct perf_session *session); 111 struct machine *machine);
109int perf_event__synthesize_event_types(perf_event__handler_t process, 112int perf_event__synthesize_event_types(struct perf_tool *tool,
110 struct perf_session *session); 113 perf_event__handler_t process,
111int perf_event__process_event_type(union perf_event *event, 114 struct machine *machine);
112 struct perf_session *session); 115int perf_event__process_event_type(struct perf_tool *tool,
113 116 union perf_event *event);
114int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist, 117
115 perf_event__handler_t process, 118int perf_event__synthesize_tracing_data(struct perf_tool *tool,
116 struct perf_session *session); 119 int fd, struct perf_evlist *evlist,
120 perf_event__handler_t process);
117int perf_event__process_tracing_data(union perf_event *event, 121int perf_event__process_tracing_data(union perf_event *event,
118 struct perf_session *session); 122 struct perf_session *session);
119 123
120int perf_event__synthesize_build_id(struct dso *pos, u16 misc, 124int perf_event__synthesize_build_id(struct perf_tool *tool,
125 struct dso *pos, u16 misc,
121 perf_event__handler_t process, 126 perf_event__handler_t process,
122 struct machine *machine, 127 struct machine *machine);
123 struct perf_session *session); 128int perf_event__process_build_id(struct perf_tool *tool,
124int perf_event__process_build_id(union perf_event *event, 129 union perf_event *event,
125 struct perf_session *session); 130 struct perf_session *session);
126 131
127/* 132/*
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 89289c8e935e..ff6f9d56ea41 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -117,7 +117,6 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
117 117
118static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 118static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
119 int evidx __used, 119 int evidx __used,
120 int nr_events __used,
121 void(*timer)(void *arg) __used, 120 void(*timer)(void *arg) __used,
122 void *arg __used, 121 void *arg __used,
123 int delay_secs __used) 122 int delay_secs __used)
@@ -128,7 +127,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
128#define K_RIGHT -2 127#define K_RIGHT -2
129#else 128#else
130#include "ui/keysyms.h" 129#include "ui/keysyms.h"
131int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 130int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
132 void(*timer)(void *arg), void *arg, int delay_secs); 131 void(*timer)(void *arg), void *arg, int delay_secs);
133 132
134int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 133int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 78284b13e808..316aa0ab7122 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -562,6 +562,10 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
562 INIT_LIST_HEAD(&self->user_dsos); 562 INIT_LIST_HEAD(&self->user_dsos);
563 INIT_LIST_HEAD(&self->kernel_dsos); 563 INIT_LIST_HEAD(&self->kernel_dsos);
564 564
565 self->threads = RB_ROOT;
566 INIT_LIST_HEAD(&self->dead_threads);
567 self->last_match = NULL;
568
565 self->kmaps.machine = self; 569 self->kmaps.machine = self;
566 self->pid = pid; 570 self->pid = pid;
567 self->root_dir = strdup(root_dir); 571 self->root_dir = strdup(root_dir);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 890d85545d0f..2b8017f8a930 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -18,9 +18,11 @@ enum map_type {
18extern const char *map_type__name[MAP__NR_TYPES]; 18extern const char *map_type__name[MAP__NR_TYPES];
19 19
20struct dso; 20struct dso;
21struct ip_callchain;
21struct ref_reloc_sym; 22struct ref_reloc_sym;
22struct map_groups; 23struct map_groups;
23struct machine; 24struct machine;
25struct perf_evsel;
24 26
25struct map { 27struct map {
26 union { 28 union {
@@ -61,7 +63,11 @@ struct map_groups {
61struct machine { 63struct machine {
62 struct rb_node rb_node; 64 struct rb_node rb_node;
63 pid_t pid; 65 pid_t pid;
66 u16 id_hdr_size;
64 char *root_dir; 67 char *root_dir;
68 struct rb_root threads;
69 struct list_head dead_threads;
70 struct thread *last_match;
65 struct list_head user_dsos; 71 struct list_head user_dsos;
66 struct list_head kernel_dsos; 72 struct list_head kernel_dsos;
67 struct map_groups kmaps; 73 struct map_groups kmaps;
@@ -148,6 +154,13 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid);
148void machine__exit(struct machine *self); 154void machine__exit(struct machine *self);
149void machine__delete(struct machine *self); 155void machine__delete(struct machine *self);
150 156
157int machine__resolve_callchain(struct machine *machine,
158 struct perf_evsel *evsel, struct thread *thread,
159 struct ip_callchain *chain,
160 struct symbol **parent);
161int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
162 u64 addr);
163
151/* 164/*
152 * Default guest kernel is defined by parameter --guestkallsyms 165 * Default guest kernel is defined by parameter --guestkallsyms
153 * and --guestmodules 166 * and --guestmodules
@@ -190,6 +203,12 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
190 struct map **mapp, 203 struct map **mapp,
191 symbol_filter_t filter); 204 symbol_filter_t filter);
192 205
206
207struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
208void machine__remove_thread(struct machine *machine, struct thread *th);
209
210size_t machine__fprintf(struct machine *machine, FILE *fp);
211
193static inline 212static inline
194struct symbol *machine__find_kernel_symbol(struct machine *self, 213struct symbol *machine__find_kernel_symbol(struct machine *self,
195 enum map_type type, u64 addr, 214 enum map_type type, u64 addr,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 928918b796b2..586ab3fe60f8 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -25,8 +25,6 @@ enum event_result {
25 EVT_HANDLED_ALL 25 EVT_HANDLED_ALL
26}; 26};
27 27
28char debugfs_path[MAXPATHLEN];
29
30#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x 28#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
31#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x 29#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
32 30
@@ -140,7 +138,7 @@ static int tp_event_has_id(struct dirent *sys_dir, struct dirent *evt_dir)
140 char evt_path[MAXPATHLEN]; 138 char evt_path[MAXPATHLEN];
141 int fd; 139 int fd;
142 140
143 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 141 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
144 sys_dir->d_name, evt_dir->d_name); 142 sys_dir->d_name, evt_dir->d_name);
145 fd = open(evt_path, O_RDONLY); 143 fd = open(evt_path, O_RDONLY);
146 if (fd < 0) 144 if (fd < 0)
@@ -171,16 +169,16 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
171 char evt_path[MAXPATHLEN]; 169 char evt_path[MAXPATHLEN];
172 char dir_path[MAXPATHLEN]; 170 char dir_path[MAXPATHLEN];
173 171
174 if (debugfs_valid_mountpoint(debugfs_path)) 172 if (debugfs_valid_mountpoint(tracing_events_path))
175 return NULL; 173 return NULL;
176 174
177 sys_dir = opendir(debugfs_path); 175 sys_dir = opendir(tracing_events_path);
178 if (!sys_dir) 176 if (!sys_dir)
179 return NULL; 177 return NULL;
180 178
181 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 179 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
182 180
183 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 181 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
184 sys_dirent.d_name); 182 sys_dirent.d_name);
185 evt_dir = opendir(dir_path); 183 evt_dir = opendir(dir_path);
186 if (!evt_dir) 184 if (!evt_dir)
@@ -447,7 +445,7 @@ parse_single_tracepoint_event(char *sys_name,
447 u64 id; 445 u64 id;
448 int fd; 446 int fd;
449 447
450 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", debugfs_path, 448 snprintf(evt_path, MAXPATHLEN, "%s/%s/%s/id", tracing_events_path,
451 sys_name, evt_name); 449 sys_name, evt_name);
452 450
453 fd = open(evt_path, O_RDONLY); 451 fd = open(evt_path, O_RDONLY);
@@ -485,7 +483,7 @@ parse_multiple_tracepoint_event(struct perf_evlist *evlist, char *sys_name,
485 struct dirent *evt_ent; 483 struct dirent *evt_ent;
486 DIR *evt_dir; 484 DIR *evt_dir;
487 485
488 snprintf(evt_path, MAXPATHLEN, "%s/%s", debugfs_path, sys_name); 486 snprintf(evt_path, MAXPATHLEN, "%s/%s", tracing_events_path, sys_name);
489 evt_dir = opendir(evt_path); 487 evt_dir = opendir(evt_path);
490 488
491 if (!evt_dir) { 489 if (!evt_dir) {
@@ -528,7 +526,7 @@ parse_tracepoint_event(struct perf_evlist *evlist, const char **strp,
528 char sys_name[MAX_EVENT_LENGTH]; 526 char sys_name[MAX_EVENT_LENGTH];
529 unsigned int sys_length, evt_length; 527 unsigned int sys_length, evt_length;
530 528
531 if (debugfs_valid_mountpoint(debugfs_path)) 529 if (debugfs_valid_mountpoint(tracing_events_path))
532 return 0; 530 return 0;
533 531
534 evt_name = strchr(*strp, ':'); 532 evt_name = strchr(*strp, ':');
@@ -920,10 +918,10 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
920 char evt_path[MAXPATHLEN]; 918 char evt_path[MAXPATHLEN];
921 char dir_path[MAXPATHLEN]; 919 char dir_path[MAXPATHLEN];
922 920
923 if (debugfs_valid_mountpoint(debugfs_path)) 921 if (debugfs_valid_mountpoint(tracing_events_path))
924 return; 922 return;
925 923
926 sys_dir = opendir(debugfs_path); 924 sys_dir = opendir(tracing_events_path);
927 if (!sys_dir) 925 if (!sys_dir)
928 return; 926 return;
929 927
@@ -932,7 +930,7 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
932 !strglobmatch(sys_dirent.d_name, subsys_glob)) 930 !strglobmatch(sys_dirent.d_name, subsys_glob))
933 continue; 931 continue;
934 932
935 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 933 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
936 sys_dirent.d_name); 934 sys_dirent.d_name);
937 evt_dir = opendir(dir_path); 935 evt_dir = opendir(dir_path);
938 if (!evt_dir) 936 if (!evt_dir)
@@ -964,16 +962,16 @@ int is_valid_tracepoint(const char *event_string)
964 char evt_path[MAXPATHLEN]; 962 char evt_path[MAXPATHLEN];
965 char dir_path[MAXPATHLEN]; 963 char dir_path[MAXPATHLEN];
966 964
967 if (debugfs_valid_mountpoint(debugfs_path)) 965 if (debugfs_valid_mountpoint(tracing_events_path))
968 return 0; 966 return 0;
969 967
970 sys_dir = opendir(debugfs_path); 968 sys_dir = opendir(tracing_events_path);
971 if (!sys_dir) 969 if (!sys_dir)
972 return 0; 970 return 0;
973 971
974 for_each_subsystem(sys_dir, sys_dirent, sys_next) { 972 for_each_subsystem(sys_dir, sys_dirent, sys_next) {
975 973
976 snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, 974 snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
977 sys_dirent.d_name); 975 sys_dirent.d_name);
978 evt_dir = opendir(dir_path); 976 evt_dir = opendir(dir_path);
979 if (!evt_dir) 977 if (!evt_dir)
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 2f8e375e038d..7e0cbe75d5f1 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -39,7 +39,6 @@ void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
39int print_hwcache_events(const char *event_glob); 39int print_hwcache_events(const char *event_glob);
40extern int is_valid_tracepoint(const char *event_string); 40extern int is_valid_tracepoint(const char *event_string);
41 41
42extern char debugfs_path[];
43extern int valid_debugfs_mount(const char *debugfs); 42extern int valid_debugfs_mount(const char *debugfs);
44 43
45#endif /* __PERF_PARSE_EVENTS_H */ 44#endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 1132c8f0ce89..17e94d0c36f9 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -5,7 +5,6 @@
5#include "util.h" 5#include "util.h"
6#include "probe-event.h" 6#include "probe-event.h"
7 7
8#define MAX_PATH_LEN 256
9#define MAX_PROBE_BUFFER 1024 8#define MAX_PROBE_BUFFER 1024
10#define MAX_PROBES 128 9#define MAX_PROBES 128
11 10
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 74350ffb57fe..a82ce4303ff5 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -27,6 +27,8 @@
27 27
28#include "../../perf.h" 28#include "../../perf.h"
29#include "../util.h" 29#include "../util.h"
30#include "../thread.h"
31#include "../event.h"
30#include "../trace-event.h" 32#include "../trace-event.h"
31 33
32#include <EXTERN.h> 34#include <EXTERN.h>
@@ -248,7 +250,7 @@ static inline struct event *find_cache_event(int type)
248static void perl_process_event(union perf_event *pevent __unused, 250static void perl_process_event(union perf_event *pevent __unused,
249 struct perf_sample *sample, 251 struct perf_sample *sample,
250 struct perf_evsel *evsel, 252 struct perf_evsel *evsel,
251 struct perf_session *session __unused, 253 struct machine *machine __unused,
252 struct thread *thread) 254 struct thread *thread)
253{ 255{
254 struct format_field *field; 256 struct format_field *field;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 6ccf70e8d8f2..0b2a48783172 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -29,6 +29,8 @@
29 29
30#include "../../perf.h" 30#include "../../perf.h"
31#include "../util.h" 31#include "../util.h"
32#include "../event.h"
33#include "../thread.h"
32#include "../trace-event.h" 34#include "../trace-event.h"
33 35
34PyMODINIT_FUNC initperf_trace_context(void); 36PyMODINIT_FUNC initperf_trace_context(void);
@@ -207,7 +209,7 @@ static inline struct event *find_cache_event(int type)
207static void python_process_event(union perf_event *pevent __unused, 209static void python_process_event(union perf_event *pevent __unused,
208 struct perf_sample *sample, 210 struct perf_sample *sample,
209 struct perf_evsel *evsel __unused, 211 struct perf_evsel *evsel __unused,
210 struct perf_session *session __unused, 212 struct machine *machine __unused,
211 struct thread *thread) 213 struct thread *thread)
212{ 214{
213 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 215 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0f4555ce9063..d9318d8a9ba1 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -10,6 +10,7 @@
10#include "evlist.h" 10#include "evlist.h"
11#include "evsel.h" 11#include "evsel.h"
12#include "session.h" 12#include "session.h"
13#include "tool.h"
13#include "sort.h" 14#include "sort.h"
14#include "util.h" 15#include "util.h"
15#include "cpumap.h" 16#include "cpumap.h"
@@ -78,39 +79,13 @@ out_close:
78 return -1; 79 return -1;
79} 80}
80 81
81static void perf_session__id_header_size(struct perf_session *session)
82{
83 struct perf_sample *data;
84 u64 sample_type = session->sample_type;
85 u16 size = 0;
86
87 if (!session->sample_id_all)
88 goto out;
89
90 if (sample_type & PERF_SAMPLE_TID)
91 size += sizeof(data->tid) * 2;
92
93 if (sample_type & PERF_SAMPLE_TIME)
94 size += sizeof(data->time);
95
96 if (sample_type & PERF_SAMPLE_ID)
97 size += sizeof(data->id);
98
99 if (sample_type & PERF_SAMPLE_STREAM_ID)
100 size += sizeof(data->stream_id);
101
102 if (sample_type & PERF_SAMPLE_CPU)
103 size += sizeof(data->cpu) * 2;
104out:
105 session->id_hdr_size = size;
106}
107
108void perf_session__update_sample_type(struct perf_session *self) 82void perf_session__update_sample_type(struct perf_session *self)
109{ 83{
110 self->sample_type = perf_evlist__sample_type(self->evlist); 84 self->sample_type = perf_evlist__sample_type(self->evlist);
111 self->sample_size = __perf_evsel__sample_size(self->sample_type); 85 self->sample_size = __perf_evsel__sample_size(self->sample_type);
112 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 86 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
113 perf_session__id_header_size(self); 87 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
88 self->host_machine.id_hdr_size = self->id_hdr_size;
114} 89}
115 90
116int perf_session__create_kernel_maps(struct perf_session *self) 91int perf_session__create_kernel_maps(struct perf_session *self)
@@ -130,7 +105,7 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
130 105
131struct perf_session *perf_session__new(const char *filename, int mode, 106struct perf_session *perf_session__new(const char *filename, int mode,
132 bool force, bool repipe, 107 bool force, bool repipe,
133 struct perf_event_ops *ops) 108 struct perf_tool *tool)
134{ 109{
135 size_t len = filename ? strlen(filename) + 1 : 0; 110 size_t len = filename ? strlen(filename) + 1 : 0;
136 struct perf_session *self = zalloc(sizeof(*self) + len); 111 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -139,9 +114,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
139 goto out; 114 goto out;
140 115
141 memcpy(self->filename, filename, len); 116 memcpy(self->filename, filename, len);
142 self->threads = RB_ROOT;
143 INIT_LIST_HEAD(&self->dead_threads);
144 self->last_match = NULL;
145 /* 117 /*
146 * On 64bit we can mmap the data file in one go. No need for tiny mmap 118 * On 64bit we can mmap the data file in one go. No need for tiny mmap
147 * slices. On 32bit we use 32MB. 119 * slices. On 32bit we use 32MB.
@@ -171,10 +143,10 @@ struct perf_session *perf_session__new(const char *filename, int mode,
171 goto out_delete; 143 goto out_delete;
172 } 144 }
173 145
174 if (ops && ops->ordering_requires_timestamps && 146 if (tool && tool->ordering_requires_timestamps &&
175 ops->ordered_samples && !self->sample_id_all) { 147 tool->ordered_samples && !self->sample_id_all) {
176 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); 148 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
177 ops->ordered_samples = false; 149 tool->ordered_samples = false;
178 } 150 }
179 151
180out: 152out:
@@ -184,17 +156,22 @@ out_delete:
184 return NULL; 156 return NULL;
185} 157}
186 158
187static void perf_session__delete_dead_threads(struct perf_session *self) 159static void machine__delete_dead_threads(struct machine *machine)
188{ 160{
189 struct thread *n, *t; 161 struct thread *n, *t;
190 162
191 list_for_each_entry_safe(t, n, &self->dead_threads, node) { 163 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
192 list_del(&t->node); 164 list_del(&t->node);
193 thread__delete(t); 165 thread__delete(t);
194 } 166 }
195} 167}
196 168
197static void perf_session__delete_threads(struct perf_session *self) 169static void perf_session__delete_dead_threads(struct perf_session *session)
170{
171 machine__delete_dead_threads(&session->host_machine);
172}
173
174static void machine__delete_threads(struct machine *self)
198{ 175{
199 struct rb_node *nd = rb_first(&self->threads); 176 struct rb_node *nd = rb_first(&self->threads);
200 177
@@ -207,6 +184,11 @@ static void perf_session__delete_threads(struct perf_session *self)
207 } 184 }
208} 185}
209 186
187static void perf_session__delete_threads(struct perf_session *session)
188{
189 machine__delete_threads(&session->host_machine);
190}
191
210void perf_session__delete(struct perf_session *self) 192void perf_session__delete(struct perf_session *self)
211{ 193{
212 perf_session__destroy_kernel_maps(self); 194 perf_session__destroy_kernel_maps(self);
@@ -217,7 +199,7 @@ void perf_session__delete(struct perf_session *self)
217 free(self); 199 free(self);
218} 200}
219 201
220void perf_session__remove_thread(struct perf_session *self, struct thread *th) 202void machine__remove_thread(struct machine *self, struct thread *th)
221{ 203{
222 self->last_match = NULL; 204 self->last_match = NULL;
223 rb_erase(&th->rb_node, &self->threads); 205 rb_erase(&th->rb_node, &self->threads);
@@ -236,16 +218,16 @@ static bool symbol__match_parent_regex(struct symbol *sym)
236 return 0; 218 return 0;
237} 219}
238 220
239int perf_session__resolve_callchain(struct perf_session *self, 221int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel,
240 struct thread *thread, 222 struct thread *thread,
241 struct ip_callchain *chain, 223 struct ip_callchain *chain,
242 struct symbol **parent) 224 struct symbol **parent)
243{ 225{
244 u8 cpumode = PERF_RECORD_MISC_USER; 226 u8 cpumode = PERF_RECORD_MISC_USER;
245 unsigned int i; 227 unsigned int i;
246 int err; 228 int err;
247 229
248 callchain_cursor_reset(&self->callchain_cursor); 230 callchain_cursor_reset(&evsel->hists.callchain_cursor);
249 231
250 for (i = 0; i < chain->nr; i++) { 232 for (i = 0; i < chain->nr; i++) {
251 u64 ip; 233 u64 ip;
@@ -272,7 +254,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
272 254
273 al.filtered = false; 255 al.filtered = false;
274 thread__find_addr_location(thread, self, cpumode, 256 thread__find_addr_location(thread, self, cpumode,
275 MAP__FUNCTION, thread->pid, ip, &al, NULL); 257 MAP__FUNCTION, ip, &al, NULL);
276 if (al.sym != NULL) { 258 if (al.sym != NULL) {
277 if (sort__has_parent && !*parent && 259 if (sort__has_parent && !*parent &&
278 symbol__match_parent_regex(al.sym)) 260 symbol__match_parent_regex(al.sym))
@@ -281,7 +263,7 @@ int perf_session__resolve_callchain(struct perf_session *self,
281 break; 263 break;
282 } 264 }
283 265
284 err = callchain_cursor_append(&self->callchain_cursor, 266 err = callchain_cursor_append(&evsel->hists.callchain_cursor,
285 ip, al.map, al.sym); 267 ip, al.map, al.sym);
286 if (err) 268 if (err)
287 return err; 269 return err;
@@ -290,75 +272,91 @@ int perf_session__resolve_callchain(struct perf_session *self,
290 return 0; 272 return 0;
291} 273}
292 274
293static int process_event_synth_stub(union perf_event *event __used, 275static int process_event_synth_tracing_data_stub(union perf_event *event __used,
294 struct perf_session *session __used) 276 struct perf_session *session __used)
277{
278 dump_printf(": unhandled!\n");
279 return 0;
280}
281
282static int process_event_synth_attr_stub(union perf_event *event __used,
283 struct perf_evlist **pevlist __used)
295{ 284{
296 dump_printf(": unhandled!\n"); 285 dump_printf(": unhandled!\n");
297 return 0; 286 return 0;
298} 287}
299 288
300static int process_event_sample_stub(union perf_event *event __used, 289static int process_event_sample_stub(struct perf_tool *tool __used,
290 union perf_event *event __used,
301 struct perf_sample *sample __used, 291 struct perf_sample *sample __used,
302 struct perf_evsel *evsel __used, 292 struct perf_evsel *evsel __used,
303 struct perf_session *session __used) 293 struct machine *machine __used)
304{ 294{
305 dump_printf(": unhandled!\n"); 295 dump_printf(": unhandled!\n");
306 return 0; 296 return 0;
307} 297}
308 298
309static int process_event_stub(union perf_event *event __used, 299static int process_event_stub(struct perf_tool *tool __used,
300 union perf_event *event __used,
310 struct perf_sample *sample __used, 301 struct perf_sample *sample __used,
311 struct perf_session *session __used) 302 struct machine *machine __used)
303{
304 dump_printf(": unhandled!\n");
305 return 0;
306}
307
308static int process_finished_round_stub(struct perf_tool *tool __used,
309 union perf_event *event __used,
310 struct perf_session *perf_session __used)
312{ 311{
313 dump_printf(": unhandled!\n"); 312 dump_printf(": unhandled!\n");
314 return 0; 313 return 0;
315} 314}
316 315
317static int process_finished_round_stub(union perf_event *event __used, 316static int process_event_type_stub(struct perf_tool *tool __used,
318 struct perf_session *session __used, 317 union perf_event *event __used)
319 struct perf_event_ops *ops __used)
320{ 318{
321 dump_printf(": unhandled!\n"); 319 dump_printf(": unhandled!\n");
322 return 0; 320 return 0;
323} 321}
324 322
325static int process_finished_round(union perf_event *event, 323static int process_finished_round(struct perf_tool *tool,
326 struct perf_session *session, 324 union perf_event *event,
327 struct perf_event_ops *ops); 325 struct perf_session *session);
328 326
329static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) 327static void perf_tool__fill_defaults(struct perf_tool *tool)
330{ 328{
331 if (handler->sample == NULL) 329 if (tool->sample == NULL)
332 handler->sample = process_event_sample_stub; 330 tool->sample = process_event_sample_stub;
333 if (handler->mmap == NULL) 331 if (tool->mmap == NULL)
334 handler->mmap = process_event_stub; 332 tool->mmap = process_event_stub;
335 if (handler->comm == NULL) 333 if (tool->comm == NULL)
336 handler->comm = process_event_stub; 334 tool->comm = process_event_stub;
337 if (handler->fork == NULL) 335 if (tool->fork == NULL)
338 handler->fork = process_event_stub; 336 tool->fork = process_event_stub;
339 if (handler->exit == NULL) 337 if (tool->exit == NULL)
340 handler->exit = process_event_stub; 338 tool->exit = process_event_stub;
341 if (handler->lost == NULL) 339 if (tool->lost == NULL)
342 handler->lost = perf_event__process_lost; 340 tool->lost = perf_event__process_lost;
343 if (handler->read == NULL) 341 if (tool->read == NULL)
344 handler->read = process_event_stub; 342 tool->read = process_event_sample_stub;
345 if (handler->throttle == NULL) 343 if (tool->throttle == NULL)
346 handler->throttle = process_event_stub; 344 tool->throttle = process_event_stub;
347 if (handler->unthrottle == NULL) 345 if (tool->unthrottle == NULL)
348 handler->unthrottle = process_event_stub; 346 tool->unthrottle = process_event_stub;
349 if (handler->attr == NULL) 347 if (tool->attr == NULL)
350 handler->attr = process_event_synth_stub; 348 tool->attr = process_event_synth_attr_stub;
351 if (handler->event_type == NULL) 349 if (tool->event_type == NULL)
352 handler->event_type = process_event_synth_stub; 350 tool->event_type = process_event_type_stub;
353 if (handler->tracing_data == NULL) 351 if (tool->tracing_data == NULL)
354 handler->tracing_data = process_event_synth_stub; 352 tool->tracing_data = process_event_synth_tracing_data_stub;
355 if (handler->build_id == NULL) 353 if (tool->build_id == NULL)
356 handler->build_id = process_event_synth_stub; 354 tool->build_id = process_finished_round_stub;
357 if (handler->finished_round == NULL) { 355 if (tool->finished_round == NULL) {
358 if (handler->ordered_samples) 356 if (tool->ordered_samples)
359 handler->finished_round = process_finished_round; 357 tool->finished_round = process_finished_round;
360 else 358 else
361 handler->finished_round = process_finished_round_stub; 359 tool->finished_round = process_finished_round_stub;
362 } 360 }
363} 361}
364 362
@@ -490,11 +488,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
490static int perf_session_deliver_event(struct perf_session *session, 488static int perf_session_deliver_event(struct perf_session *session,
491 union perf_event *event, 489 union perf_event *event,
492 struct perf_sample *sample, 490 struct perf_sample *sample,
493 struct perf_event_ops *ops, 491 struct perf_tool *tool,
494 u64 file_offset); 492 u64 file_offset);
495 493
496static void flush_sample_queue(struct perf_session *s, 494static void flush_sample_queue(struct perf_session *s,
497 struct perf_event_ops *ops) 495 struct perf_tool *tool)
498{ 496{
499 struct ordered_samples *os = &s->ordered_samples; 497 struct ordered_samples *os = &s->ordered_samples;
500 struct list_head *head = &os->samples; 498 struct list_head *head = &os->samples;
@@ -505,7 +503,7 @@ static void flush_sample_queue(struct perf_session *s,
505 unsigned idx = 0, progress_next = os->nr_samples / 16; 503 unsigned idx = 0, progress_next = os->nr_samples / 16;
506 int ret; 504 int ret;
507 505
508 if (!ops->ordered_samples || !limit) 506 if (!tool->ordered_samples || !limit)
509 return; 507 return;
510 508
511 list_for_each_entry_safe(iter, tmp, head, list) { 509 list_for_each_entry_safe(iter, tmp, head, list) {
@@ -516,7 +514,7 @@ static void flush_sample_queue(struct perf_session *s,
516 if (ret) 514 if (ret)
517 pr_err("Can't parse sample, err = %d\n", ret); 515 pr_err("Can't parse sample, err = %d\n", ret);
518 else 516 else
519 perf_session_deliver_event(s, iter->event, &sample, ops, 517 perf_session_deliver_event(s, iter->event, &sample, tool,
520 iter->file_offset); 518 iter->file_offset);
521 519
522 os->last_flush = iter->timestamp; 520 os->last_flush = iter->timestamp;
@@ -578,11 +576,11 @@ static void flush_sample_queue(struct perf_session *s,
578 * Flush every events below timestamp 7 576 * Flush every events below timestamp 7
579 * etc... 577 * etc...
580 */ 578 */
581static int process_finished_round(union perf_event *event __used, 579static int process_finished_round(struct perf_tool *tool,
582 struct perf_session *session, 580 union perf_event *event __used,
583 struct perf_event_ops *ops) 581 struct perf_session *session)
584{ 582{
585 flush_sample_queue(session, ops); 583 flush_sample_queue(session, tool);
586 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; 584 session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
587 585
588 return 0; 586 return 0;
@@ -737,13 +735,26 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
737 callchain__printf(sample); 735 callchain__printf(sample);
738} 736}
739 737
738static struct machine *
739 perf_session__find_machine_for_cpumode(struct perf_session *session,
740 union perf_event *event)
741{
742 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
743
744 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
745 return perf_session__find_machine(session, event->ip.pid);
746
747 return perf_session__find_host_machine(session);
748}
749
740static int perf_session_deliver_event(struct perf_session *session, 750static int perf_session_deliver_event(struct perf_session *session,
741 union perf_event *event, 751 union perf_event *event,
742 struct perf_sample *sample, 752 struct perf_sample *sample,
743 struct perf_event_ops *ops, 753 struct perf_tool *tool,
744 u64 file_offset) 754 u64 file_offset)
745{ 755{
746 struct perf_evsel *evsel; 756 struct perf_evsel *evsel;
757 struct machine *machine;
747 758
748 dump_event(session, event, file_offset, sample); 759 dump_event(session, event, file_offset, sample);
749 760
@@ -765,6 +776,8 @@ static int perf_session_deliver_event(struct perf_session *session,
765 hists__inc_nr_events(&evsel->hists, event->header.type); 776 hists__inc_nr_events(&evsel->hists, event->header.type);
766 } 777 }
767 778
779 machine = perf_session__find_machine_for_cpumode(session, event);
780
768 switch (event->header.type) { 781 switch (event->header.type) {
769 case PERF_RECORD_SAMPLE: 782 case PERF_RECORD_SAMPLE:
770 dump_sample(session, event, sample); 783 dump_sample(session, event, sample);
@@ -772,23 +785,25 @@ static int perf_session_deliver_event(struct perf_session *session,
772 ++session->hists.stats.nr_unknown_id; 785 ++session->hists.stats.nr_unknown_id;
773 return -1; 786 return -1;
774 } 787 }
775 return ops->sample(event, sample, evsel, session); 788 return tool->sample(tool, event, sample, evsel, machine);
776 case PERF_RECORD_MMAP: 789 case PERF_RECORD_MMAP:
777 return ops->mmap(event, sample, session); 790 return tool->mmap(tool, event, sample, machine);
778 case PERF_RECORD_COMM: 791 case PERF_RECORD_COMM:
779 return ops->comm(event, sample, session); 792 return tool->comm(tool, event, sample, machine);
780 case PERF_RECORD_FORK: 793 case PERF_RECORD_FORK:
781 return ops->fork(event, sample, session); 794 return tool->fork(tool, event, sample, machine);
782 case PERF_RECORD_EXIT: 795 case PERF_RECORD_EXIT:
783 return ops->exit(event, sample, session); 796 return tool->exit(tool, event, sample, machine);
784 case PERF_RECORD_LOST: 797 case PERF_RECORD_LOST:
785 return ops->lost(event, sample, session); 798 if (tool->lost == perf_event__process_lost)
799 session->hists.stats.total_lost += event->lost.lost;
800 return tool->lost(tool, event, sample, machine);
786 case PERF_RECORD_READ: 801 case PERF_RECORD_READ:
787 return ops->read(event, sample, session); 802 return tool->read(tool, event, sample, evsel, machine);
788 case PERF_RECORD_THROTTLE: 803 case PERF_RECORD_THROTTLE:
789 return ops->throttle(event, sample, session); 804 return tool->throttle(tool, event, sample, machine);
790 case PERF_RECORD_UNTHROTTLE: 805 case PERF_RECORD_UNTHROTTLE:
791 return ops->unthrottle(event, sample, session); 806 return tool->unthrottle(tool, event, sample, machine);
792 default: 807 default:
793 ++session->hists.stats.nr_unknown_events; 808 ++session->hists.stats.nr_unknown_events;
794 return -1; 809 return -1;
@@ -812,24 +827,29 @@ static int perf_session__preprocess_sample(struct perf_session *session,
812} 827}
813 828
814static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 829static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
815 struct perf_event_ops *ops, u64 file_offset) 830 struct perf_tool *tool, u64 file_offset)
816{ 831{
832 int err;
833
817 dump_event(session, event, file_offset, NULL); 834 dump_event(session, event, file_offset, NULL);
818 835
819 /* These events are processed right away */ 836 /* These events are processed right away */
820 switch (event->header.type) { 837 switch (event->header.type) {
821 case PERF_RECORD_HEADER_ATTR: 838 case PERF_RECORD_HEADER_ATTR:
822 return ops->attr(event, session); 839 err = tool->attr(event, &session->evlist);
840 if (err == 0)
841 perf_session__update_sample_type(session);
842 return err;
823 case PERF_RECORD_HEADER_EVENT_TYPE: 843 case PERF_RECORD_HEADER_EVENT_TYPE:
824 return ops->event_type(event, session); 844 return tool->event_type(tool, event);
825 case PERF_RECORD_HEADER_TRACING_DATA: 845 case PERF_RECORD_HEADER_TRACING_DATA:
826 /* setup for reading amidst mmap */ 846 /* setup for reading amidst mmap */
827 lseek(session->fd, file_offset, SEEK_SET); 847 lseek(session->fd, file_offset, SEEK_SET);
828 return ops->tracing_data(event, session); 848 return tool->tracing_data(event, session);
829 case PERF_RECORD_HEADER_BUILD_ID: 849 case PERF_RECORD_HEADER_BUILD_ID:
830 return ops->build_id(event, session); 850 return tool->build_id(tool, event, session);
831 case PERF_RECORD_FINISHED_ROUND: 851 case PERF_RECORD_FINISHED_ROUND:
832 return ops->finished_round(event, session, ops); 852 return tool->finished_round(tool, event, session);
833 default: 853 default:
834 return -EINVAL; 854 return -EINVAL;
835 } 855 }
@@ -837,7 +857,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
837 857
838static int perf_session__process_event(struct perf_session *session, 858static int perf_session__process_event(struct perf_session *session,
839 union perf_event *event, 859 union perf_event *event,
840 struct perf_event_ops *ops, 860 struct perf_tool *tool,
841 u64 file_offset) 861 u64 file_offset)
842{ 862{
843 struct perf_sample sample; 863 struct perf_sample sample;
@@ -853,7 +873,7 @@ static int perf_session__process_event(struct perf_session *session,
853 hists__inc_nr_events(&session->hists, event->header.type); 873 hists__inc_nr_events(&session->hists, event->header.type);
854 874
855 if (event->header.type >= PERF_RECORD_USER_TYPE_START) 875 if (event->header.type >= PERF_RECORD_USER_TYPE_START)
856 return perf_session__process_user_event(session, event, ops, file_offset); 876 return perf_session__process_user_event(session, event, tool, file_offset);
857 877
858 /* 878 /*
859 * For all kernel events we get the sample data 879 * For all kernel events we get the sample data
@@ -866,14 +886,14 @@ static int perf_session__process_event(struct perf_session *session,
866 if (perf_session__preprocess_sample(session, event, &sample)) 886 if (perf_session__preprocess_sample(session, event, &sample))
867 return 0; 887 return 0;
868 888
869 if (ops->ordered_samples) { 889 if (tool->ordered_samples) {
870 ret = perf_session_queue_event(session, event, &sample, 890 ret = perf_session_queue_event(session, event, &sample,
871 file_offset); 891 file_offset);
872 if (ret != -ETIME) 892 if (ret != -ETIME)
873 return ret; 893 return ret;
874 } 894 }
875 895
876 return perf_session_deliver_event(session, event, &sample, ops, 896 return perf_session_deliver_event(session, event, &sample, tool,
877 file_offset); 897 file_offset);
878} 898}
879 899
@@ -884,6 +904,11 @@ void perf_event_header__bswap(struct perf_event_header *self)
884 self->size = bswap_16(self->size); 904 self->size = bswap_16(self->size);
885} 905}
886 906
907struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
908{
909 return machine__findnew_thread(&session->host_machine, pid);
910}
911
887static struct thread *perf_session__register_idle_thread(struct perf_session *self) 912static struct thread *perf_session__register_idle_thread(struct perf_session *self)
888{ 913{
889 struct thread *thread = perf_session__findnew(self, 0); 914 struct thread *thread = perf_session__findnew(self, 0);
@@ -897,9 +922,9 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
897} 922}
898 923
899static void perf_session__warn_about_errors(const struct perf_session *session, 924static void perf_session__warn_about_errors(const struct perf_session *session,
900 const struct perf_event_ops *ops) 925 const struct perf_tool *tool)
901{ 926{
902 if (ops->lost == perf_event__process_lost && 927 if (tool->lost == perf_event__process_lost &&
903 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) { 928 session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) {
904 ui__warning("Processed %d events and lost %d chunks!\n\n" 929 ui__warning("Processed %d events and lost %d chunks!\n\n"
905 "Check IO/CPU overload!\n\n", 930 "Check IO/CPU overload!\n\n",
@@ -934,7 +959,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
934volatile int session_done; 959volatile int session_done;
935 960
936static int __perf_session__process_pipe_events(struct perf_session *self, 961static int __perf_session__process_pipe_events(struct perf_session *self,
937 struct perf_event_ops *ops) 962 struct perf_tool *tool)
938{ 963{
939 union perf_event event; 964 union perf_event event;
940 uint32_t size; 965 uint32_t size;
@@ -943,7 +968,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
943 int err; 968 int err;
944 void *p; 969 void *p;
945 970
946 perf_event_ops__fill_defaults(ops); 971 perf_tool__fill_defaults(tool);
947 972
948 head = 0; 973 head = 0;
949more: 974more:
@@ -980,7 +1005,7 @@ more:
980 } 1005 }
981 1006
982 if (size == 0 || 1007 if (size == 0 ||
983 (skip = perf_session__process_event(self, &event, ops, head)) < 0) { 1008 (skip = perf_session__process_event(self, &event, tool, head)) < 0) {
984 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1009 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
985 head, event.header.size, event.header.type); 1010 head, event.header.size, event.header.type);
986 /* 1011 /*
@@ -1003,7 +1028,7 @@ more:
1003done: 1028done:
1004 err = 0; 1029 err = 0;
1005out_err: 1030out_err:
1006 perf_session__warn_about_errors(self, ops); 1031 perf_session__warn_about_errors(self, tool);
1007 perf_session_free_sample_buffers(self); 1032 perf_session_free_sample_buffers(self);
1008 return err; 1033 return err;
1009} 1034}
@@ -1034,7 +1059,7 @@ fetch_mmaped_event(struct perf_session *session,
1034 1059
1035int __perf_session__process_events(struct perf_session *session, 1060int __perf_session__process_events(struct perf_session *session,
1036 u64 data_offset, u64 data_size, 1061 u64 data_offset, u64 data_size,
1037 u64 file_size, struct perf_event_ops *ops) 1062 u64 file_size, struct perf_tool *tool)
1038{ 1063{
1039 u64 head, page_offset, file_offset, file_pos, progress_next; 1064 u64 head, page_offset, file_offset, file_pos, progress_next;
1040 int err, mmap_prot, mmap_flags, map_idx = 0; 1065 int err, mmap_prot, mmap_flags, map_idx = 0;
@@ -1043,7 +1068,7 @@ int __perf_session__process_events(struct perf_session *session,
1043 union perf_event *event; 1068 union perf_event *event;
1044 uint32_t size; 1069 uint32_t size;
1045 1070
1046 perf_event_ops__fill_defaults(ops); 1071 perf_tool__fill_defaults(tool);
1047 1072
1048 page_size = sysconf(_SC_PAGESIZE); 1073 page_size = sysconf(_SC_PAGESIZE);
1049 1074
@@ -1098,7 +1123,7 @@ more:
1098 size = event->header.size; 1123 size = event->header.size;
1099 1124
1100 if (size == 0 || 1125 if (size == 0 ||
1101 perf_session__process_event(session, event, ops, file_pos) < 0) { 1126 perf_session__process_event(session, event, tool, file_pos) < 0) {
1102 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n", 1127 dump_printf("%#" PRIx64 " [%#x]: skipping unknown header type: %d\n",
1103 file_offset + head, event->header.size, 1128 file_offset + head, event->header.size,
1104 event->header.type); 1129 event->header.type);
@@ -1127,15 +1152,15 @@ more:
1127 err = 0; 1152 err = 0;
1128 /* do the final flush for ordered samples */ 1153 /* do the final flush for ordered samples */
1129 session->ordered_samples.next_flush = ULLONG_MAX; 1154 session->ordered_samples.next_flush = ULLONG_MAX;
1130 flush_sample_queue(session, ops); 1155 flush_sample_queue(session, tool);
1131out_err: 1156out_err:
1132 perf_session__warn_about_errors(session, ops); 1157 perf_session__warn_about_errors(session, tool);
1133 perf_session_free_sample_buffers(session); 1158 perf_session_free_sample_buffers(session);
1134 return err; 1159 return err;
1135} 1160}
1136 1161
1137int perf_session__process_events(struct perf_session *self, 1162int perf_session__process_events(struct perf_session *self,
1138 struct perf_event_ops *ops) 1163 struct perf_tool *tool)
1139{ 1164{
1140 int err; 1165 int err;
1141 1166
@@ -1146,9 +1171,9 @@ int perf_session__process_events(struct perf_session *self,
1146 err = __perf_session__process_events(self, 1171 err = __perf_session__process_events(self,
1147 self->header.data_offset, 1172 self->header.data_offset,
1148 self->header.data_size, 1173 self->header.data_size,
1149 self->size, ops); 1174 self->size, tool);
1150 else 1175 else
1151 err = __perf_session__process_pipe_events(self, ops); 1176 err = __perf_session__process_pipe_events(self, tool);
1152 1177
1153 return err; 1178 return err;
1154} 1179}
@@ -1163,9 +1188,8 @@ bool perf_session__has_traces(struct perf_session *self, const char *msg)
1163 return true; 1188 return true;
1164} 1189}
1165 1190
1166int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps, 1191int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
1167 const char *symbol_name, 1192 const char *symbol_name, u64 addr)
1168 u64 addr)
1169{ 1193{
1170 char *bracket; 1194 char *bracket;
1171 enum map_type i; 1195 enum map_type i;
@@ -1224,6 +1248,27 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1224 return ret; 1248 return ret;
1225} 1249}
1226 1250
1251size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
1252{
1253 /*
1254 * FIXME: Here we have to actually print all the machines in this
1255 * session, not just the host...
1256 */
1257 return machine__fprintf(&session->host_machine, fp);
1258}
1259
1260void perf_session__remove_thread(struct perf_session *session,
1261 struct thread *th)
1262{
1263 /*
1264 * FIXME: This one makes no sense, we need to remove the thread from
1265 * the machine it belongs to, perf_session can have many machines, so
1266 * doing it always on ->host_machine is wrong. Fix when auditing all
1267 * the 'perf kvm' code.
1268 */
1269 machine__remove_thread(&session->host_machine, th);
1270}
1271
1227struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 1272struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1228 unsigned int type) 1273 unsigned int type)
1229{ 1274{
@@ -1236,17 +1281,16 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1236 return NULL; 1281 return NULL;
1237} 1282}
1238 1283
1239void perf_session__print_ip(union perf_event *event, 1284void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
1240 struct perf_sample *sample, 1285 struct machine *machine, struct perf_evsel *evsel,
1241 struct perf_session *session, 1286 int print_sym, int print_dso)
1242 int print_sym, int print_dso)
1243{ 1287{
1244 struct addr_location al; 1288 struct addr_location al;
1245 const char *symname, *dsoname; 1289 const char *symname, *dsoname;
1246 struct callchain_cursor *cursor = &session->callchain_cursor; 1290 struct callchain_cursor *cursor = &evsel->hists.callchain_cursor;
1247 struct callchain_cursor_node *node; 1291 struct callchain_cursor_node *node;
1248 1292
1249 if (perf_event__preprocess_sample(event, session, &al, sample, 1293 if (perf_event__preprocess_sample(event, machine, &al, sample,
1250 NULL) < 0) { 1294 NULL) < 0) {
1251 error("problem processing %d event, skipping it.\n", 1295 error("problem processing %d event, skipping it.\n",
1252 event->header.type); 1296 event->header.type);
@@ -1255,7 +1299,7 @@ void perf_session__print_ip(union perf_event *event,
1255 1299
1256 if (symbol_conf.use_callchain && sample->callchain) { 1300 if (symbol_conf.use_callchain && sample->callchain) {
1257 1301
1258 if (perf_session__resolve_callchain(session, al.thread, 1302 if (machine__resolve_callchain(machine, evsel, al.thread,
1259 sample->callchain, NULL) != 0) { 1303 sample->callchain, NULL) != 0) {
1260 if (verbose) 1304 if (verbose)
1261 error("Failed to resolve callchain. Skipping\n"); 1305 error("Failed to resolve callchain. Skipping\n");
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6e393c98eb34..30e9c6b6fc3c 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -30,9 +30,6 @@ struct perf_session {
30 struct perf_header header; 30 struct perf_header header;
31 unsigned long size; 31 unsigned long size;
32 unsigned long mmap_window; 32 unsigned long mmap_window;
33 struct rb_root threads;
34 struct list_head dead_threads;
35 struct thread *last_match;
36 struct machine host_machine; 33 struct machine host_machine;
37 struct rb_root machines; 34 struct rb_root machines;
38 struct perf_evlist *evlist; 35 struct perf_evlist *evlist;
@@ -53,65 +50,31 @@ struct perf_session {
53 int cwdlen; 50 int cwdlen;
54 char *cwd; 51 char *cwd;
55 struct ordered_samples ordered_samples; 52 struct ordered_samples ordered_samples;
56 struct callchain_cursor callchain_cursor;
57 char filename[0]; 53 char filename[0];
58}; 54};
59 55
60struct perf_evsel; 56struct perf_tool;
61struct perf_event_ops;
62
63typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample,
64 struct perf_evsel *evsel, struct perf_session *session);
65typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
66 struct perf_session *session);
67typedef int (*event_synth_op)(union perf_event *self,
68 struct perf_session *session);
69typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
70 struct perf_event_ops *ops);
71
72struct perf_event_ops {
73 event_sample sample;
74 event_op mmap,
75 comm,
76 fork,
77 exit,
78 lost,
79 read,
80 throttle,
81 unthrottle;
82 event_synth_op attr,
83 event_type,
84 tracing_data,
85 build_id;
86 event_op2 finished_round;
87 bool ordered_samples;
88 bool ordering_requires_timestamps;
89};
90 57
91struct perf_session *perf_session__new(const char *filename, int mode, 58struct perf_session *perf_session__new(const char *filename, int mode,
92 bool force, bool repipe, 59 bool force, bool repipe,
93 struct perf_event_ops *ops); 60 struct perf_tool *tool);
94void perf_session__delete(struct perf_session *self); 61void perf_session__delete(struct perf_session *self);
95 62
96void perf_event_header__bswap(struct perf_event_header *self); 63void perf_event_header__bswap(struct perf_event_header *self);
97 64
98int __perf_session__process_events(struct perf_session *self, 65int __perf_session__process_events(struct perf_session *self,
99 u64 data_offset, u64 data_size, u64 size, 66 u64 data_offset, u64 data_size, u64 size,
100 struct perf_event_ops *ops); 67 struct perf_tool *tool);
101int perf_session__process_events(struct perf_session *self, 68int perf_session__process_events(struct perf_session *self,
102 struct perf_event_ops *event_ops); 69 struct perf_tool *tool);
103 70
104int perf_session__resolve_callchain(struct perf_session *self, 71int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
105 struct thread *thread, 72 struct thread *thread,
106 struct ip_callchain *chain, 73 struct ip_callchain *chain,
107 struct symbol **parent); 74 struct symbol **parent);
108 75
109bool perf_session__has_traces(struct perf_session *self, const char *msg); 76bool perf_session__has_traces(struct perf_session *self, const char *msg);
110 77
111int perf_session__set_kallsyms_ref_reloc_sym(struct map **maps,
112 const char *symbol_name,
113 u64 addr);
114
115void mem_bswap_64(void *src, int byte_size); 78void mem_bswap_64(void *src, int byte_size);
116void perf_event__attr_swap(struct perf_event_attr *attr); 79void perf_event__attr_swap(struct perf_event_attr *attr);
117 80
@@ -144,12 +107,16 @@ struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t p
144 107
145static inline 108static inline
146void perf_session__process_machines(struct perf_session *self, 109void perf_session__process_machines(struct perf_session *self,
110 struct perf_tool *tool,
147 machine__process_t process) 111 machine__process_t process)
148{ 112{
149 process(&self->host_machine, self); 113 process(&self->host_machine, tool);
150 return machines__process(&self->machines, process, self); 114 return machines__process(&self->machines, process, tool);
151} 115}
152 116
117struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
118size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
119
153size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp); 120size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
154 121
155size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, 122size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
@@ -170,10 +137,9 @@ static inline int perf_session__parse_sample(struct perf_session *session,
170struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 137struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
171 unsigned int type); 138 unsigned int type);
172 139
173void perf_session__print_ip(union perf_event *event, 140void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
174 struct perf_sample *sample, 141 struct machine *machine, struct perf_evsel *evsel,
175 struct perf_session *session, 142 int print_sym, int print_dso);
176 int print_sym, int print_dso);
177 143
178int perf_session__cpu_bitmap(struct perf_session *session, 144int perf_session__cpu_bitmap(struct perf_session *session,
179 const char *cpu_list, unsigned long *cpu_bitmap); 145 const char *cpu_list, unsigned long *cpu_bitmap);
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 95d370074928..36d4c5619575 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -27,7 +27,8 @@ build_tmp = getenv('PYTHON_EXTBUILD_TMP')
27perf = Extension('perf', 27perf = Extension('perf',
28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 28 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 29 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'], 30 'util/util.c', 'util/xyarray.c', 'util/cgroup.c',
31 'util/debugfs.c'],
31 include_dirs = ['util/include'], 32 include_dirs = ['util/include'],
32 extra_compile_args = cflags, 33 extra_compile_args = cflags,
33 ) 34 )
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 29f8d742e92f..123c2e14353e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -68,6 +68,7 @@ struct strlist;
68 68
69struct symbol_conf { 69struct symbol_conf {
70 unsigned short priv_size; 70 unsigned short priv_size;
71 unsigned short nr_events;
71 bool try_vmlinux_path, 72 bool try_vmlinux_path,
72 use_modules, 73 use_modules,
73 sort_by_name, 74 sort_by_name,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index d5d3b22250f3..fb4b7ea6752f 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -61,7 +61,7 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
61 map_groups__fprintf(&self->mg, verbose, fp); 61 map_groups__fprintf(&self->mg, verbose, fp);
62} 62}
63 63
64struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) 64struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
65{ 65{
66 struct rb_node **p = &self->threads.rb_node; 66 struct rb_node **p = &self->threads.rb_node;
67 struct rb_node *parent = NULL; 67 struct rb_node *parent = NULL;
@@ -125,12 +125,12 @@ int thread__fork(struct thread *self, struct thread *parent)
125 return 0; 125 return 0;
126} 126}
127 127
128size_t perf_session__fprintf(struct perf_session *self, FILE *fp) 128size_t machine__fprintf(struct machine *machine, FILE *fp)
129{ 129{
130 size_t ret = 0; 130 size_t ret = 0;
131 struct rb_node *nd; 131 struct rb_node *nd;
132 132
133 for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) { 133 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
134 struct thread *pos = rb_entry(nd, struct thread, rb_node); 134 struct thread *pos = rb_entry(nd, struct thread, rb_node);
135 135
136 ret += thread__fprintf(pos, fp); 136 ret += thread__fprintf(pos, fp);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e5f2401c1b5e..70c2c13ff679 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,16 +18,14 @@ struct thread {
18 int comm_len; 18 int comm_len;
19}; 19};
20 20
21struct perf_session; 21struct machine;
22 22
23void thread__delete(struct thread *self); 23void thread__delete(struct thread *self);
24 24
25int thread__set_comm(struct thread *self, const char *comm); 25int thread__set_comm(struct thread *self, const char *comm);
26int thread__comm_len(struct thread *self); 26int thread__comm_len(struct thread *self);
27struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
28void thread__insert_map(struct thread *self, struct map *map); 27void thread__insert_map(struct thread *self, struct map *map);
29int thread__fork(struct thread *self, struct thread *parent); 28int thread__fork(struct thread *self, struct thread *parent);
30size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
31 29
32static inline struct map *thread__find_map(struct thread *self, 30static inline struct map *thread__find_map(struct thread *self,
33 enum map_type type, u64 addr) 31 enum map_type type, u64 addr)
@@ -35,14 +33,12 @@ static inline struct map *thread__find_map(struct thread *self,
35 return self ? map_groups__find(&self->mg, type, addr) : NULL; 33 return self ? map_groups__find(&self->mg, type, addr) : NULL;
36} 34}
37 35
38void thread__find_addr_map(struct thread *self, 36void thread__find_addr_map(struct thread *thread, struct machine *machine,
39 struct perf_session *session, u8 cpumode, 37 u8 cpumode, enum map_type type, u64 addr,
40 enum map_type type, pid_t pid, u64 addr,
41 struct addr_location *al); 38 struct addr_location *al);
42 39
43void thread__find_addr_location(struct thread *self, 40void thread__find_addr_location(struct thread *thread, struct machine *machine,
44 struct perf_session *session, u8 cpumode, 41 u8 cpumode, enum map_type type, u64 addr,
45 enum map_type type, pid_t pid, u64 addr,
46 struct addr_location *al, 42 struct addr_location *al,
47 symbol_filter_t filter); 43 symbol_filter_t filter);
48#endif /* __PERF_THREAD_H */ 44#endif /* __PERF_THREAD_H */
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
new file mode 100644
index 000000000000..b0e1aadba8d5
--- /dev/null
+++ b/tools/perf/util/tool.h
@@ -0,0 +1,50 @@
1#ifndef __PERF_TOOL_H
2#define __PERF_TOOL_H
3
4#include <stdbool.h>
5
6struct perf_session;
7union perf_event;
8struct perf_evlist;
9struct perf_evsel;
10struct perf_sample;
11struct perf_tool;
12struct machine;
13
14typedef int (*event_sample)(struct perf_tool *tool, union perf_event *event,
15 struct perf_sample *sample,
16 struct perf_evsel *evsel, struct machine *machine);
17
18typedef int (*event_op)(struct perf_tool *tool, union perf_event *event,
19 struct perf_sample *sample, struct machine *machine);
20
21typedef int (*event_attr_op)(union perf_event *event,
22 struct perf_evlist **pevlist);
23typedef int (*event_simple_op)(struct perf_tool *tool, union perf_event *event);
24
25typedef int (*event_synth_op)(union perf_event *event,
26 struct perf_session *session);
27
28typedef int (*event_op2)(struct perf_tool *tool, union perf_event *event,
29 struct perf_session *session);
30
31struct perf_tool {
32 event_sample sample,
33 read;
34 event_op mmap,
35 comm,
36 fork,
37 exit,
38 lost,
39 throttle,
40 unthrottle;
41 event_attr_op attr;
42 event_synth_op tracing_data;
43 event_simple_op event_type;
44 event_op2 finished_round,
45 build_id;
46 bool ordered_samples;
47 bool ordering_requires_timestamps;
48};
49
50#endif /* __PERF_TOOL_H */
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 399650967958..a248f3c2c60d 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -1,15 +1,17 @@
1#ifndef __PERF_TOP_H 1#ifndef __PERF_TOP_H
2#define __PERF_TOP_H 1 2#define __PERF_TOP_H 1
3 3
4#include "tool.h"
4#include "types.h" 5#include "types.h"
5#include "../perf.h"
6#include <stddef.h> 6#include <stddef.h>
7#include <stdbool.h>
7 8
8struct perf_evlist; 9struct perf_evlist;
9struct perf_evsel; 10struct perf_evsel;
10struct perf_session; 11struct perf_session;
11 12
12struct perf_top { 13struct perf_top {
14 struct perf_tool tool;
13 struct perf_evlist *evlist; 15 struct perf_evlist *evlist;
14 /* 16 /*
15 * Symbols will be added here in perf_event__process_sample and will 17 * Symbols will be added here in perf_event__process_sample and will
@@ -23,10 +25,26 @@ struct perf_top {
23 int freq; 25 int freq;
24 pid_t target_pid, target_tid; 26 pid_t target_pid, target_tid;
25 bool hide_kernel_symbols, hide_user_symbols, zero; 27 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool system_wide;
29 bool use_tui, use_stdio;
30 bool sort_has_symbols;
31 bool dont_use_callchains;
32 bool kptr_restrict_warned;
33 bool vmlinux_warned;
34 bool inherit;
35 bool group;
36 bool sample_id_all_avail;
37 bool dump_symtab;
26 const char *cpu_list; 38 const char *cpu_list;
27 struct hist_entry *sym_filter_entry; 39 struct hist_entry *sym_filter_entry;
28 struct perf_evsel *sym_evsel; 40 struct perf_evsel *sym_evsel;
29 struct perf_session *session; 41 struct perf_session *session;
42 struct winsize winsize;
43 unsigned int mmap_pages;
44 int default_interval;
45 int realtime_prio;
46 int sym_pcnt_filter;
47 const char *sym_filter;
30}; 48};
31 49
32size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 50size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/trace-event-info.c b/tools/perf/util/trace-event-info.c
index d2655f08bcc0..ac6830d8292b 100644
--- a/tools/perf/util/trace-event-info.c
+++ b/tools/perf/util/trace-event-info.c
@@ -18,7 +18,8 @@
18 * 18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */ 20 */
21#define _GNU_SOURCE 21#include <ctype.h>
22#include "util.h"
22#include <dirent.h> 23#include <dirent.h>
23#include <mntent.h> 24#include <mntent.h>
24#include <stdio.h> 25#include <stdio.h>
@@ -31,7 +32,6 @@
31#include <pthread.h> 32#include <pthread.h>
32#include <fcntl.h> 33#include <fcntl.h>
33#include <unistd.h> 34#include <unistd.h>
34#include <ctype.h>
35#include <errno.h> 35#include <errno.h>
36#include <stdbool.h> 36#include <stdbool.h>
37#include <linux/list.h> 37#include <linux/list.h>
@@ -44,10 +44,6 @@
44 44
45#define VERSION "0.5" 45#define VERSION "0.5"
46 46
47#define _STR(x) #x
48#define STR(x) _STR(x)
49#define MAX_PATH 256
50
51#define TRACE_CTRL "tracing_on" 47#define TRACE_CTRL "tracing_on"
52#define TRACE "trace" 48#define TRACE "trace"
53#define AVAILABLE "available_tracers" 49#define AVAILABLE "available_tracers"
@@ -73,26 +69,6 @@ struct events {
73}; 69};
74 70
75 71
76
77static void die(const char *fmt, ...)
78{
79 va_list ap;
80 int ret = errno;
81
82 if (errno)
83 perror("perf");
84 else
85 ret = -1;
86
87 va_start(ap, fmt);
88 fprintf(stderr, " ");
89 vfprintf(stderr, fmt, ap);
90 va_end(ap);
91
92 fprintf(stderr, "\n");
93 exit(ret);
94}
95
96void *malloc_or_die(unsigned int size) 72void *malloc_or_die(unsigned int size)
97{ 73{
98 void *data; 74 void *data;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index c9dcbec7d800..a3fdf55f317b 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -39,7 +39,7 @@ static int stop_script_unsupported(void)
39static void process_event_unsupported(union perf_event *event __unused, 39static void process_event_unsupported(union perf_event *event __unused,
40 struct perf_sample *sample __unused, 40 struct perf_sample *sample __unused,
41 struct perf_evsel *evsel __unused, 41 struct perf_evsel *evsel __unused,
42 struct perf_session *session __unused, 42 struct machine *machine __unused,
43 struct thread *thread __unused) 43 struct thread *thread __unused)
44{ 44{
45} 45}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index a84100817649..58ae14c5baac 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,7 +3,11 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "parse-events.h" 5#include "parse-events.h"
6#include "session.h" 6
7struct machine;
8struct perf_sample;
9union perf_event;
10struct thread;
7 11
8#define __unused __attribute__((unused)) 12#define __unused __attribute__((unused))
9 13
@@ -292,7 +296,7 @@ struct scripting_ops {
292 void (*process_event) (union perf_event *event, 296 void (*process_event) (union perf_event *event,
293 struct perf_sample *sample, 297 struct perf_sample *sample,
294 struct perf_evsel *evsel, 298 struct perf_evsel *evsel,
295 struct perf_session *session, 299 struct machine *machine,
296 struct thread *thread); 300 struct thread *thread);
297 int (*generate_script) (const char *outfile); 301 int (*generate_script) (const char *outfile);
298}; 302};
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 0575905d1205..295a9c93f945 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -224,7 +224,7 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser)
224} 224}
225 225
226static int annotate_browser__run(struct annotate_browser *self, int evidx, 226static int annotate_browser__run(struct annotate_browser *self, int evidx,
227 int nr_events, void(*timer)(void *arg), 227 void(*timer)(void *arg),
228 void *arg, int delay_secs) 228 void *arg, int delay_secs)
229{ 229{
230 struct rb_node *nd = NULL; 230 struct rb_node *nd = NULL;
@@ -328,8 +328,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
328 notes = symbol__annotation(target); 328 notes = symbol__annotation(target);
329 pthread_mutex_lock(&notes->lock); 329 pthread_mutex_lock(&notes->lock);
330 330
331 if (notes->src == NULL && 331 if (notes->src == NULL && symbol__alloc_hist(target) < 0) {
332 symbol__alloc_hist(target, nr_events) < 0) {
333 pthread_mutex_unlock(&notes->lock); 332 pthread_mutex_unlock(&notes->lock);
334 ui__warning("Not enough memory for annotating '%s' symbol!\n", 333 ui__warning("Not enough memory for annotating '%s' symbol!\n",
335 target->name); 334 target->name);
@@ -337,7 +336,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
337 } 336 }
338 337
339 pthread_mutex_unlock(&notes->lock); 338 pthread_mutex_unlock(&notes->lock);
340 symbol__tui_annotate(target, ms->map, evidx, nr_events, 339 symbol__tui_annotate(target, ms->map, evidx,
341 timer, arg, delay_secs); 340 timer, arg, delay_secs);
342 } 341 }
343 continue; 342 continue;
@@ -358,15 +357,15 @@ out:
358 return key; 357 return key;
359} 358}
360 359
361int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, 360int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
362 void(*timer)(void *arg), void *arg, int delay_secs) 361 void(*timer)(void *arg), void *arg, int delay_secs)
363{ 362{
364 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events, 363 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx,
365 timer, arg, delay_secs); 364 timer, arg, delay_secs);
366} 365}
367 366
368int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, 367int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
369 int nr_events, void(*timer)(void *arg), void *arg, 368 void(*timer)(void *arg), void *arg,
370 int delay_secs) 369 int delay_secs)
371{ 370{
372 struct objdump_line *pos, *n; 371 struct objdump_line *pos, *n;
@@ -419,8 +418,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
419 browser.b.nr_entries = browser.nr_entries; 418 browser.b.nr_entries = browser.nr_entries;
420 browser.b.entries = &notes->src->source, 419 browser.b.entries = &notes->src->source,
421 browser.b.width += 18; /* Percentage */ 420 browser.b.width += 18; /* Percentage */
422 ret = annotate_browser__run(&browser, evidx, nr_events, 421 ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs);
423 timer, arg, delay_secs);
424 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 422 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
425 list_del(&pos->node); 423 list_del(&pos->node);
426 objdump_line__free(pos); 424 objdump_line__free(pos);
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index d0c94b459685..1212a386a033 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1020,7 +1020,7 @@ do_annotate:
1020 * Don't let this be freed, say, by hists__decay_entry. 1020 * Don't let this be freed, say, by hists__decay_entry.
1021 */ 1021 */
1022 he->used = true; 1022 he->used = true;
1023 err = hist_entry__tui_annotate(he, evsel->idx, nr_events, 1023 err = hist_entry__tui_annotate(he, evsel->idx,
1024 timer, arg, delay_secs); 1024 timer, arg, delay_secs);
1025 he->used = false; 1025 he->used = false;
1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries); 1026 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
diff --git a/tools/perf/util/ui/progress.c b/tools/perf/util/ui/progress.c
index 295e366b6311..13aa64e50e11 100644
--- a/tools/perf/util/ui/progress.c
+++ b/tools/perf/util/ui/progress.c
@@ -14,6 +14,9 @@ void ui_progress__update(u64 curr, u64 total, const char *title)
14 if (use_browser <= 0) 14 if (use_browser <= 0)
15 return; 15 return;
16 16
17 if (total == 0)
18 return;
19
17 ui__refresh_dimensions(true); 20 ui__refresh_dimensions(true);
18 pthread_mutex_lock(&ui__lock); 21 pthread_mutex_lock(&ui__lock);
19 y = SLtt_Screen_Rows / 2 - 2; 22 y = SLtt_Screen_Rows / 2 - 2;