aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2014-10-24 16:26:37 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2014-10-24 16:26:37 -0400
commitdb65bcfd9563a7531c3dd46c350565705be1fd84 (patch)
treeff7b068472764e36ab02a739917e206dd11d6b46 /tools
parentb47dcbdc5161d3d5756f430191e2840d9b855492 (diff)
parentf114040e3ea6e07372334ade75d1ee0775c355e1 (diff)
Merge tag 'v3.18-rc1' into x86/urgent
Reason: Need to apply audit patch on top of v3.18-rc1. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-diff.txt6
-rw-r--r--tools/perf/Documentation/perf-kvm.txt4
-rw-r--r--tools/perf/Documentation/perf-list.txt2
-rw-r--r--tools/perf/Documentation/perf-record.txt2
-rw-r--r--tools/perf/Documentation/perf-script-perl.txt4
-rw-r--r--tools/perf/Documentation/perf-script-python.txt6
-rw-r--r--tools/perf/Documentation/perf-script.txt4
-rw-r--r--tools/perf/Documentation/perf-test.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt2
-rw-r--r--tools/perf/builtin-annotate.c14
-rw-r--r--tools/perf/builtin-diff.c21
-rw-r--r--tools/perf/builtin-kvm.c29
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-report.c31
-rw-r--r--tools/perf/builtin-sched.c3
-rw-r--r--tools/perf/builtin-script.c22
-rw-r--r--tools/perf/builtin-stat.c1
-rw-r--r--tools/perf/builtin-top.c60
-rw-r--r--tools/perf/builtin-trace.c16
-rw-r--r--tools/perf/tests/builtin-test.c5
-rw-r--r--tools/perf/tests/dwarf-unwind.c3
-rw-r--r--tools/perf/tests/hists_cumulate.c8
-rw-r--r--tools/perf/tests/hists_filter.c23
-rw-r--r--tools/perf/tests/hists_link.c23
-rw-r--r--tools/perf/tests/hists_output.c20
-rw-r--r--tools/perf/tests/parse-events.c36
-rw-r--r--tools/perf/ui/browsers/header.c1
-rw-r--r--tools/perf/ui/browsers/hists.c52
-rw-r--r--tools/perf/ui/gtk/hists.c2
-rw-r--r--tools/perf/util/annotate.c8
-rw-r--r--tools/perf/util/callchain.h2
-rw-r--r--tools/perf/util/event.h26
-rw-r--r--tools/perf/util/evlist.c49
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/evsel.c77
-rw-r--r--tools/perf/util/evsel.h17
-rw-r--r--tools/perf/util/hist.c73
-rw-r--r--tools/perf/util/hist.h49
-rw-r--r--tools/perf/util/include/linux/string.h1
-rw-r--r--tools/perf/util/machine.c10
-rw-r--r--tools/perf/util/map.c8
-rw-r--r--tools/perf/util/ordered-events.c49
-rw-r--r--tools/perf/util/ordered-events.h10
-rw-r--r--tools/perf/util/parse-events.c133
-rw-r--r--tools/perf/util/parse-events.h14
-rw-r--r--tools/perf/util/parse-events.l30
-rw-r--r--tools/perf/util/parse-events.y40
-rw-r--r--tools/perf/util/pmu.c10
-rw-r--r--tools/perf/util/pmu.h10
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c1
-rw-r--r--tools/perf/util/session.c28
-rw-r--r--tools/perf/util/session.h1
-rw-r--r--tools/perf/util/sort.c4
-rw-r--r--tools/perf/util/string.c24
-rw-r--r--tools/perf/util/symbol.c8
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/thread.c6
-rw-r--r--tools/perf/util/thread_map.c21
-rw-r--r--tools/perf/util/thread_map.h1
-rw-r--r--tools/perf/util/unwind-libunwind.c37
-rw-r--r--tools/perf/util/unwind.h17
-rw-r--r--tools/perf/util/util.c8
62 files changed, 833 insertions, 347 deletions
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index b3b8abae62b8..e463caa3eb49 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -196,10 +196,10 @@ If specified the 'Weighted diff' column is displayed with value 'd' computed as:
196 196
197 - period being the hist entry period value 197 - period being the hist entry period value
198 198
199 - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option 199 - WEIGHT-A/WEIGHT-B being user supplied weights in the the '-c' option
200 behind ':' separator like '-c wdiff:1,2'. 200 behind ':' separator like '-c wdiff:1,2'.
201 - WIEGHT-A being the weight of the data file 201 - WEIGHT-A being the weight of the data file
202 - WIEGHT-B being the weight of the baseline data file 202 - WEIGHT-B being the weight of the baseline data file
203 203
204SEE ALSO 204SEE ALSO
205-------- 205--------
diff --git a/tools/perf/Documentation/perf-kvm.txt b/tools/perf/Documentation/perf-kvm.txt
index 6e689dc89a2f..6252e776009c 100644
--- a/tools/perf/Documentation/perf-kvm.txt
+++ b/tools/perf/Documentation/perf-kvm.txt
@@ -100,7 +100,7 @@ OPTIONS
100STAT REPORT OPTIONS 100STAT REPORT OPTIONS
101------------------- 101-------------------
102--vcpu=<value>:: 102--vcpu=<value>::
103 analyze events which occures on this vcpu. (default: all vcpus) 103 analyze events which occur on this vcpu. (default: all vcpus)
104 104
105--event=<value>:: 105--event=<value>::
106 event to be analyzed. Possible values: vmexit, mmio (x86 only), 106 event to be analyzed. Possible values: vmexit, mmio (x86 only),
@@ -134,7 +134,7 @@ STAT LIVE OPTIONS
134 Analyze events only for given process ID(s) (comma separated list). 134 Analyze events only for given process ID(s) (comma separated list).
135 135
136--vcpu=<value>:: 136--vcpu=<value>::
137 analyze events which occures on this vcpu. (default: all vcpus) 137 analyze events which occur on this vcpu. (default: all vcpus)
138 138
139 139
140--event=<value>:: 140--event=<value>::
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 6fce6a622206..cbb4f743d921 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -19,7 +19,7 @@ various perf commands with the -e option.
19EVENT MODIFIERS 19EVENT MODIFIERS
20--------------- 20---------------
21 21
22Events can optionally have a modifer by appending a colon and one or 22Events can optionally have a modifier by appending a colon and one or
23more modifiers. Modifiers allow the user to restrict the events to be 23more modifiers. Modifiers allow the user to restrict the events to be
24counted. The following modifiers exist: 24counted. The following modifiers exist:
25 25
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index d460049cae8e..398f8d53bd6d 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -146,7 +146,7 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
146 146
147-N:: 147-N::
148--no-buildid-cache:: 148--no-buildid-cache::
149Do not update the builid cache. This saves some overhead in situations 149Do not update the buildid cache. This saves some overhead in situations
150where the information in the perf.data file (which includes buildids) 150where the information in the perf.data file (which includes buildids)
151is sufficient. 151is sufficient.
152 152
diff --git a/tools/perf/Documentation/perf-script-perl.txt b/tools/perf/Documentation/perf-script-perl.txt
index d00bef231340..dfbb506d2c34 100644
--- a/tools/perf/Documentation/perf-script-perl.txt
+++ b/tools/perf/Documentation/perf-script-perl.txt
@@ -181,8 +181,8 @@ strings for flag and symbolic fields. These correspond to the strings
181and values parsed from the 'print fmt' fields of the event format 181and values parsed from the 'print fmt' fields of the event format
182files: 182files:
183 183
184 flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name 184 flag_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the flag field $field_name of event $event_name
185 symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name 185 symbol_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the symbolic field $field_name of event $event_name
186 186
187Perf::Trace::Context Module 187Perf::Trace::Context Module
188~~~~~~~~~~~~~~~~~~~~~~~~~~~ 188~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tools/perf/Documentation/perf-script-python.txt b/tools/perf/Documentation/perf-script-python.txt
index 9f1f054b8432..54acba221558 100644
--- a/tools/perf/Documentation/perf-script-python.txt
+++ b/tools/perf/Documentation/perf-script-python.txt
@@ -263,7 +263,7 @@ and having the counts we've tallied as values.
263 263
264The print_syscall_totals() function iterates over the entries in the 264The print_syscall_totals() function iterates over the entries in the
265dictionary and displays a line for each entry containing the syscall 265dictionary and displays a line for each entry containing the syscall
266name (the dictonary keys contain the syscall ids, which are passed to 266name (the dictionary keys contain the syscall ids, which are passed to
267the Util function syscall_name(), which translates the raw syscall 267the Util function syscall_name(), which translates the raw syscall
268numbers to the corresponding syscall name strings). The output is 268numbers to the corresponding syscall name strings). The output is
269displayed after all the events in the trace have been processed, by 269displayed after all the events in the trace have been processed, by
@@ -576,8 +576,8 @@ strings for flag and symbolic fields. These correspond to the strings
576and values parsed from the 'print fmt' fields of the event format 576and values parsed from the 'print fmt' fields of the event format
577files: 577files:
578 578
579 flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name 579 flag_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the flag field field_name of event event_name
580 symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name 580 symbol_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the symbolic field field_name of event event_name
581 581
582The *autodict* function returns a special kind of Python 582The *autodict* function returns a special kind of Python
583dictionary that implements Perl's 'autovivifying' hashes in Python 583dictionary that implements Perl's 'autovivifying' hashes in Python
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 05f9a0a6784c..21494806c0ab 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,7 @@ OPTIONS
115-f:: 115-f::
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline. 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline, period.
119 Field list can be prepended with the type, trace, sw or hw, 119 Field list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
@@ -140,7 +140,7 @@ OPTIONS
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternativey, consider the order: 143 Alternatively, consider the order:
144 144
145 -f comm,tid,time,ip,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index d1d3e5121f89..31a5c3ea7f74 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -25,7 +25,7 @@ OPTIONS
25------- 25-------
26-s:: 26-s::
27--skip:: 27--skip::
28 Tests to skip (comma separater numeric list). 28 Tests to skip (comma separated numeric list).
29 29
30-v:: 30-v::
31--verbose:: 31--verbose::
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 02aac831bdd9..7e1b1f2bb83c 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -20,7 +20,7 @@ scheduling events, etc.
20This is a live mode tool in addition to working with perf.data files like 20This is a live mode tool in addition to working with perf.data files like
21the other perf tools. Files can be generated using the 'perf record' command 21the other perf tools. Files can be generated using the 'perf record' command
22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*'). 22but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
23Alernatively, the 'perf trace record' can be used as a shortcut to 23Alternatively, 'perf trace record' can be used as a shortcut to
24automatically include the raw_syscalls events when writing events to a file. 24automatically include the raw_syscalls events when writing events to a file.
25 25
26The following options apply to perf trace; options to perf trace record are 26The following options apply to perf trace; options to perf trace record are
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index be5939418425..e7417fe97a97 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -51,6 +51,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
51 struct addr_location *al, 51 struct addr_location *al,
52 struct perf_annotate *ann) 52 struct perf_annotate *ann)
53{ 53{
54 struct hists *hists = evsel__hists(evsel);
54 struct hist_entry *he; 55 struct hist_entry *he;
55 int ret; 56 int ret;
56 57
@@ -66,13 +67,12 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
66 return 0; 67 return 0;
67 } 68 }
68 69
69 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0, 70 he = __hists__add_entry(hists, al, NULL, NULL, NULL, 1, 1, 0, true);
70 true);
71 if (he == NULL) 71 if (he == NULL)
72 return -ENOMEM; 72 return -ENOMEM;
73 73
74 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr); 74 ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
75 hists__inc_nr_samples(&evsel->hists, true); 75 hists__inc_nr_samples(hists, true);
76 return ret; 76 return ret;
77} 77}
78 78
@@ -214,6 +214,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
214 214
215 if (dump_trace) { 215 if (dump_trace) {
216 perf_session__fprintf_nr_events(session, stdout); 216 perf_session__fprintf_nr_events(session, stdout);
217 perf_evlist__fprintf_nr_events(session->evlist, stdout);
217 goto out; 218 goto out;
218 } 219 }
219 220
@@ -225,7 +226,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
225 226
226 total_nr_samples = 0; 227 total_nr_samples = 0;
227 evlist__for_each(session->evlist, pos) { 228 evlist__for_each(session->evlist, pos) {
228 struct hists *hists = &pos->hists; 229 struct hists *hists = evsel__hists(pos);
229 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 230 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
230 231
231 if (nr_samples > 0) { 232 if (nr_samples > 0) {
@@ -325,7 +326,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
325 "Show event group information together"), 326 "Show event group information together"),
326 OPT_END() 327 OPT_END()
327 }; 328 };
328 int ret; 329 int ret = hists__init();
330
331 if (ret < 0)
332 return ret;
329 333
330 argc = parse_options(argc, argv, options, annotate_usage, 0); 334 argc = parse_options(argc, argv, options, annotate_usage, 0);
331 335
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index a3ce19f7aebd..8c5c11ca8c53 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -327,6 +327,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
327 struct machine *machine) 327 struct machine *machine)
328{ 328{
329 struct addr_location al; 329 struct addr_location al;
330 struct hists *hists = evsel__hists(evsel);
330 331
331 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { 332 if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) {
332 pr_warning("problem processing %d event, skipping it.\n", 333 pr_warning("problem processing %d event, skipping it.\n",
@@ -334,7 +335,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
334 return -1; 335 return -1;
335 } 336 }
336 337
337 if (hists__add_entry(&evsel->hists, &al, sample->period, 338 if (hists__add_entry(hists, &al, sample->period,
338 sample->weight, sample->transaction)) { 339 sample->weight, sample->transaction)) {
339 pr_warning("problem incrementing symbol period, skipping event\n"); 340 pr_warning("problem incrementing symbol period, skipping event\n");
340 return -1; 341 return -1;
@@ -346,9 +347,9 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
346 * hists__output_resort() and precompute needs the total 347 * hists__output_resort() and precompute needs the total
347 * period in order to sort entries by percentage delta. 348 * period in order to sort entries by percentage delta.
348 */ 349 */
349 evsel->hists.stats.total_period += sample->period; 350 hists->stats.total_period += sample->period;
350 if (!al.filtered) 351 if (!al.filtered)
351 evsel->hists.stats.total_non_filtered_period += sample->period; 352 hists->stats.total_non_filtered_period += sample->period;
352 353
353 return 0; 354 return 0;
354} 355}
@@ -382,7 +383,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
382 struct perf_evsel *evsel; 383 struct perf_evsel *evsel;
383 384
384 evlist__for_each(evlist, evsel) { 385 evlist__for_each(evlist, evsel) {
385 struct hists *hists = &evsel->hists; 386 struct hists *hists = evsel__hists(evsel);
386 387
387 hists__collapse_resort(hists, NULL); 388 hists__collapse_resort(hists, NULL);
388 } 389 }
@@ -631,24 +632,26 @@ static void data_process(void)
631 bool first = true; 632 bool first = true;
632 633
633 evlist__for_each(evlist_base, evsel_base) { 634 evlist__for_each(evlist_base, evsel_base) {
635 struct hists *hists_base = evsel__hists(evsel_base);
634 struct data__file *d; 636 struct data__file *d;
635 int i; 637 int i;
636 638
637 data__for_each_file_new(i, d) { 639 data__for_each_file_new(i, d) {
638 struct perf_evlist *evlist = d->session->evlist; 640 struct perf_evlist *evlist = d->session->evlist;
639 struct perf_evsel *evsel; 641 struct perf_evsel *evsel;
642 struct hists *hists;
640 643
641 evsel = evsel_match(evsel_base, evlist); 644 evsel = evsel_match(evsel_base, evlist);
642 if (!evsel) 645 if (!evsel)
643 continue; 646 continue;
644 647
645 d->hists = &evsel->hists; 648 hists = evsel__hists(evsel);
649 d->hists = hists;
646 650
647 hists__match(&evsel_base->hists, &evsel->hists); 651 hists__match(hists_base, hists);
648 652
649 if (!show_baseline_only) 653 if (!show_baseline_only)
650 hists__link(&evsel_base->hists, 654 hists__link(hists_base, hists);
651 &evsel->hists);
652 } 655 }
653 656
654 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n", 657 fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
@@ -659,7 +662,7 @@ static void data_process(void)
659 if (verbose || data__files_cnt > 2) 662 if (verbose || data__files_cnt > 2)
660 data__fprintf(); 663 data__fprintf();
661 664
662 hists__process(&evsel_base->hists); 665 hists__process(hists_base);
663 } 666 }
664} 667}
665 668
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index d8bf2271f4ea..b65eb0507b38 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -376,7 +376,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
376 struct perf_sample *sample) 376 struct perf_sample *sample)
377{ 377{
378 /* Only kvm_entry records vcpu id. */ 378 /* Only kvm_entry records vcpu id. */
379 if (!thread->priv && kvm_entry_event(evsel)) { 379 if (!thread__priv(thread) && kvm_entry_event(evsel)) {
380 struct vcpu_event_record *vcpu_record; 380 struct vcpu_event_record *vcpu_record;
381 381
382 vcpu_record = zalloc(sizeof(*vcpu_record)); 382 vcpu_record = zalloc(sizeof(*vcpu_record));
@@ -386,10 +386,10 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
386 } 386 }
387 387
388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); 388 vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
389 thread->priv = vcpu_record; 389 thread__set_priv(thread, vcpu_record);
390 } 390 }
391 391
392 return thread->priv; 392 return thread__priv(thread);
393} 393}
394 394
395static bool handle_kvm_event(struct perf_kvm_stat *kvm, 395static bool handle_kvm_event(struct perf_kvm_stat *kvm,
@@ -896,8 +896,7 @@ static int perf_kvm__handle_stdin(void)
896 896
897static int kvm_events_live_report(struct perf_kvm_stat *kvm) 897static int kvm_events_live_report(struct perf_kvm_stat *kvm)
898{ 898{
899 struct pollfd *pollfds = NULL; 899 int nr_stdin, ret, err = -EINVAL;
900 int nr_fds, nr_stdin, ret, err = -EINVAL;
901 struct termios save; 900 struct termios save;
902 901
903 /* live flag must be set first */ 902 /* live flag must be set first */
@@ -919,34 +918,27 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
919 signal(SIGINT, sig_handler); 918 signal(SIGINT, sig_handler);
920 signal(SIGTERM, sig_handler); 919 signal(SIGTERM, sig_handler);
921 920
922 /* use pollfds -- need to add timerfd and stdin */
923 nr_fds = kvm->evlist->pollfd.nr;
924
925 /* add timer fd */ 921 /* add timer fd */
926 if (perf_kvm__timerfd_create(kvm) < 0) { 922 if (perf_kvm__timerfd_create(kvm) < 0) {
927 err = -1; 923 err = -1;
928 goto out; 924 goto out;
929 } 925 }
930 926
931 if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd)) 927 if (perf_evlist__add_pollfd(kvm->evlist, kvm->timerfd) < 0)
932 goto out; 928 goto out;
933 929
934 nr_fds++; 930 nr_stdin = perf_evlist__add_pollfd(kvm->evlist, fileno(stdin));
935 931 if (nr_stdin < 0)
936 if (perf_evlist__add_pollfd(kvm->evlist, fileno(stdin)))
937 goto out; 932 goto out;
938 933
939 nr_stdin = nr_fds;
940 nr_fds++;
941 if (fd_set_nonblock(fileno(stdin)) != 0) 934 if (fd_set_nonblock(fileno(stdin)) != 0)
942 goto out; 935 goto out;
943 936
944 pollfds = kvm->evlist->pollfd.entries;
945
946 /* everything is good - enable the events and process */ 937 /* everything is good - enable the events and process */
947 perf_evlist__enable(kvm->evlist); 938 perf_evlist__enable(kvm->evlist);
948 939
949 while (!done) { 940 while (!done) {
941 struct fdarray *fda = &kvm->evlist->pollfd;
950 int rc; 942 int rc;
951 943
952 rc = perf_kvm__mmap_read(kvm); 944 rc = perf_kvm__mmap_read(kvm);
@@ -957,11 +949,11 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)
957 if (err) 949 if (err)
958 goto out; 950 goto out;
959 951
960 if (pollfds[nr_stdin].revents & POLLIN) 952 if (fda->entries[nr_stdin].revents & POLLIN)
961 done = perf_kvm__handle_stdin(); 953 done = perf_kvm__handle_stdin();
962 954
963 if (!rc && !done) 955 if (!rc && !done)
964 err = poll(pollfds, nr_fds, 100); 956 err = fdarray__poll(fda, 100);
965 } 957 }
966 958
967 perf_evlist__disable(kvm->evlist); 959 perf_evlist__disable(kvm->evlist);
@@ -1366,6 +1358,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1366 } 1358 }
1367 kvm->session->evlist = kvm->evlist; 1359 kvm->session->evlist = kvm->evlist;
1368 perf_session__set_id_hdr_size(kvm->session); 1360 perf_session__set_id_hdr_size(kvm->session);
1361 ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
1369 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target, 1362 machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
1370 kvm->evlist->threads, false); 1363 kvm->evlist->threads, false);
1371 err = kvm_live_open_events(kvm); 1364 err = kvm_live_open_events(kvm);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 44c6f3d55ce7..2583a9b04317 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -14,6 +14,8 @@
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16 16
17#include "util/callchain.h"
18#include "util/cgroup.h"
17#include "util/header.h" 19#include "util/header.h"
18#include "util/event.h" 20#include "util/event.h"
19#include "util/evlist.h" 21#include "util/evlist.h"
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index ac145fae0521..140a6cd88351 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -257,6 +257,13 @@ static int report__setup_sample_type(struct report *rep)
257 } 257 }
258 } 258 }
259 259
260 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
261 if ((sample_type & PERF_SAMPLE_REGS_USER) &&
262 (sample_type & PERF_SAMPLE_STACK_USER))
263 callchain_param.record_mode = CALLCHAIN_DWARF;
264 else
265 callchain_param.record_mode = CALLCHAIN_FP;
266 }
260 return 0; 267 return 0;
261} 268}
262 269
@@ -288,12 +295,14 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
288 evname = buf; 295 evname = buf;
289 296
290 for_each_group_member(pos, evsel) { 297 for_each_group_member(pos, evsel) {
298 const struct hists *pos_hists = evsel__hists(pos);
299
291 if (symbol_conf.filter_relative) { 300 if (symbol_conf.filter_relative) {
292 nr_samples += pos->hists.stats.nr_non_filtered_samples; 301 nr_samples += pos_hists->stats.nr_non_filtered_samples;
293 nr_events += pos->hists.stats.total_non_filtered_period; 302 nr_events += pos_hists->stats.total_non_filtered_period;
294 } else { 303 } else {
295 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 304 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
296 nr_events += pos->hists.stats.total_period; 305 nr_events += pos_hists->stats.total_period;
297 } 306 }
298 } 307 }
299 } 308 }
@@ -318,7 +327,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
318 struct perf_evsel *pos; 327 struct perf_evsel *pos;
319 328
320 evlist__for_each(evlist, pos) { 329 evlist__for_each(evlist, pos) {
321 struct hists *hists = &pos->hists; 330 struct hists *hists = evsel__hists(pos);
322 const char *evname = perf_evsel__name(pos); 331 const char *evname = perf_evsel__name(pos);
323 332
324 if (symbol_conf.event_group && 333 if (symbol_conf.event_group &&
@@ -427,7 +436,7 @@ static void report__collapse_hists(struct report *rep)
427 ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); 436 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
428 437
429 evlist__for_each(rep->session->evlist, pos) { 438 evlist__for_each(rep->session->evlist, pos) {
430 struct hists *hists = &pos->hists; 439 struct hists *hists = evsel__hists(pos);
431 440
432 if (pos->idx == 0) 441 if (pos->idx == 0)
433 hists->symbol_filter_str = rep->symbol_filter_str; 442 hists->symbol_filter_str = rep->symbol_filter_str;
@@ -437,7 +446,7 @@ static void report__collapse_hists(struct report *rep)
437 /* Non-group events are considered as leader */ 446 /* Non-group events are considered as leader */
438 if (symbol_conf.event_group && 447 if (symbol_conf.event_group &&
439 !perf_evsel__is_group_leader(pos)) { 448 !perf_evsel__is_group_leader(pos)) {
440 struct hists *leader_hists = &pos->leader->hists; 449 struct hists *leader_hists = evsel__hists(pos->leader);
441 450
442 hists__match(leader_hists, hists); 451 hists__match(leader_hists, hists);
443 hists__link(leader_hists, hists); 452 hists__link(leader_hists, hists);
@@ -485,6 +494,7 @@ static int __cmd_report(struct report *rep)
485 494
486 if (dump_trace) { 495 if (dump_trace) {
487 perf_session__fprintf_nr_events(session, stdout); 496 perf_session__fprintf_nr_events(session, stdout);
497 perf_evlist__fprintf_nr_events(session->evlist, stdout);
488 return 0; 498 return 0;
489 } 499 }
490 } 500 }
@@ -500,7 +510,7 @@ static int __cmd_report(struct report *rep)
500 } 510 }
501 511
502 evlist__for_each(session->evlist, pos) 512 evlist__for_each(session->evlist, pos)
503 hists__output_resort(&pos->hists); 513 hists__output_resort(evsel__hists(pos));
504 514
505 return report__browse_hists(rep); 515 return report__browse_hists(rep);
506} 516}
@@ -565,7 +575,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
565 struct stat st; 575 struct stat st;
566 bool has_br_stack = false; 576 bool has_br_stack = false;
567 int branch_mode = -1; 577 int branch_mode = -1;
568 int ret = -1;
569 char callchain_default_opt[] = "fractal,0.5,callee"; 578 char callchain_default_opt[] = "fractal,0.5,callee";
570 const char * const report_usage[] = { 579 const char * const report_usage[] = {
571 "perf report [<options>]", 580 "perf report [<options>]",
@@ -692,6 +701,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
692 struct perf_data_file file = { 701 struct perf_data_file file = {
693 .mode = PERF_DATA_MODE_READ, 702 .mode = PERF_DATA_MODE_READ,
694 }; 703 };
704 int ret = hists__init();
705
706 if (ret < 0)
707 return ret;
695 708
696 perf_config(report__config, &report); 709 perf_config(report__config, &report);
697 710
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 9c9287fbf8e9..891c3930080e 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1431,9 +1431,6 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1431{ 1431{
1432 int err = 0; 1432 int err = 0;
1433 1433
1434 evsel->hists.stats.total_period += sample->period;
1435 hists__inc_nr_samples(&evsel->hists, true);
1436
1437 if (evsel->handler != NULL) { 1434 if (evsel->handler != NULL) {
1438 tracepoint_handler f = evsel->handler; 1435 tracepoint_handler f = evsel->handler;
1439 err = f(tool, evsel, sample, machine); 1436 err = f(tool, evsel, sample, machine);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index b9b9e58a6c39..9708a1290571 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -44,6 +44,7 @@ enum perf_output_field {
44 PERF_OUTPUT_ADDR = 1U << 10, 44 PERF_OUTPUT_ADDR = 1U << 10,
45 PERF_OUTPUT_SYMOFFSET = 1U << 11, 45 PERF_OUTPUT_SYMOFFSET = 1U << 11,
46 PERF_OUTPUT_SRCLINE = 1U << 12, 46 PERF_OUTPUT_SRCLINE = 1U << 12,
47 PERF_OUTPUT_PERIOD = 1U << 13,
47}; 48};
48 49
49struct output_option { 50struct output_option {
@@ -63,6 +64,7 @@ struct output_option {
63 {.str = "addr", .field = PERF_OUTPUT_ADDR}, 64 {.str = "addr", .field = PERF_OUTPUT_ADDR},
64 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET}, 65 {.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
65 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 66 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
67 {.str = "period", .field = PERF_OUTPUT_PERIOD},
66}; 68};
67 69
68/* default set to maintain compatibility with current format */ 70/* default set to maintain compatibility with current format */
@@ -80,7 +82,8 @@ static struct {
80 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 82 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
81 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 83 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
82 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 84 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
83 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 85 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
86 PERF_OUTPUT_PERIOD,
84 87
85 .invalid_fields = PERF_OUTPUT_TRACE, 88 .invalid_fields = PERF_OUTPUT_TRACE,
86 }, 89 },
@@ -91,7 +94,8 @@ static struct {
91 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 94 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
92 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 95 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
93 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 96 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
94 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 97 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
98 PERF_OUTPUT_PERIOD,
95 99
96 .invalid_fields = PERF_OUTPUT_TRACE, 100 .invalid_fields = PERF_OUTPUT_TRACE,
97 }, 101 },
@@ -110,7 +114,8 @@ static struct {
110 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 114 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
111 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 115 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
112 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP | 116 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
113 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO, 117 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
118 PERF_OUTPUT_PERIOD,
114 119
115 .invalid_fields = PERF_OUTPUT_TRACE, 120 .invalid_fields = PERF_OUTPUT_TRACE,
116 }, 121 },
@@ -229,6 +234,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
229 PERF_OUTPUT_CPU)) 234 PERF_OUTPUT_CPU))
230 return -EINVAL; 235 return -EINVAL;
231 236
237 if (PRINT_FIELD(PERIOD) &&
238 perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
239 PERF_OUTPUT_PERIOD))
240 return -EINVAL;
241
232 return 0; 242 return 0;
233} 243}
234 244
@@ -448,6 +458,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
448 458
449 print_sample_start(sample, thread, evsel); 459 print_sample_start(sample, thread, evsel);
450 460
461 if (PRINT_FIELD(PERIOD))
462 printf("%10" PRIu64 " ", sample->period);
463
451 if (PRINT_FIELD(EVNAME)) { 464 if (PRINT_FIELD(EVNAME)) {
452 const char *evname = perf_evsel__name(evsel); 465 const char *evname = perf_evsel__name(evsel);
453 printf("%s: ", evname ? evname : "[unknown]"); 466 printf("%s: ", evname ? evname : "[unknown]");
@@ -572,7 +585,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
572 585
573 scripting_ops->process_event(event, sample, evsel, thread, &al); 586 scripting_ops->process_event(event, sample, evsel, thread, &al);
574 587
575 evsel->hists.stats.total_period += sample->period;
576 return 0; 588 return 0;
577} 589}
578 590
@@ -1544,7 +1556,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1544 "comma separated output fields prepend with 'type:'. " 1556 "comma separated output fields prepend with 'type:'. "
1545 "Valid types: hw,sw,trace,raw. " 1557 "Valid types: hw,sw,trace,raw. "
1546 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1558 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
1547 "addr,symoff", parse_output_fields), 1559 "addr,symoff,period", parse_output_fields),
1548 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1560 OPT_BOOLEAN('a', "all-cpus", &system_wide,
1549 "system-wide collection from all CPUs"), 1561 "system-wide collection from all CPUs"),
1550 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 1562 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b22c62f80078..055ce9232c9e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,6 +43,7 @@
43 43
44#include "perf.h" 44#include "perf.h"
45#include "builtin.h" 45#include "builtin.h"
46#include "util/cgroup.h"
46#include "util/util.h" 47#include "util/util.h"
47#include "util/parse-options.h" 48#include "util/parse-options.h"
48#include "util/parse-events.h" 49#include "util/parse-events.h"
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fc3d55f832ac..0aa7747ff139 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -251,6 +251,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
251 char bf[160]; 251 char bf[160];
252 int printed = 0; 252 int printed = 0;
253 const int win_width = top->winsize.ws_col - 1; 253 const int win_width = top->winsize.ws_col - 1;
254 struct hists *hists = evsel__hists(top->sym_evsel);
254 255
255 puts(CONSOLE_CLEAR); 256 puts(CONSOLE_CLEAR);
256 257
@@ -261,13 +262,13 @@ static void perf_top__print_sym_table(struct perf_top *top)
261 262
262 printf("%-*.*s\n", win_width, win_width, graph_dotted_line); 263 printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
263 264
264 if (top->sym_evsel->hists.stats.nr_lost_warned != 265 if (hists->stats.nr_lost_warned !=
265 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) { 266 hists->stats.nr_events[PERF_RECORD_LOST]) {
266 top->sym_evsel->hists.stats.nr_lost_warned = 267 hists->stats.nr_lost_warned =
267 top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 268 hists->stats.nr_events[PERF_RECORD_LOST];
268 color_fprintf(stdout, PERF_COLOR_RED, 269 color_fprintf(stdout, PERF_COLOR_RED,
269 "WARNING: LOST %d chunks, Check IO/CPU overload", 270 "WARNING: LOST %d chunks, Check IO/CPU overload",
270 top->sym_evsel->hists.stats.nr_lost_warned); 271 hists->stats.nr_lost_warned);
271 ++printed; 272 ++printed;
272 } 273 }
273 274
@@ -277,21 +278,18 @@ static void perf_top__print_sym_table(struct perf_top *top)
277 } 278 }
278 279
279 if (top->zero) { 280 if (top->zero) {
280 hists__delete_entries(&top->sym_evsel->hists); 281 hists__delete_entries(hists);
281 } else { 282 } else {
282 hists__decay_entries(&top->sym_evsel->hists, 283 hists__decay_entries(hists, top->hide_user_symbols,
283 top->hide_user_symbols,
284 top->hide_kernel_symbols); 284 top->hide_kernel_symbols);
285 } 285 }
286 286
287 hists__collapse_resort(&top->sym_evsel->hists, NULL); 287 hists__collapse_resort(hists, NULL);
288 hists__output_resort(&top->sym_evsel->hists); 288 hists__output_resort(hists);
289 289
290 hists__output_recalc_col_len(&top->sym_evsel->hists, 290 hists__output_recalc_col_len(hists, top->print_entries - printed);
291 top->print_entries - printed);
292 putchar('\n'); 291 putchar('\n');
293 hists__fprintf(&top->sym_evsel->hists, false, 292 hists__fprintf(hists, false, top->print_entries - printed, win_width,
294 top->print_entries - printed, win_width,
295 top->min_percent, stdout); 293 top->min_percent, stdout);
296} 294}
297 295
@@ -334,6 +332,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
334{ 332{
335 char *buf = malloc(0), *p; 333 char *buf = malloc(0), *p;
336 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL; 334 struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
335 struct hists *hists = evsel__hists(top->sym_evsel);
337 struct rb_node *next; 336 struct rb_node *next;
338 size_t dummy = 0; 337 size_t dummy = 0;
339 338
@@ -351,7 +350,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
351 if (p) 350 if (p)
352 *p = 0; 351 *p = 0;
353 352
354 next = rb_first(&top->sym_evsel->hists.entries); 353 next = rb_first(&hists->entries);
355 while (next) { 354 while (next) {
356 n = rb_entry(next, struct hist_entry, rb_node); 355 n = rb_entry(next, struct hist_entry, rb_node);
357 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) { 356 if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
@@ -538,21 +537,24 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
538static void perf_top__sort_new_samples(void *arg) 537static void perf_top__sort_new_samples(void *arg)
539{ 538{
540 struct perf_top *t = arg; 539 struct perf_top *t = arg;
540 struct hists *hists;
541
541 perf_top__reset_sample_counters(t); 542 perf_top__reset_sample_counters(t);
542 543
543 if (t->evlist->selected != NULL) 544 if (t->evlist->selected != NULL)
544 t->sym_evsel = t->evlist->selected; 545 t->sym_evsel = t->evlist->selected;
545 546
547 hists = evsel__hists(t->sym_evsel);
548
546 if (t->zero) { 549 if (t->zero) {
547 hists__delete_entries(&t->sym_evsel->hists); 550 hists__delete_entries(hists);
548 } else { 551 } else {
549 hists__decay_entries(&t->sym_evsel->hists, 552 hists__decay_entries(hists, t->hide_user_symbols,
550 t->hide_user_symbols,
551 t->hide_kernel_symbols); 553 t->hide_kernel_symbols);
552 } 554 }
553 555
554 hists__collapse_resort(&t->sym_evsel->hists, NULL); 556 hists__collapse_resort(hists, NULL);
555 hists__output_resort(&t->sym_evsel->hists); 557 hists__output_resort(hists);
556} 558}
557 559
558static void *display_thread_tui(void *arg) 560static void *display_thread_tui(void *arg)
@@ -573,8 +575,10 @@ static void *display_thread_tui(void *arg)
573 * Zooming in/out UIDs. For now juse use whatever the user passed 575 * Zooming in/out UIDs. For now juse use whatever the user passed
574 * via --uid. 576 * via --uid.
575 */ 577 */
576 evlist__for_each(top->evlist, pos) 578 evlist__for_each(top->evlist, pos) {
577 pos->hists.uid_filter_str = top->record_opts.target.uid_str; 579 struct hists *hists = evsel__hists(pos);
580 hists->uid_filter_str = top->record_opts.target.uid_str;
581 }
578 582
579 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent, 583 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
580 &top->session->header.env); 584 &top->session->header.env);
@@ -768,6 +772,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
768 } 772 }
769 773
770 if (al.sym == NULL || !al.sym->ignore) { 774 if (al.sym == NULL || !al.sym->ignore) {
775 struct hists *hists = evsel__hists(evsel);
771 struct hist_entry_iter iter = { 776 struct hist_entry_iter iter = {
772 .add_entry_cb = hist_iter__top_callback, 777 .add_entry_cb = hist_iter__top_callback,
773 }; 778 };
@@ -777,14 +782,14 @@ static void perf_event__process_sample(struct perf_tool *tool,
777 else 782 else
778 iter.ops = &hist_iter_normal; 783 iter.ops = &hist_iter_normal;
779 784
780 pthread_mutex_lock(&evsel->hists.lock); 785 pthread_mutex_lock(&hists->lock);
781 786
782 err = hist_entry_iter__add(&iter, &al, evsel, sample, 787 err = hist_entry_iter__add(&iter, &al, evsel, sample,
783 top->max_stack, top); 788 top->max_stack, top);
784 if (err < 0) 789 if (err < 0)
785 pr_err("Problem incrementing symbol period, skipping event\n"); 790 pr_err("Problem incrementing symbol period, skipping event\n");
786 791
787 pthread_mutex_unlock(&evsel->hists.lock); 792 pthread_mutex_unlock(&hists->lock);
788 } 793 }
789 794
790 return; 795 return;
@@ -849,7 +854,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
849 perf_event__process_sample(&top->tool, event, evsel, 854 perf_event__process_sample(&top->tool, event, evsel,
850 &sample, machine); 855 &sample, machine);
851 } else if (event->header.type < PERF_RECORD_MAX) { 856 } else if (event->header.type < PERF_RECORD_MAX) {
852 hists__inc_nr_events(&evsel->hists, event->header.type); 857 hists__inc_nr_events(evsel__hists(evsel), event->header.type);
853 machine__process_event(machine, event, &sample); 858 machine__process_event(machine, event, &sample);
854 } else 859 } else
855 ++session->stats.nr_unknown_events; 860 ++session->stats.nr_unknown_events;
@@ -1042,7 +1047,6 @@ parse_percent_limit(const struct option *opt, const char *arg,
1042 1047
1043int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1048int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1044{ 1049{
1045 int status = -1;
1046 char errbuf[BUFSIZ]; 1050 char errbuf[BUFSIZ];
1047 struct perf_top top = { 1051 struct perf_top top = {
1048 .count_filter = 5, 1052 .count_filter = 5,
@@ -1160,6 +1164,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1160 "perf top [<options>]", 1164 "perf top [<options>]",
1161 NULL 1165 NULL
1162 }; 1166 };
1167 int status = hists__init();
1168
1169 if (status < 0)
1170 return status;
1163 1171
1164 top.evlist = perf_evlist__new(); 1172 top.evlist = perf_evlist__new();
1165 if (top.evlist == NULL) 1173 if (top.evlist == NULL)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 09bcf2393910..fb126459b134 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1189,13 +1189,13 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
1189 if (thread == NULL) 1189 if (thread == NULL)
1190 goto fail; 1190 goto fail;
1191 1191
1192 if (thread->priv == NULL) 1192 if (thread__priv(thread) == NULL)
1193 thread->priv = thread_trace__new(); 1193 thread__set_priv(thread, thread_trace__new());
1194 1194
1195 if (thread->priv == NULL) 1195 if (thread__priv(thread) == NULL)
1196 goto fail; 1196 goto fail;
1197 1197
1198 ttrace = thread->priv; 1198 ttrace = thread__priv(thread);
1199 ++ttrace->nr_events; 1199 ++ttrace->nr_events;
1200 1200
1201 return ttrace; 1201 return ttrace;
@@ -1248,7 +1248,7 @@ struct trace {
1248 1248
1249static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1249static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1250{ 1250{
1251 struct thread_trace *ttrace = thread->priv; 1251 struct thread_trace *ttrace = thread__priv(thread);
1252 1252
1253 if (fd > ttrace->paths.max) { 1253 if (fd > ttrace->paths.max) {
1254 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *)); 1254 char **npath = realloc(ttrace->paths.table, (fd + 1) * sizeof(char *));
@@ -1301,7 +1301,7 @@ static int thread__read_fd_path(struct thread *thread, int fd)
1301static const char *thread__fd_path(struct thread *thread, int fd, 1301static const char *thread__fd_path(struct thread *thread, int fd,
1302 struct trace *trace) 1302 struct trace *trace)
1303{ 1303{
1304 struct thread_trace *ttrace = thread->priv; 1304 struct thread_trace *ttrace = thread__priv(thread);
1305 1305
1306 if (ttrace == NULL) 1306 if (ttrace == NULL)
1307 return NULL; 1307 return NULL;
@@ -1338,7 +1338,7 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1338{ 1338{
1339 int fd = arg->val; 1339 int fd = arg->val;
1340 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1340 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1341 struct thread_trace *ttrace = arg->thread->priv; 1341 struct thread_trace *ttrace = thread__priv(arg->thread);
1342 1342
1343 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) 1343 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1344 zfree(&ttrace->paths.table[fd]); 1344 zfree(&ttrace->paths.table[fd]);
@@ -2381,7 +2381,7 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2381 FILE *fp = data->fp; 2381 FILE *fp = data->fp;
2382 size_t printed = data->printed; 2382 size_t printed = data->printed;
2383 struct trace *trace = data->trace; 2383 struct trace *trace = data->trace;
2384 struct thread_trace *ttrace = thread->priv; 2384 struct thread_trace *ttrace = thread__priv(thread);
2385 double ratio; 2385 double ratio;
2386 2386
2387 if (ttrace == NULL) 2387 if (ttrace == NULL)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index ac655b0700e7..162c978f1491 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -6,6 +6,7 @@
6#include <unistd.h> 6#include <unistd.h>
7#include <string.h> 7#include <string.h>
8#include "builtin.h" 8#include "builtin.h"
9#include "hist.h"
9#include "intlist.h" 10#include "intlist.h"
10#include "tests.h" 11#include "tests.h"
11#include "debug.h" 12#include "debug.h"
@@ -302,6 +303,10 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
302 OPT_END() 303 OPT_END()
303 }; 304 };
304 struct intlist *skiplist = NULL; 305 struct intlist *skiplist = NULL;
306 int ret = hists__init();
307
308 if (ret < 0)
309 return ret;
305 310
306 argc = parse_options(argc, argv, test_options, test_usage, 0); 311 argc = parse_options(argc, argv, test_options, test_usage, 0);
307 if (argc >= 1 && !strcmp(argv[0], "list")) 312 if (argc >= 1 && !strcmp(argv[0], "list"))
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 96adb730b744..fc25e57f4a5d 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -9,6 +9,7 @@
9#include "perf_regs.h" 9#include "perf_regs.h"
10#include "map.h" 10#include "map.h"
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h"
12 13
13static int mmap_handler(struct perf_tool *tool __maybe_unused, 14static int mmap_handler(struct perf_tool *tool __maybe_unused,
14 union perf_event *event, 15 union perf_event *event,
@@ -120,6 +121,8 @@ int test__dwarf_unwind(void)
120 return -1; 121 return -1;
121 } 122 }
122 123
124 callchain_param.record_mode = CALLCHAIN_DWARF;
125
123 if (init_live_machine(machine)) { 126 if (init_live_machine(machine)) {
124 pr_err("Could not init machine\n"); 127 pr_err("Could not init machine\n");
125 goto out; 128 goto out;
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index 0ac240db2e24..614d5c4978ab 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -245,7 +245,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
245static int test1(struct perf_evsel *evsel, struct machine *machine) 245static int test1(struct perf_evsel *evsel, struct machine *machine)
246{ 246{
247 int err; 247 int err;
248 struct hists *hists = &evsel->hists; 248 struct hists *hists = evsel__hists(evsel);
249 /* 249 /*
250 * expected output: 250 * expected output:
251 * 251 *
@@ -295,7 +295,7 @@ out:
295static int test2(struct perf_evsel *evsel, struct machine *machine) 295static int test2(struct perf_evsel *evsel, struct machine *machine)
296{ 296{
297 int err; 297 int err;
298 struct hists *hists = &evsel->hists; 298 struct hists *hists = evsel__hists(evsel);
299 /* 299 /*
300 * expected output: 300 * expected output:
301 * 301 *
@@ -442,7 +442,7 @@ out:
442static int test3(struct perf_evsel *evsel, struct machine *machine) 442static int test3(struct perf_evsel *evsel, struct machine *machine)
443{ 443{
444 int err; 444 int err;
445 struct hists *hists = &evsel->hists; 445 struct hists *hists = evsel__hists(evsel);
446 /* 446 /*
447 * expected output: 447 * expected output:
448 * 448 *
@@ -498,7 +498,7 @@ out:
498static int test4(struct perf_evsel *evsel, struct machine *machine) 498static int test4(struct perf_evsel *evsel, struct machine *machine)
499{ 499{
500 int err; 500 int err;
501 struct hists *hists = &evsel->hists; 501 struct hists *hists = evsel__hists(evsel);
502 /* 502 /*
503 * expected output: 503 * expected output:
504 * 504 *
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index 821f581fd930..5a31787cc6b9 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -66,11 +66,12 @@ static int add_hist_entries(struct perf_evlist *evlist,
66 .ops = &hist_iter_normal, 66 .ops = &hist_iter_normal,
67 .hide_unresolved = false, 67 .hide_unresolved = false,
68 }; 68 };
69 struct hists *hists = evsel__hists(evsel);
69 70
70 /* make sure it has no filter at first */ 71 /* make sure it has no filter at first */
71 evsel->hists.thread_filter = NULL; 72 hists->thread_filter = NULL;
72 evsel->hists.dso_filter = NULL; 73 hists->dso_filter = NULL;
73 evsel->hists.symbol_filter_str = NULL; 74 hists->symbol_filter_str = NULL;
74 75
75 sample.pid = fake_samples[i].pid; 76 sample.pid = fake_samples[i].pid;
76 sample.tid = fake_samples[i].pid; 77 sample.tid = fake_samples[i].pid;
@@ -134,7 +135,7 @@ int test__hists_filter(void)
134 goto out; 135 goto out;
135 136
136 evlist__for_each(evlist, evsel) { 137 evlist__for_each(evlist, evsel) {
137 struct hists *hists = &evsel->hists; 138 struct hists *hists = evsel__hists(evsel);
138 139
139 hists__collapse_resort(hists, NULL); 140 hists__collapse_resort(hists, NULL);
140 hists__output_resort(hists); 141 hists__output_resort(hists);
@@ -160,7 +161,7 @@ int test__hists_filter(void)
160 hists->stats.total_non_filtered_period); 161 hists->stats.total_non_filtered_period);
161 162
162 /* now applying thread filter for 'bash' */ 163 /* now applying thread filter for 'bash' */
163 evsel->hists.thread_filter = fake_samples[9].thread; 164 hists->thread_filter = fake_samples[9].thread;
164 hists__filter_by_thread(hists); 165 hists__filter_by_thread(hists);
165 166
166 if (verbose > 2) { 167 if (verbose > 2) {
@@ -185,11 +186,11 @@ int test__hists_filter(void)
185 hists->stats.total_non_filtered_period == 400); 186 hists->stats.total_non_filtered_period == 400);
186 187
187 /* remove thread filter first */ 188 /* remove thread filter first */
188 evsel->hists.thread_filter = NULL; 189 hists->thread_filter = NULL;
189 hists__filter_by_thread(hists); 190 hists__filter_by_thread(hists);
190 191
191 /* now applying dso filter for 'kernel' */ 192 /* now applying dso filter for 'kernel' */
192 evsel->hists.dso_filter = fake_samples[0].map->dso; 193 hists->dso_filter = fake_samples[0].map->dso;
193 hists__filter_by_dso(hists); 194 hists__filter_by_dso(hists);
194 195
195 if (verbose > 2) { 196 if (verbose > 2) {
@@ -214,7 +215,7 @@ int test__hists_filter(void)
214 hists->stats.total_non_filtered_period == 300); 215 hists->stats.total_non_filtered_period == 300);
215 216
216 /* remove dso filter first */ 217 /* remove dso filter first */
217 evsel->hists.dso_filter = NULL; 218 hists->dso_filter = NULL;
218 hists__filter_by_dso(hists); 219 hists__filter_by_dso(hists);
219 220
220 /* 221 /*
@@ -224,7 +225,7 @@ int test__hists_filter(void)
224 * be counted as a separate entry but the sample count and 225 * be counted as a separate entry but the sample count and
225 * total period will be remained. 226 * total period will be remained.
226 */ 227 */
227 evsel->hists.symbol_filter_str = "main"; 228 hists->symbol_filter_str = "main";
228 hists__filter_by_symbol(hists); 229 hists__filter_by_symbol(hists);
229 230
230 if (verbose > 2) { 231 if (verbose > 2) {
@@ -249,8 +250,8 @@ int test__hists_filter(void)
249 hists->stats.total_non_filtered_period == 300); 250 hists->stats.total_non_filtered_period == 300);
250 251
251 /* now applying all filters at once. */ 252 /* now applying all filters at once. */
252 evsel->hists.thread_filter = fake_samples[1].thread; 253 hists->thread_filter = fake_samples[1].thread;
253 evsel->hists.dso_filter = fake_samples[1].map->dso; 254 hists->dso_filter = fake_samples[1].map->dso;
254 hists__filter_by_thread(hists); 255 hists__filter_by_thread(hists);
255 hists__filter_by_dso(hists); 256 hists__filter_by_dso(hists);
256 257
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index d4b34b0f50a2..278ba8344c23 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -73,6 +73,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
73 * "bash [libc] malloc" so total 9 entries will be in the tree. 73 * "bash [libc] malloc" so total 9 entries will be in the tree.
74 */ 74 */
75 evlist__for_each(evlist, evsel) { 75 evlist__for_each(evlist, evsel) {
76 struct hists *hists = evsel__hists(evsel);
77
76 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { 78 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
77 const union perf_event event = { 79 const union perf_event event = {
78 .header = { 80 .header = {
@@ -87,7 +89,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
87 &sample) < 0) 89 &sample) < 0)
88 goto out; 90 goto out;
89 91
90 he = __hists__add_entry(&evsel->hists, &al, NULL, 92 he = __hists__add_entry(hists, &al, NULL,
91 NULL, NULL, 1, 1, 0, true); 93 NULL, NULL, 1, 1, 0, true);
92 if (he == NULL) 94 if (he == NULL)
93 goto out; 95 goto out;
@@ -111,7 +113,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
111 &sample) < 0) 113 &sample) < 0)
112 goto out; 114 goto out;
113 115
114 he = __hists__add_entry(&evsel->hists, &al, NULL, 116 he = __hists__add_entry(hists, &al, NULL,
115 NULL, NULL, 1, 1, 0, true); 117 NULL, NULL, 1, 1, 0, true);
116 if (he == NULL) 118 if (he == NULL)
117 goto out; 119 goto out;
@@ -271,6 +273,7 @@ static int validate_link(struct hists *leader, struct hists *other)
271int test__hists_link(void) 273int test__hists_link(void)
272{ 274{
273 int err = -1; 275 int err = -1;
276 struct hists *hists, *first_hists;
274 struct machines machines; 277 struct machines machines;
275 struct machine *machine = NULL; 278 struct machine *machine = NULL;
276 struct perf_evsel *evsel, *first; 279 struct perf_evsel *evsel, *first;
@@ -306,24 +309,28 @@ int test__hists_link(void)
306 goto out; 309 goto out;
307 310
308 evlist__for_each(evlist, evsel) { 311 evlist__for_each(evlist, evsel) {
309 hists__collapse_resort(&evsel->hists, NULL); 312 hists = evsel__hists(evsel);
313 hists__collapse_resort(hists, NULL);
310 314
311 if (verbose > 2) 315 if (verbose > 2)
312 print_hists_in(&evsel->hists); 316 print_hists_in(hists);
313 } 317 }
314 318
315 first = perf_evlist__first(evlist); 319 first = perf_evlist__first(evlist);
316 evsel = perf_evlist__last(evlist); 320 evsel = perf_evlist__last(evlist);
317 321
322 first_hists = evsel__hists(first);
323 hists = evsel__hists(evsel);
324
318 /* match common entries */ 325 /* match common entries */
319 hists__match(&first->hists, &evsel->hists); 326 hists__match(first_hists, hists);
320 err = validate_match(&first->hists, &evsel->hists); 327 err = validate_match(first_hists, hists);
321 if (err) 328 if (err)
322 goto out; 329 goto out;
323 330
324 /* link common and/or dummy entries */ 331 /* link common and/or dummy entries */
325 hists__link(&first->hists, &evsel->hists); 332 hists__link(first_hists, hists);
326 err = validate_link(&first->hists, &evsel->hists); 333 err = validate_link(first_hists, hists);
327 if (err) 334 if (err)
328 goto out; 335 goto out;
329 336
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index e3bbd6c54c1b..a748f2be1222 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -122,7 +122,7 @@ typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
122static int test1(struct perf_evsel *evsel, struct machine *machine) 122static int test1(struct perf_evsel *evsel, struct machine *machine)
123{ 123{
124 int err; 124 int err;
125 struct hists *hists = &evsel->hists; 125 struct hists *hists = evsel__hists(evsel);
126 struct hist_entry *he; 126 struct hist_entry *he;
127 struct rb_root *root; 127 struct rb_root *root;
128 struct rb_node *node; 128 struct rb_node *node;
@@ -159,7 +159,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)
159 print_hists_out(hists); 159 print_hists_out(hists);
160 } 160 }
161 161
162 root = &evsel->hists.entries; 162 root = &hists->entries;
163 node = rb_first(root); 163 node = rb_first(root);
164 he = rb_entry(node, struct hist_entry, rb_node); 164 he = rb_entry(node, struct hist_entry, rb_node);
165 TEST_ASSERT_VAL("Invalid hist entry", 165 TEST_ASSERT_VAL("Invalid hist entry",
@@ -224,7 +224,7 @@ out:
224static int test2(struct perf_evsel *evsel, struct machine *machine) 224static int test2(struct perf_evsel *evsel, struct machine *machine)
225{ 225{
226 int err; 226 int err;
227 struct hists *hists = &evsel->hists; 227 struct hists *hists = evsel__hists(evsel);
228 struct hist_entry *he; 228 struct hist_entry *he;
229 struct rb_root *root; 229 struct rb_root *root;
230 struct rb_node *node; 230 struct rb_node *node;
@@ -259,7 +259,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)
259 print_hists_out(hists); 259 print_hists_out(hists);
260 } 260 }
261 261
262 root = &evsel->hists.entries; 262 root = &hists->entries;
263 node = rb_first(root); 263 node = rb_first(root);
264 he = rb_entry(node, struct hist_entry, rb_node); 264 he = rb_entry(node, struct hist_entry, rb_node);
265 TEST_ASSERT_VAL("Invalid hist entry", 265 TEST_ASSERT_VAL("Invalid hist entry",
@@ -280,7 +280,7 @@ out:
280static int test3(struct perf_evsel *evsel, struct machine *machine) 280static int test3(struct perf_evsel *evsel, struct machine *machine)
281{ 281{
282 int err; 282 int err;
283 struct hists *hists = &evsel->hists; 283 struct hists *hists = evsel__hists(evsel);
284 struct hist_entry *he; 284 struct hist_entry *he;
285 struct rb_root *root; 285 struct rb_root *root;
286 struct rb_node *node; 286 struct rb_node *node;
@@ -313,7 +313,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)
313 print_hists_out(hists); 313 print_hists_out(hists);
314 } 314 }
315 315
316 root = &evsel->hists.entries; 316 root = &hists->entries;
317 node = rb_first(root); 317 node = rb_first(root);
318 he = rb_entry(node, struct hist_entry, rb_node); 318 he = rb_entry(node, struct hist_entry, rb_node);
319 TEST_ASSERT_VAL("Invalid hist entry", 319 TEST_ASSERT_VAL("Invalid hist entry",
@@ -354,7 +354,7 @@ out:
354static int test4(struct perf_evsel *evsel, struct machine *machine) 354static int test4(struct perf_evsel *evsel, struct machine *machine)
355{ 355{
356 int err; 356 int err;
357 struct hists *hists = &evsel->hists; 357 struct hists *hists = evsel__hists(evsel);
358 struct hist_entry *he; 358 struct hist_entry *he;
359 struct rb_root *root; 359 struct rb_root *root;
360 struct rb_node *node; 360 struct rb_node *node;
@@ -391,7 +391,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
391 print_hists_out(hists); 391 print_hists_out(hists);
392 } 392 }
393 393
394 root = &evsel->hists.entries; 394 root = &hists->entries;
395 node = rb_first(root); 395 node = rb_first(root);
396 he = rb_entry(node, struct hist_entry, rb_node); 396 he = rb_entry(node, struct hist_entry, rb_node);
397 TEST_ASSERT_VAL("Invalid hist entry", 397 TEST_ASSERT_VAL("Invalid hist entry",
@@ -456,7 +456,7 @@ out:
456static int test5(struct perf_evsel *evsel, struct machine *machine) 456static int test5(struct perf_evsel *evsel, struct machine *machine)
457{ 457{
458 int err; 458 int err;
459 struct hists *hists = &evsel->hists; 459 struct hists *hists = evsel__hists(evsel);
460 struct hist_entry *he; 460 struct hist_entry *he;
461 struct rb_root *root; 461 struct rb_root *root;
462 struct rb_node *node; 462 struct rb_node *node;
@@ -494,7 +494,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)
494 print_hists_out(hists); 494 print_hists_out(hists);
495 } 495 }
496 496
497 root = &evsel->hists.entries; 497 root = &hists->entries;
498 node = rb_first(root); 498 node = rb_first(root);
499 he = rb_entry(node, struct hist_entry, rb_node); 499 he = rb_entry(node, struct hist_entry, rb_node);
500 500
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 5941927a4b7f..7f2f51f93619 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -457,6 +457,36 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist)
457 return 0; 457 return 0;
458} 458}
459 459
460
461static int test__checkevent_pmu_events_mix(struct perf_evlist *evlist)
462{
463 struct perf_evsel *evsel = perf_evlist__first(evlist);
464
465 /* pmu-event:u */
466 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
467 TEST_ASSERT_VAL("wrong exclude_user",
468 !evsel->attr.exclude_user);
469 TEST_ASSERT_VAL("wrong exclude_kernel",
470 evsel->attr.exclude_kernel);
471 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
472 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
473 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
474
475 /* cpu/pmu-event/u*/
476 evsel = perf_evsel__next(evsel);
477 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
478 TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
479 TEST_ASSERT_VAL("wrong exclude_user",
480 !evsel->attr.exclude_user);
481 TEST_ASSERT_VAL("wrong exclude_kernel",
482 evsel->attr.exclude_kernel);
483 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
484 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
485 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
486
487 return 0;
488}
489
460static int test__checkterms_simple(struct list_head *terms) 490static int test__checkterms_simple(struct list_head *terms)
461{ 491{
462 struct parse_events_term *term; 492 struct parse_events_term *term;
@@ -1554,6 +1584,12 @@ static int test_pmu_events(void)
1554 e.check = test__checkevent_pmu_events; 1584 e.check = test__checkevent_pmu_events;
1555 1585
1556 ret = test_event(&e); 1586 ret = test_event(&e);
1587 if (ret)
1588 break;
1589 snprintf(name, MAX_NAME, "%s:u,cpu/event=%s/u", ent->d_name, ent->d_name);
1590 e.name = name;
1591 e.check = test__checkevent_pmu_events_mix;
1592 ret = test_event(&e);
1557#undef MAX_NAME 1593#undef MAX_NAME
1558 } 1594 }
1559 1595
diff --git a/tools/perf/ui/browsers/header.c b/tools/perf/ui/browsers/header.c
index 89c16b988618..e8278c558d4a 100644
--- a/tools/perf/ui/browsers/header.c
+++ b/tools/perf/ui/browsers/header.c
@@ -1,6 +1,7 @@
1#include "util/cache.h" 1#include "util/cache.h"
2#include "util/debug.h" 2#include "util/debug.h"
3#include "ui/browser.h" 3#include "ui/browser.h"
4#include "ui/keysyms.h"
4#include "ui/ui.h" 5#include "ui/ui.h"
5#include "ui/util.h" 6#include "ui/util.h"
6#include "ui/libslang.h" 7#include "ui/libslang.h"
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 8f60a970404f..cfb976b3de3a 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -35,7 +35,9 @@ struct hist_browser {
35 35
36extern void hist_browser__init_hpp(void); 36extern void hist_browser__init_hpp(void);
37 37
38static int hists__browser_title(struct hists *hists, char *bf, size_t size); 38static int hists__browser_title(struct hists *hists,
39 struct hist_browser_timer *hbt,
40 char *bf, size_t size);
39static void hist_browser__update_nr_entries(struct hist_browser *hb); 41static void hist_browser__update_nr_entries(struct hist_browser *hb);
40 42
41static struct rb_node *hists__filter_entries(struct rb_node *nd, 43static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -390,7 +392,7 @@ static int hist_browser__run(struct hist_browser *browser,
390 browser->b.entries = &browser->hists->entries; 392 browser->b.entries = &browser->hists->entries;
391 browser->b.nr_entries = hist_browser__nr_entries(browser); 393 browser->b.nr_entries = hist_browser__nr_entries(browser);
392 394
393 hists__browser_title(browser->hists, title, sizeof(title)); 395 hists__browser_title(browser->hists, hbt, title, sizeof(title));
394 396
395 if (ui_browser__show(&browser->b, title, 397 if (ui_browser__show(&browser->b, title,
396 "Press '?' for help on key bindings") < 0) 398 "Press '?' for help on key bindings") < 0)
@@ -417,7 +419,8 @@ static int hist_browser__run(struct hist_browser *browser,
417 ui_browser__warn_lost_events(&browser->b); 419 ui_browser__warn_lost_events(&browser->b);
418 } 420 }
419 421
420 hists__browser_title(browser->hists, title, sizeof(title)); 422 hists__browser_title(browser->hists,
423 hbt, title, sizeof(title));
421 ui_browser__show_title(&browser->b, title); 424 ui_browser__show_title(&browser->b, title);
422 continue; 425 continue;
423 } 426 }
@@ -1204,7 +1207,15 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *browser
1204 return browser->he_selection->thread; 1207 return browser->he_selection->thread;
1205} 1208}
1206 1209
1207static int hists__browser_title(struct hists *hists, char *bf, size_t size) 1210/* Check whether the browser is for 'top' or 'report' */
1211static inline bool is_report_browser(void *timer)
1212{
1213 return timer == NULL;
1214}
1215
1216static int hists__browser_title(struct hists *hists,
1217 struct hist_browser_timer *hbt,
1218 char *bf, size_t size)
1208{ 1219{
1209 char unit; 1220 char unit;
1210 int printed; 1221 int printed;
@@ -1229,12 +1240,14 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
1229 ev_name = buf; 1240 ev_name = buf;
1230 1241
1231 for_each_group_member(pos, evsel) { 1242 for_each_group_member(pos, evsel) {
1243 struct hists *pos_hists = evsel__hists(pos);
1244
1232 if (symbol_conf.filter_relative) { 1245 if (symbol_conf.filter_relative) {
1233 nr_samples += pos->hists.stats.nr_non_filtered_samples; 1246 nr_samples += pos_hists->stats.nr_non_filtered_samples;
1234 nr_events += pos->hists.stats.total_non_filtered_period; 1247 nr_events += pos_hists->stats.total_non_filtered_period;
1235 } else { 1248 } else {
1236 nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1249 nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
1237 nr_events += pos->hists.stats.total_period; 1250 nr_events += pos_hists->stats.total_period;
1238 } 1251 }
1239 } 1252 }
1240 } 1253 }
@@ -1256,6 +1269,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size)
1256 if (dso) 1269 if (dso)
1257 printed += scnprintf(bf + printed, size - printed, 1270 printed += scnprintf(bf + printed, size - printed,
1258 ", DSO: %s", dso->short_name); 1271 ", DSO: %s", dso->short_name);
1272 if (!is_report_browser(hbt)) {
1273 struct perf_top *top = hbt->arg;
1274
1275 if (top->zero)
1276 printed += scnprintf(bf + printed, size - printed, " [z]");
1277 }
1278
1259 return printed; 1279 return printed;
1260} 1280}
1261 1281
@@ -1267,12 +1287,6 @@ static inline void free_popup_options(char **options, int n)
1267 zfree(&options[i]); 1287 zfree(&options[i]);
1268} 1288}
1269 1289
1270/* Check whether the browser is for 'top' or 'report' */
1271static inline bool is_report_browser(void *timer)
1272{
1273 return timer == NULL;
1274}
1275
1276/* 1290/*
1277 * Only runtime switching of perf data file will make "input_name" point 1291 * Only runtime switching of perf data file will make "input_name" point
1278 * to a malloced buffer. So add "is_input_name_malloced" flag to decide 1292 * to a malloced buffer. So add "is_input_name_malloced" flag to decide
@@ -1387,7 +1401,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1387 float min_pcnt, 1401 float min_pcnt,
1388 struct perf_session_env *env) 1402 struct perf_session_env *env)
1389{ 1403{
1390 struct hists *hists = &evsel->hists; 1404 struct hists *hists = evsel__hists(evsel);
1391 struct hist_browser *browser = hist_browser__new(hists); 1405 struct hist_browser *browser = hist_browser__new(hists);
1392 struct branch_info *bi; 1406 struct branch_info *bi;
1393 struct pstack *fstack; 1407 struct pstack *fstack;
@@ -1802,8 +1816,9 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1802 struct perf_evsel_menu *menu = container_of(browser, 1816 struct perf_evsel_menu *menu = container_of(browser,
1803 struct perf_evsel_menu, b); 1817 struct perf_evsel_menu, b);
1804 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); 1818 struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
1819 struct hists *hists = evsel__hists(evsel);
1805 bool current_entry = ui_browser__is_current_entry(browser, row); 1820 bool current_entry = ui_browser__is_current_entry(browser, row);
1806 unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1821 unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE];
1807 const char *ev_name = perf_evsel__name(evsel); 1822 const char *ev_name = perf_evsel__name(evsel);
1808 char bf[256], unit; 1823 char bf[256], unit;
1809 const char *warn = " "; 1824 const char *warn = " ";
@@ -1818,7 +1833,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1818 ev_name = perf_evsel__group_name(evsel); 1833 ev_name = perf_evsel__group_name(evsel);
1819 1834
1820 for_each_group_member(pos, evsel) { 1835 for_each_group_member(pos, evsel) {
1821 nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE]; 1836 struct hists *pos_hists = evsel__hists(pos);
1837 nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE];
1822 } 1838 }
1823 } 1839 }
1824 1840
@@ -1827,7 +1843,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
1827 unit, unit == ' ' ? "" : " ", ev_name); 1843 unit, unit == ' ' ? "" : " ", ev_name);
1828 slsmg_printf("%s", bf); 1844 slsmg_printf("%s", bf);
1829 1845
1830 nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST]; 1846 nr_events = hists->stats.nr_events[PERF_RECORD_LOST];
1831 if (nr_events != 0) { 1847 if (nr_events != 0) {
1832 menu->lost_events = true; 1848 menu->lost_events = true;
1833 if (!current_entry) 1849 if (!current_entry)
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index f3fa4258b256..fc654fb77ace 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -319,7 +319,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
319 gtk_container_add(GTK_CONTAINER(window), vbox); 319 gtk_container_add(GTK_CONTAINER(window), vbox);
320 320
321 evlist__for_each(evlist, pos) { 321 evlist__for_each(evlist, pos) {
322 struct hists *hists = &pos->hists; 322 struct hists *hists = evsel__hists(pos);
323 const char *evname = perf_evsel__name(pos); 323 const char *evname = perf_evsel__name(pos);
324 GtkWidget *scrolled_window; 324 GtkWidget *scrolled_window;
325 GtkWidget *tab_label; 325 GtkWidget *tab_label;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 36437527dbb3..7dabde14ea54 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -478,7 +478,7 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,
478 478
479 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 479 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
480 480
481 if (addr < sym->start || addr > sym->end) 481 if (addr < sym->start || addr >= sym->end)
482 return -ERANGE; 482 return -ERANGE;
483 483
484 offset = addr - sym->start; 484 offset = addr - sym->start;
@@ -836,7 +836,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
836 end = map__rip_2objdump(map, sym->end); 836 end = map__rip_2objdump(map, sym->end);
837 837
838 offset = line_ip - start; 838 offset = line_ip - start;
839 if ((u64)line_ip < start || (u64)line_ip > end) 839 if ((u64)line_ip < start || (u64)line_ip >= end)
840 offset = -1; 840 offset = -1;
841 else 841 else
842 parsed_line = tmp2 + 1; 842 parsed_line = tmp2 + 1;
@@ -966,7 +966,7 @@ fallback:
966 kce.kcore_filename = symfs_filename; 966 kce.kcore_filename = symfs_filename;
967 kce.addr = map__rip_2objdump(map, sym->start); 967 kce.addr = map__rip_2objdump(map, sym->start);
968 kce.offs = sym->start; 968 kce.offs = sym->start;
969 kce.len = sym->end + 1 - sym->start; 969 kce.len = sym->end - sym->start;
970 if (!kcore_extract__create(&kce)) { 970 if (!kcore_extract__create(&kce)) {
971 delete_extract = true; 971 delete_extract = true;
972 strlcpy(symfs_filename, kce.extract_filename, 972 strlcpy(symfs_filename, kce.extract_filename,
@@ -987,7 +987,7 @@ fallback:
987 disassembler_style ? "-M " : "", 987 disassembler_style ? "-M " : "",
988 disassembler_style ? disassembler_style : "", 988 disassembler_style ? disassembler_style : "",
989 map__rip_2objdump(map, sym->start), 989 map__rip_2objdump(map, sym->start),
990 map__rip_2objdump(map, sym->end+1), 990 map__rip_2objdump(map, sym->end),
991 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 991 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
992 symbol_conf.annotate_src ? "-S" : "", 992 symbol_conf.annotate_src ? "-S" : "",
993 symfs_filename, filename); 993 symfs_filename, filename);
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 2a1f5a46543a..94cfefddf4db 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -65,6 +65,8 @@ struct callchain_param {
65 enum chain_key key; 65 enum chain_key key;
66}; 66};
67 67
68extern struct callchain_param callchain_param;
69
68struct callchain_list { 70struct callchain_list {
69 u64 ip; 71 u64 ip;
70 struct map_symbol ms; 72 struct map_symbol ms;
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 7eb7107731ec..5699e7e2a790 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -190,6 +190,32 @@ enum perf_user_event_type { /* above any possible kernel type */
190 PERF_RECORD_HEADER_MAX 190 PERF_RECORD_HEADER_MAX
191}; 191};
192 192
193/*
194 * The kernel collects the number of events it couldn't send in a stretch and
195 * when possible sends this number in a PERF_RECORD_LOST event. The number of
196 * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
197 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
198 * the sum of all struct lost_event.lost fields reported.
199 *
200 * The total_period is needed because by default auto-freq is used, so
201 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
202 * the total number of low level events, it is necessary to to sum all struct
203 * sample_event.period and stash the result in total_period.
204 */
205struct events_stats {
206 u64 total_period;
207 u64 total_non_filtered_period;
208 u64 total_lost;
209 u64 total_invalid_chains;
210 u32 nr_events[PERF_RECORD_HEADER_MAX];
211 u32 nr_non_filtered_samples;
212 u32 nr_lost_warned;
213 u32 nr_unknown_events;
214 u32 nr_invalid_chains;
215 u32 nr_unknown_id;
216 u32 nr_unprocessable_samples;
217};
218
193struct attr_event { 219struct attr_event {
194 struct perf_event_header header; 220 struct perf_event_header header;
195 struct perf_event_attr attr; 221 struct perf_event_attr attr;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3cebc9a8d52e..3c9e77d6b4c2 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1003,6 +1003,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
1003 1003
1004out_delete_threads: 1004out_delete_threads:
1005 thread_map__delete(evlist->threads); 1005 thread_map__delete(evlist->threads);
1006 evlist->threads = NULL;
1006 return -1; 1007 return -1;
1007} 1008}
1008 1009
@@ -1175,11 +1176,51 @@ void perf_evlist__close(struct perf_evlist *evlist)
1175 } 1176 }
1176} 1177}
1177 1178
1179static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
1180{
1181 int err = -ENOMEM;
1182
1183 /*
1184 * Try reading /sys/devices/system/cpu/online to get
1185 * an all cpus map.
1186 *
1187 * FIXME: -ENOMEM is the best we can do here, the cpu_map
1188 * code needs an overhaul to properly forward the
1189 * error, and we may not want to do that fallback to a
1190 * default cpu identity map :-\
1191 */
1192 evlist->cpus = cpu_map__new(NULL);
1193 if (evlist->cpus == NULL)
1194 goto out;
1195
1196 evlist->threads = thread_map__new_dummy();
1197 if (evlist->threads == NULL)
1198 goto out_free_cpus;
1199
1200 err = 0;
1201out:
1202 return err;
1203out_free_cpus:
1204 cpu_map__delete(evlist->cpus);
1205 evlist->cpus = NULL;
1206 goto out;
1207}
1208
1178int perf_evlist__open(struct perf_evlist *evlist) 1209int perf_evlist__open(struct perf_evlist *evlist)
1179{ 1210{
1180 struct perf_evsel *evsel; 1211 struct perf_evsel *evsel;
1181 int err; 1212 int err;
1182 1213
1214 /*
1215 * Default: one fd per CPU, all threads, aka systemwide
1216 * as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL
1217 */
1218 if (evlist->threads == NULL && evlist->cpus == NULL) {
1219 err = perf_evlist__create_syswide_maps(evlist);
1220 if (err < 0)
1221 goto out_err;
1222 }
1223
1183 perf_evlist__update_id_pos(evlist); 1224 perf_evlist__update_id_pos(evlist);
1184 1225
1185 evlist__for_each(evlist, evsel) { 1226 evlist__for_each(evlist, evsel) {
@@ -1276,8 +1317,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
1276 sigaction(SIGUSR1, &act, NULL); 1317 sigaction(SIGUSR1, &act, NULL);
1277 } 1318 }
1278 1319
1279 if (target__none(target)) 1320 if (target__none(target)) {
1321 if (evlist->threads == NULL) {
1322 fprintf(stderr, "FATAL: evlist->threads need to be set at this point (%s:%d).\n",
1323 __func__, __LINE__);
1324 goto out_close_pipes;
1325 }
1280 evlist->threads->map[0] = evlist->workload.pid; 1326 evlist->threads->map[0] = evlist->workload.pid;
1327 }
1281 1328
1282 close(child_ready_pipe[1]); 1329 close(child_ready_pipe[1]);
1283 close(go_pipe[0]); 1330 close(go_pipe[0]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index bd312b01e876..649b0c597283 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -117,6 +117,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
117 void *ucontext)); 117 void *ucontext));
118int perf_evlist__start_workload(struct perf_evlist *evlist); 118int perf_evlist__start_workload(struct perf_evlist *evlist);
119 119
120struct option;
121
120int perf_evlist__parse_mmap_pages(const struct option *opt, 122int perf_evlist__parse_mmap_pages(const struct option *opt,
121 const char *str, 123 const char *str,
122 int unset); 124 int unset);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index e0868a901c4a..2f9e68025ede 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -15,6 +15,8 @@
15#include <linux/perf_event.h> 15#include <linux/perf_event.h>
16#include <sys/resource.h> 16#include <sys/resource.h>
17#include "asm/bug.h" 17#include "asm/bug.h"
18#include "callchain.h"
19#include "cgroup.h"
18#include "evsel.h" 20#include "evsel.h"
19#include "evlist.h" 21#include "evlist.h"
20#include "util.h" 22#include "util.h"
@@ -32,6 +34,48 @@ static struct {
32 bool cloexec; 34 bool cloexec;
33} perf_missing_features; 35} perf_missing_features;
34 36
37static int perf_evsel__no_extra_init(struct perf_evsel *evsel __maybe_unused)
38{
39 return 0;
40}
41
42static void perf_evsel__no_extra_fini(struct perf_evsel *evsel __maybe_unused)
43{
44}
45
46static struct {
47 size_t size;
48 int (*init)(struct perf_evsel *evsel);
49 void (*fini)(struct perf_evsel *evsel);
50} perf_evsel__object = {
51 .size = sizeof(struct perf_evsel),
52 .init = perf_evsel__no_extra_init,
53 .fini = perf_evsel__no_extra_fini,
54};
55
56int perf_evsel__object_config(size_t object_size,
57 int (*init)(struct perf_evsel *evsel),
58 void (*fini)(struct perf_evsel *evsel))
59{
60
61 if (object_size == 0)
62 goto set_methods;
63
64 if (perf_evsel__object.size > object_size)
65 return -EINVAL;
66
67 perf_evsel__object.size = object_size;
68
69set_methods:
70 if (init != NULL)
71 perf_evsel__object.init = init;
72
73 if (fini != NULL)
74 perf_evsel__object.fini = fini;
75
76 return 0;
77}
78
35#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 79#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
36 80
37int __perf_evsel__sample_size(u64 sample_type) 81int __perf_evsel__sample_size(u64 sample_type)
@@ -116,16 +160,6 @@ void perf_evsel__calc_id_pos(struct perf_evsel *evsel)
116 evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); 160 evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type);
117} 161}
118 162
119void hists__init(struct hists *hists)
120{
121 memset(hists, 0, sizeof(*hists));
122 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
123 hists->entries_in = &hists->entries_in_array[0];
124 hists->entries_collapsed = RB_ROOT;
125 hists->entries = RB_ROOT;
126 pthread_mutex_init(&hists->lock, NULL);
127}
128
129void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, 163void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
130 enum perf_event_sample_format bit) 164 enum perf_event_sample_format bit)
131{ 165{
@@ -168,14 +202,14 @@ void perf_evsel__init(struct perf_evsel *evsel,
168 evsel->unit = ""; 202 evsel->unit = "";
169 evsel->scale = 1.0; 203 evsel->scale = 1.0;
170 INIT_LIST_HEAD(&evsel->node); 204 INIT_LIST_HEAD(&evsel->node);
171 hists__init(&evsel->hists); 205 perf_evsel__object.init(evsel);
172 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); 206 evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
173 perf_evsel__calc_id_pos(evsel); 207 perf_evsel__calc_id_pos(evsel);
174} 208}
175 209
176struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) 210struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
177{ 211{
178 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 212 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
179 213
180 if (evsel != NULL) 214 if (evsel != NULL)
181 perf_evsel__init(evsel, attr, idx); 215 perf_evsel__init(evsel, attr, idx);
@@ -185,7 +219,7 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
185 219
186struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx) 220struct perf_evsel *perf_evsel__newtp_idx(const char *sys, const char *name, int idx)
187{ 221{
188 struct perf_evsel *evsel = zalloc(sizeof(*evsel)); 222 struct perf_evsel *evsel = zalloc(perf_evsel__object.size);
189 223
190 if (evsel != NULL) { 224 if (evsel != NULL) {
191 struct perf_event_attr attr = { 225 struct perf_event_attr attr = {
@@ -692,7 +726,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
692 } 726 }
693} 727}
694 728
695int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 729static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
696{ 730{
697 int cpu, thread; 731 int cpu, thread;
698 732
@@ -780,13 +814,13 @@ int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
780 return evsel->counts != NULL ? 0 : -ENOMEM; 814 return evsel->counts != NULL ? 0 : -ENOMEM;
781} 815}
782 816
783void perf_evsel__free_fd(struct perf_evsel *evsel) 817static void perf_evsel__free_fd(struct perf_evsel *evsel)
784{ 818{
785 xyarray__delete(evsel->fd); 819 xyarray__delete(evsel->fd);
786 evsel->fd = NULL; 820 evsel->fd = NULL;
787} 821}
788 822
789void perf_evsel__free_id(struct perf_evsel *evsel) 823static void perf_evsel__free_id(struct perf_evsel *evsel)
790{ 824{
791 xyarray__delete(evsel->sample_id); 825 xyarray__delete(evsel->sample_id);
792 evsel->sample_id = NULL; 826 evsel->sample_id = NULL;
@@ -817,16 +851,17 @@ void perf_evsel__exit(struct perf_evsel *evsel)
817 assert(list_empty(&evsel->node)); 851 assert(list_empty(&evsel->node));
818 perf_evsel__free_fd(evsel); 852 perf_evsel__free_fd(evsel);
819 perf_evsel__free_id(evsel); 853 perf_evsel__free_id(evsel);
820}
821
822void perf_evsel__delete(struct perf_evsel *evsel)
823{
824 perf_evsel__exit(evsel);
825 close_cgroup(evsel->cgrp); 854 close_cgroup(evsel->cgrp);
826 zfree(&evsel->group_name); 855 zfree(&evsel->group_name);
827 if (evsel->tp_format) 856 if (evsel->tp_format)
828 pevent_free_format(evsel->tp_format); 857 pevent_free_format(evsel->tp_format);
829 zfree(&evsel->name); 858 zfree(&evsel->name);
859 perf_evsel__object.fini(evsel);
860}
861
862void perf_evsel__delete(struct perf_evsel *evsel)
863{
864 perf_evsel__exit(evsel);
830 free(evsel); 865 free(evsel);
831} 866}
832 867
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7bc314be6a7b..163c5604e5d1 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -7,8 +7,6 @@
7#include <linux/perf_event.h> 7#include <linux/perf_event.h>
8#include <linux/types.h> 8#include <linux/types.h>
9#include "xyarray.h" 9#include "xyarray.h"
10#include "cgroup.h"
11#include "hist.h"
12#include "symbol.h" 10#include "symbol.h"
13 11
14struct perf_counts_values { 12struct perf_counts_values {
@@ -43,6 +41,8 @@ struct perf_sample_id {
43 u64 period; 41 u64 period;
44}; 42};
45 43
44struct cgroup_sel;
45
46/** struct perf_evsel - event selector 46/** struct perf_evsel - event selector
47 * 47 *
48 * @name - Can be set to retain the original event name passed by the user, 48 * @name - Can be set to retain the original event name passed by the user,
@@ -66,7 +66,6 @@ struct perf_evsel {
66 struct perf_counts *prev_raw_counts; 66 struct perf_counts *prev_raw_counts;
67 int idx; 67 int idx;
68 u32 ids; 68 u32 ids;
69 struct hists hists;
70 char *name; 69 char *name;
71 double scale; 70 double scale;
72 const char *unit; 71 const char *unit;
@@ -100,13 +99,16 @@ union u64_swap {
100 u32 val32[2]; 99 u32 val32[2];
101}; 100};
102 101
103#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists)
104
105struct cpu_map; 102struct cpu_map;
103struct target;
106struct thread_map; 104struct thread_map;
107struct perf_evlist; 105struct perf_evlist;
108struct record_opts; 106struct record_opts;
109 107
108int perf_evsel__object_config(size_t object_size,
109 int (*init)(struct perf_evsel *evsel),
110 void (*fini)(struct perf_evsel *evsel));
111
110struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx); 112struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx);
111 113
112static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr) 114static inline struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr)
@@ -153,12 +155,9 @@ const char *perf_evsel__name(struct perf_evsel *evsel);
153const char *perf_evsel__group_name(struct perf_evsel *evsel); 155const char *perf_evsel__group_name(struct perf_evsel *evsel);
154int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size); 156int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
155 157
156int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
157int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads); 158int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
158int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus); 159int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
159void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus); 160void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
160void perf_evsel__free_fd(struct perf_evsel *evsel);
161void perf_evsel__free_id(struct perf_evsel *evsel);
162void perf_evsel__free_counts(struct perf_evsel *evsel); 161void perf_evsel__free_counts(struct perf_evsel *evsel);
163void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 162void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
164 163
@@ -281,8 +280,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
281 return __perf_evsel__read(evsel, ncpus, nthreads, true); 280 return __perf_evsel__read(evsel, ncpus, nthreads, true);
282} 281}
283 282
284void hists__init(struct hists *hists);
285
286int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, 283int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
287 struct perf_sample *sample); 284 struct perf_sample *sample);
288 285
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 86569fa3651d..6e88b9e395df 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -3,6 +3,7 @@
3#include "hist.h" 3#include "hist.h"
4#include "session.h" 4#include "session.h"
5#include "sort.h" 5#include "sort.h"
6#include "evlist.h"
6#include "evsel.h" 7#include "evsel.h"
7#include "annotate.h" 8#include "annotate.h"
8#include <math.h> 9#include <math.h>
@@ -14,13 +15,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
14static bool hists__filter_entry_by_symbol(struct hists *hists, 15static bool hists__filter_entry_by_symbol(struct hists *hists,
15 struct hist_entry *he); 16 struct hist_entry *he);
16 17
17struct callchain_param callchain_param = {
18 .mode = CHAIN_GRAPH_REL,
19 .min_percent = 0.5,
20 .order = ORDER_CALLEE,
21 .key = CCKEY_FUNCTION
22};
23
24u16 hists__col_len(struct hists *hists, enum hist_column col) 18u16 hists__col_len(struct hists *hists, enum hist_column col)
25{ 19{
26 return hists->col_len[col]; 20 return hists->col_len[col];
@@ -516,6 +510,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
516{ 510{
517 u64 cost; 511 u64 cost;
518 struct mem_info *mi = iter->priv; 512 struct mem_info *mi = iter->priv;
513 struct hists *hists = evsel__hists(iter->evsel);
519 struct hist_entry *he; 514 struct hist_entry *he;
520 515
521 if (mi == NULL) 516 if (mi == NULL)
@@ -532,7 +527,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
532 * and this is indirectly achieved by passing period=weight here 527 * and this is indirectly achieved by passing period=weight here
533 * and the he_stat__add_period() function. 528 * and the he_stat__add_period() function.
534 */ 529 */
535 he = __hists__add_entry(&iter->evsel->hists, al, iter->parent, NULL, mi, 530 he = __hists__add_entry(hists, al, iter->parent, NULL, mi,
536 cost, cost, 0, true); 531 cost, cost, 0, true);
537 if (!he) 532 if (!he)
538 return -ENOMEM; 533 return -ENOMEM;
@@ -546,13 +541,14 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
546 struct addr_location *al __maybe_unused) 541 struct addr_location *al __maybe_unused)
547{ 542{
548 struct perf_evsel *evsel = iter->evsel; 543 struct perf_evsel *evsel = iter->evsel;
544 struct hists *hists = evsel__hists(evsel);
549 struct hist_entry *he = iter->he; 545 struct hist_entry *he = iter->he;
550 int err = -EINVAL; 546 int err = -EINVAL;
551 547
552 if (he == NULL) 548 if (he == NULL)
553 goto out; 549 goto out;
554 550
555 hists__inc_nr_samples(&evsel->hists, he->filtered); 551 hists__inc_nr_samples(hists, he->filtered);
556 552
557 err = hist_entry__append_callchain(he, iter->sample); 553 err = hist_entry__append_callchain(he, iter->sample);
558 554
@@ -618,6 +614,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
618{ 614{
619 struct branch_info *bi; 615 struct branch_info *bi;
620 struct perf_evsel *evsel = iter->evsel; 616 struct perf_evsel *evsel = iter->evsel;
617 struct hists *hists = evsel__hists(evsel);
621 struct hist_entry *he = NULL; 618 struct hist_entry *he = NULL;
622 int i = iter->curr; 619 int i = iter->curr;
623 int err = 0; 620 int err = 0;
@@ -631,12 +628,12 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
631 * The report shows the percentage of total branches captured 628 * The report shows the percentage of total branches captured
632 * and not events sampled. Thus we use a pseudo period of 1. 629 * and not events sampled. Thus we use a pseudo period of 1.
633 */ 630 */
634 he = __hists__add_entry(&evsel->hists, al, iter->parent, &bi[i], NULL, 631 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
635 1, 1, 0, true); 632 1, 1, 0, true);
636 if (he == NULL) 633 if (he == NULL)
637 return -ENOMEM; 634 return -ENOMEM;
638 635
639 hists__inc_nr_samples(&evsel->hists, he->filtered); 636 hists__inc_nr_samples(hists, he->filtered);
640 637
641out: 638out:
642 iter->he = he; 639 iter->he = he;
@@ -668,7 +665,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
668 struct perf_sample *sample = iter->sample; 665 struct perf_sample *sample = iter->sample;
669 struct hist_entry *he; 666 struct hist_entry *he;
670 667
671 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 668 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
672 sample->period, sample->weight, 669 sample->period, sample->weight,
673 sample->transaction, true); 670 sample->transaction, true);
674 if (he == NULL) 671 if (he == NULL)
@@ -691,7 +688,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter,
691 688
692 iter->he = NULL; 689 iter->he = NULL;
693 690
694 hists__inc_nr_samples(&evsel->hists, he->filtered); 691 hists__inc_nr_samples(evsel__hists(evsel), he->filtered);
695 692
696 return hist_entry__append_callchain(he, sample); 693 return hist_entry__append_callchain(he, sample);
697} 694}
@@ -724,12 +721,13 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
724 struct addr_location *al) 721 struct addr_location *al)
725{ 722{
726 struct perf_evsel *evsel = iter->evsel; 723 struct perf_evsel *evsel = iter->evsel;
724 struct hists *hists = evsel__hists(evsel);
727 struct perf_sample *sample = iter->sample; 725 struct perf_sample *sample = iter->sample;
728 struct hist_entry **he_cache = iter->priv; 726 struct hist_entry **he_cache = iter->priv;
729 struct hist_entry *he; 727 struct hist_entry *he;
730 int err = 0; 728 int err = 0;
731 729
732 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 730 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL,
733 sample->period, sample->weight, 731 sample->period, sample->weight,
734 sample->transaction, true); 732 sample->transaction, true);
735 if (he == NULL) 733 if (he == NULL)
@@ -746,7 +744,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
746 */ 744 */
747 callchain_cursor_commit(&callchain_cursor); 745 callchain_cursor_commit(&callchain_cursor);
748 746
749 hists__inc_nr_samples(&evsel->hists, he->filtered); 747 hists__inc_nr_samples(hists, he->filtered);
750 748
751 return err; 749 return err;
752} 750}
@@ -802,7 +800,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
802 } 800 }
803 } 801 }
804 802
805 he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL, 803 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
806 sample->period, sample->weight, 804 sample->period, sample->weight,
807 sample->transaction, false); 805 sample->transaction, false);
808 if (he == NULL) 806 if (he == NULL)
@@ -1408,6 +1406,21 @@ int hists__link(struct hists *leader, struct hists *other)
1408 return 0; 1406 return 0;
1409} 1407}
1410 1408
1409
1410size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
1411{
1412 struct perf_evsel *pos;
1413 size_t ret = 0;
1414
1415 evlist__for_each(evlist, pos) {
1416 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1417 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
1418 }
1419
1420 return ret;
1421}
1422
1423
1411u64 hists__total_period(struct hists *hists) 1424u64 hists__total_period(struct hists *hists)
1412{ 1425{
1413 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period : 1426 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
@@ -1434,3 +1447,31 @@ int perf_hist_config(const char *var, const char *value)
1434 1447
1435 return 0; 1448 return 0;
1436} 1449}
1450
1451static int hists_evsel__init(struct perf_evsel *evsel)
1452{
1453 struct hists *hists = evsel__hists(evsel);
1454
1455 memset(hists, 0, sizeof(*hists));
1456 hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT;
1457 hists->entries_in = &hists->entries_in_array[0];
1458 hists->entries_collapsed = RB_ROOT;
1459 hists->entries = RB_ROOT;
1460 pthread_mutex_init(&hists->lock, NULL);
1461 return 0;
1462}
1463
1464/*
1465 * XXX We probably need a hists_evsel__exit() to free the hist_entries
1466 * stored in the rbtree...
1467 */
1468
1469int hists__init(void)
1470{
1471 int err = perf_evsel__object_config(sizeof(struct hists_evsel),
1472 hists_evsel__init, NULL);
1473 if (err)
1474 fputs("FATAL ERROR: Couldn't setup hists class\n", stderr);
1475
1476 return err;
1477}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 8c9c70e18cbb..d0ef9a19a744 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -4,12 +4,11 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <pthread.h> 5#include <pthread.h>
6#include "callchain.h" 6#include "callchain.h"
7#include "evsel.h"
7#include "header.h" 8#include "header.h"
8#include "color.h" 9#include "color.h"
9#include "ui/progress.h" 10#include "ui/progress.h"
10 11
11extern struct callchain_param callchain_param;
12
13struct hist_entry; 12struct hist_entry;
14struct addr_location; 13struct addr_location;
15struct symbol; 14struct symbol;
@@ -23,32 +22,6 @@ enum hist_filter {
23 HIST_FILTER__HOST, 22 HIST_FILTER__HOST,
24}; 23};
25 24
26/*
27 * The kernel collects the number of events it couldn't send in a stretch and
28 * when possible sends this number in a PERF_RECORD_LOST event. The number of
29 * such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while
30 * total_lost tells exactly how many events the kernel in fact lost, i.e. it is
31 * the sum of all struct lost_event.lost fields reported.
32 *
33 * The total_period is needed because by default auto-freq is used, so
34 * multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get
35 * the total number of low level events, it is necessary to to sum all struct
36 * sample_event.period and stash the result in total_period.
37 */
38struct events_stats {
39 u64 total_period;
40 u64 total_non_filtered_period;
41 u64 total_lost;
42 u64 total_invalid_chains;
43 u32 nr_events[PERF_RECORD_HEADER_MAX];
44 u32 nr_non_filtered_samples;
45 u32 nr_lost_warned;
46 u32 nr_unknown_events;
47 u32 nr_invalid_chains;
48 u32 nr_unknown_id;
49 u32 nr_unprocessable_samples;
50};
51
52enum hist_column { 25enum hist_column {
53 HISTC_SYMBOL, 26 HISTC_SYMBOL,
54 HISTC_DSO, 27 HISTC_DSO,
@@ -165,6 +138,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
165 138
166size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 139size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
167 int max_cols, float min_pcnt, FILE *fp); 140 int max_cols, float min_pcnt, FILE *fp);
141size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp);
168 142
169void hists__filter_by_dso(struct hists *hists); 143void hists__filter_by_dso(struct hists *hists);
170void hists__filter_by_thread(struct hists *hists); 144void hists__filter_by_thread(struct hists *hists);
@@ -185,6 +159,25 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
185void hists__match(struct hists *leader, struct hists *other); 159void hists__match(struct hists *leader, struct hists *other);
186int hists__link(struct hists *leader, struct hists *other); 160int hists__link(struct hists *leader, struct hists *other);
187 161
162struct hists_evsel {
163 struct perf_evsel evsel;
164 struct hists hists;
165};
166
167static inline struct perf_evsel *hists_to_evsel(struct hists *hists)
168{
169 struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists);
170 return &hevsel->evsel;
171}
172
173static inline struct hists *evsel__hists(struct perf_evsel *evsel)
174{
175 struct hists_evsel *hevsel = (struct hists_evsel *)evsel;
176 return &hevsel->hists;
177}
178
179int hists__init(void);
180
188struct perf_hpp { 181struct perf_hpp {
189 char *buf; 182 char *buf;
190 size_t size; 183 size_t size;
diff --git a/tools/perf/util/include/linux/string.h b/tools/perf/util/include/linux/string.h
index 97a800738226..6f19c548ecc0 100644
--- a/tools/perf/util/include/linux/string.h
+++ b/tools/perf/util/include/linux/string.h
@@ -1,4 +1,3 @@
1#include <string.h> 1#include <string.h>
2 2
3void *memdup(const void *src, size_t len); 3void *memdup(const void *src, size_t len);
4int str_append(char **s, int *len, const char *a);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b7d477fbda02..34fc7c8672e4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -13,12 +13,18 @@
13#include <symbol/kallsyms.h> 13#include <symbol/kallsyms.h>
14#include "unwind.h" 14#include "unwind.h"
15 15
16static void dsos__init(struct dsos *dsos)
17{
18 INIT_LIST_HEAD(&dsos->head);
19 dsos->root = RB_ROOT;
20}
21
16int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 22int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
17{ 23{
18 map_groups__init(&machine->kmaps); 24 map_groups__init(&machine->kmaps);
19 RB_CLEAR_NODE(&machine->rb_node); 25 RB_CLEAR_NODE(&machine->rb_node);
20 INIT_LIST_HEAD(&machine->user_dsos.head); 26 dsos__init(&machine->user_dsos);
21 INIT_LIST_HEAD(&machine->kernel_dsos.head); 27 dsos__init(&machine->kernel_dsos);
22 28
23 machine->threads = RB_ROOT; 29 machine->threads = RB_ROOT;
24 INIT_LIST_HEAD(&machine->dead_threads); 30 INIT_LIST_HEAD(&machine->dead_threads);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index b7090596ac50..2137c4596ec7 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -556,7 +556,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
556 556
557int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 557int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
558{ 558{
559 if (ams->addr < ams->map->start || ams->addr > ams->map->end) { 559 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
560 if (ams->map->groups == NULL) 560 if (ams->map->groups == NULL)
561 return -1; 561 return -1;
562 ams->map = map_groups__find(ams->map->groups, ams->map->type, 562 ams->map = map_groups__find(ams->map->groups, ams->map->type,
@@ -664,7 +664,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
664 goto move_map; 664 goto move_map;
665 } 665 }
666 666
667 before->end = map->start - 1; 667 before->end = map->start;
668 map_groups__insert(mg, before); 668 map_groups__insert(mg, before);
669 if (verbose >= 2) 669 if (verbose >= 2)
670 map__fprintf(before, fp); 670 map__fprintf(before, fp);
@@ -678,7 +678,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
678 goto move_map; 678 goto move_map;
679 } 679 }
680 680
681 after->start = map->end + 1; 681 after->start = map->end;
682 map_groups__insert(mg, after); 682 map_groups__insert(mg, after);
683 if (verbose >= 2) 683 if (verbose >= 2)
684 map__fprintf(after, fp); 684 map__fprintf(after, fp);
@@ -752,7 +752,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
752 m = rb_entry(parent, struct map, rb_node); 752 m = rb_entry(parent, struct map, rb_node);
753 if (ip < m->start) 753 if (ip < m->start)
754 p = &(*p)->rb_left; 754 p = &(*p)->rb_left;
755 else if (ip > m->end) 755 else if (ip >= m->end)
756 p = &(*p)->rb_right; 756 p = &(*p)->rb_right;
757 else 757 else
758 return m; 758 return m;
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index 706ce1a66169..fd4be94125fb 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -1,5 +1,6 @@
1#include <linux/list.h> 1#include <linux/list.h>
2#include <linux/compiler.h> 2#include <linux/compiler.h>
3#include <linux/string.h>
3#include "ordered-events.h" 4#include "ordered-events.h"
4#include "evlist.h" 5#include "evlist.h"
5#include "session.h" 6#include "session.h"
@@ -57,11 +58,45 @@ static void queue_event(struct ordered_events *oe, struct ordered_event *new)
57 } 58 }
58} 59}
59 60
61static union perf_event *__dup_event(struct ordered_events *oe,
62 union perf_event *event)
63{
64 union perf_event *new_event = NULL;
65
66 if (oe->cur_alloc_size < oe->max_alloc_size) {
67 new_event = memdup(event, event->header.size);
68 if (new_event)
69 oe->cur_alloc_size += event->header.size;
70 }
71
72 return new_event;
73}
74
75static union perf_event *dup_event(struct ordered_events *oe,
76 union perf_event *event)
77{
78 return oe->copy_on_queue ? __dup_event(oe, event) : event;
79}
80
81static void free_dup_event(struct ordered_events *oe, union perf_event *event)
82{
83 if (oe->copy_on_queue) {
84 oe->cur_alloc_size -= event->header.size;
85 free(event);
86 }
87}
88
60#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event)) 89#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct ordered_event))
61static struct ordered_event *alloc_event(struct ordered_events *oe) 90static struct ordered_event *alloc_event(struct ordered_events *oe,
91 union perf_event *event)
62{ 92{
63 struct list_head *cache = &oe->cache; 93 struct list_head *cache = &oe->cache;
64 struct ordered_event *new = NULL; 94 struct ordered_event *new = NULL;
95 union perf_event *new_event;
96
97 new_event = dup_event(oe, event);
98 if (!new_event)
99 return NULL;
65 100
66 if (!list_empty(cache)) { 101 if (!list_empty(cache)) {
67 new = list_entry(cache->next, struct ordered_event, list); 102 new = list_entry(cache->next, struct ordered_event, list);
@@ -74,8 +109,10 @@ static struct ordered_event *alloc_event(struct ordered_events *oe)
74 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new); 109 size_t size = MAX_SAMPLE_BUFFER * sizeof(*new);
75 110
76 oe->buffer = malloc(size); 111 oe->buffer = malloc(size);
77 if (!oe->buffer) 112 if (!oe->buffer) {
113 free_dup_event(oe, new_event);
78 return NULL; 114 return NULL;
115 }
79 116
80 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n", 117 pr("alloc size %" PRIu64 "B (+%zu), max %" PRIu64 "B\n",
81 oe->cur_alloc_size, size, oe->max_alloc_size); 118 oe->cur_alloc_size, size, oe->max_alloc_size);
@@ -90,15 +127,17 @@ static struct ordered_event *alloc_event(struct ordered_events *oe)
90 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size); 127 pr("allocation limit reached %" PRIu64 "B\n", oe->max_alloc_size);
91 } 128 }
92 129
130 new->event = new_event;
93 return new; 131 return new;
94} 132}
95 133
96struct ordered_event * 134struct ordered_event *
97ordered_events__new(struct ordered_events *oe, u64 timestamp) 135ordered_events__new(struct ordered_events *oe, u64 timestamp,
136 union perf_event *event)
98{ 137{
99 struct ordered_event *new; 138 struct ordered_event *new;
100 139
101 new = alloc_event(oe); 140 new = alloc_event(oe, event);
102 if (new) { 141 if (new) {
103 new->timestamp = timestamp; 142 new->timestamp = timestamp;
104 queue_event(oe, new); 143 queue_event(oe, new);
@@ -111,6 +150,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
111{ 150{
112 list_move(&event->list, &oe->cache); 151 list_move(&event->list, &oe->cache);
113 oe->nr_events--; 152 oe->nr_events--;
153 free_dup_event(oe, event->event);
114} 154}
115 155
116static int __ordered_events__flush(struct perf_session *s, 156static int __ordered_events__flush(struct perf_session *s,
@@ -240,6 +280,7 @@ void ordered_events__free(struct ordered_events *oe)
240 280
241 event = list_entry(oe->to_free.next, struct ordered_event, list); 281 event = list_entry(oe->to_free.next, struct ordered_event, list);
242 list_del(&event->list); 282 list_del(&event->list);
283 free_dup_event(oe, event->event);
243 free(event); 284 free(event);
244 } 285 }
245} 286}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index 3b2f20542a01..7b8f9b011f38 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -34,9 +34,11 @@ struct ordered_events {
34 int buffer_idx; 34 int buffer_idx;
35 unsigned int nr_events; 35 unsigned int nr_events;
36 enum oe_flush last_flush_type; 36 enum oe_flush last_flush_type;
37 bool copy_on_queue;
37}; 38};
38 39
39struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp); 40struct ordered_event *ordered_events__new(struct ordered_events *oe, u64 timestamp,
41 union perf_event *event);
40void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event); 42void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
41int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, 43int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
42 enum oe_flush how); 44 enum oe_flush how);
@@ -48,4 +50,10 @@ void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
48{ 50{
49 oe->max_alloc_size = size; 51 oe->max_alloc_size = size;
50} 52}
53
54static inline
55void ordered_events__set_copy_on_queue(struct ordered_events *oe, bool copy)
56{
57 oe->copy_on_queue = copy;
58}
51#endif /* __ORDERED_EVENTS_H */ 59#endif /* __ORDERED_EVENTS_H */
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index d76aa30cb1fb..c659a3ca1283 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -6,7 +6,7 @@
6#include "parse-options.h" 6#include "parse-options.h"
7#include "parse-events.h" 7#include "parse-events.h"
8#include "exec_cmd.h" 8#include "exec_cmd.h"
9#include "linux/string.h" 9#include "string.h"
10#include "symbol.h" 10#include "symbol.h"
11#include "cache.h" 11#include "cache.h"
12#include "header.h" 12#include "header.h"
@@ -30,6 +30,15 @@ extern int parse_events_debug;
30#endif 30#endif
31int parse_events_parse(void *data, void *scanner); 31int parse_events_parse(void *data, void *scanner);
32 32
33static struct perf_pmu_event_symbol *perf_pmu_events_list;
34/*
35 * The variable indicates the number of supported pmu event symbols.
36 * 0 means not initialized and ready to init
37 * -1 means failed to init, don't try anymore
38 * >0 is the number of supported pmu event symbols
39 */
40static int perf_pmu_events_list_num;
41
33static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = { 42static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
34 [PERF_COUNT_HW_CPU_CYCLES] = { 43 [PERF_COUNT_HW_CPU_CYCLES] = {
35 .symbol = "cpu-cycles", 44 .symbol = "cpu-cycles",
@@ -863,30 +872,111 @@ int parse_events_name(struct list_head *list, char *name)
863 return 0; 872 return 0;
864} 873}
865 874
866static int parse_events__scanner(const char *str, void *data, int start_token); 875static int
876comp_pmu(const void *p1, const void *p2)
877{
878 struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1;
879 struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2;
867 880
868static int parse_events_fixup(int ret, const char *str, void *data, 881 return strcmp(pmu1->symbol, pmu2->symbol);
869 int start_token) 882}
883
884static void perf_pmu__parse_cleanup(void)
870{ 885{
871 char *o = strdup(str); 886 if (perf_pmu_events_list_num > 0) {
872 char *s = NULL; 887 struct perf_pmu_event_symbol *p;
873 char *t = o; 888 int i;
874 char *p; 889
890 for (i = 0; i < perf_pmu_events_list_num; i++) {
891 p = perf_pmu_events_list + i;
892 free(p->symbol);
893 }
894 free(perf_pmu_events_list);
895 perf_pmu_events_list = NULL;
896 perf_pmu_events_list_num = 0;
897 }
898}
899
900#define SET_SYMBOL(str, stype) \
901do { \
902 p->symbol = str; \
903 if (!p->symbol) \
904 goto err; \
905 p->type = stype; \
906} while (0)
907
908/*
909 * Read the pmu events list from sysfs
910 * Save it into perf_pmu_events_list
911 */
912static void perf_pmu__parse_init(void)
913{
914
915 struct perf_pmu *pmu = NULL;
916 struct perf_pmu_alias *alias;
875 int len = 0; 917 int len = 0;
876 918
877 if (!o) 919 pmu = perf_pmu__find("cpu");
878 return ret; 920 if ((pmu == NULL) || list_empty(&pmu->aliases)) {
879 while ((p = strsep(&t, ",")) != NULL) { 921 perf_pmu_events_list_num = -1;
880 if (s) 922 return;
881 str_append(&s, &len, ",");
882 str_append(&s, &len, "cpu/");
883 str_append(&s, &len, p);
884 str_append(&s, &len, "/");
885 } 923 }
886 free(o); 924 list_for_each_entry(alias, &pmu->aliases, list) {
887 if (!s) 925 if (strchr(alias->name, '-'))
888 return -ENOMEM; 926 len++;
889 return parse_events__scanner(s, data, start_token); 927 len++;
928 }
929 perf_pmu_events_list = malloc(sizeof(struct perf_pmu_event_symbol) * len);
930 if (!perf_pmu_events_list)
931 return;
932 perf_pmu_events_list_num = len;
933
934 len = 0;
935 list_for_each_entry(alias, &pmu->aliases, list) {
936 struct perf_pmu_event_symbol *p = perf_pmu_events_list + len;
937 char *tmp = strchr(alias->name, '-');
938
939 if (tmp != NULL) {
940 SET_SYMBOL(strndup(alias->name, tmp - alias->name),
941 PMU_EVENT_SYMBOL_PREFIX);
942 p++;
943 SET_SYMBOL(strdup(++tmp), PMU_EVENT_SYMBOL_SUFFIX);
944 len += 2;
945 } else {
946 SET_SYMBOL(strdup(alias->name), PMU_EVENT_SYMBOL);
947 len++;
948 }
949 }
950 qsort(perf_pmu_events_list, len,
951 sizeof(struct perf_pmu_event_symbol), comp_pmu);
952
953 return;
954err:
955 perf_pmu__parse_cleanup();
956}
957
958enum perf_pmu_event_symbol_type
959perf_pmu__parse_check(const char *name)
960{
961 struct perf_pmu_event_symbol p, *r;
962
963 /* scan kernel pmu events from sysfs if needed */
964 if (perf_pmu_events_list_num == 0)
965 perf_pmu__parse_init();
966 /*
967 * name "cpu" could be prefix of cpu-cycles or cpu// events.
968 * cpu-cycles has been handled by hardcode.
969 * So it must be cpu// events, not kernel pmu event.
970 */
971 if ((perf_pmu_events_list_num <= 0) || !strcmp(name, "cpu"))
972 return PMU_EVENT_SYMBOL_ERR;
973
974 p.symbol = strdup(name);
975 r = bsearch(&p, perf_pmu_events_list,
976 (size_t) perf_pmu_events_list_num,
977 sizeof(struct perf_pmu_event_symbol), comp_pmu);
978 free(p.symbol);
979 return r ? r->type : PMU_EVENT_SYMBOL_ERR;
890} 980}
891 981
892static int parse_events__scanner(const char *str, void *data, int start_token) 982static int parse_events__scanner(const char *str, void *data, int start_token)
@@ -909,8 +999,6 @@ static int parse_events__scanner(const char *str, void *data, int start_token)
909 parse_events__flush_buffer(buffer, scanner); 999 parse_events__flush_buffer(buffer, scanner);
910 parse_events__delete_buffer(buffer, scanner); 1000 parse_events__delete_buffer(buffer, scanner);
911 parse_events_lex_destroy(scanner); 1001 parse_events_lex_destroy(scanner);
912 if (ret && !strchr(str, '/'))
913 ret = parse_events_fixup(ret, str, data, start_token);
914 return ret; 1002 return ret;
915} 1003}
916 1004
@@ -945,6 +1033,7 @@ int parse_events(struct perf_evlist *evlist, const char *str)
945 int ret; 1033 int ret;
946 1034
947 ret = parse_events__scanner(str, &data, PE_START_EVENTS); 1035 ret = parse_events__scanner(str, &data, PE_START_EVENTS);
1036 perf_pmu__parse_cleanup();
948 if (!ret) { 1037 if (!ret) {
949 int entries = data.idx - evlist->nr_entries; 1038 int entries = data.idx - evlist->nr_entries;
950 perf_evlist__splice_list_tail(evlist, &data.list, entries); 1039 perf_evlist__splice_list_tail(evlist, &data.list, entries);
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index df094b4ed5ed..db2cf78ff0f3 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -35,6 +35,18 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
35 35
36#define EVENTS_HELP_MAX (128*1024) 36#define EVENTS_HELP_MAX (128*1024)
37 37
38enum perf_pmu_event_symbol_type {
39 PMU_EVENT_SYMBOL_ERR, /* not a PMU EVENT */
40 PMU_EVENT_SYMBOL, /* normal style PMU event */
41 PMU_EVENT_SYMBOL_PREFIX, /* prefix of pre-suf style event */
42 PMU_EVENT_SYMBOL_SUFFIX, /* suffix of pre-suf style event */
43};
44
45struct perf_pmu_event_symbol {
46 char *symbol;
47 enum perf_pmu_event_symbol_type type;
48};
49
38enum { 50enum {
39 PARSE_EVENTS__TERM_TYPE_NUM, 51 PARSE_EVENTS__TERM_TYPE_NUM,
40 PARSE_EVENTS__TERM_TYPE_STR, 52 PARSE_EVENTS__TERM_TYPE_STR,
@@ -95,6 +107,8 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
95 void *ptr, char *type); 107 void *ptr, char *type);
96int parse_events_add_pmu(struct list_head *list, int *idx, 108int parse_events_add_pmu(struct list_head *list, int *idx,
97 char *pmu , struct list_head *head_config); 109 char *pmu , struct list_head *head_config);
110enum perf_pmu_event_symbol_type
111perf_pmu__parse_check(const char *name);
98void parse_events__set_leader(char *name, struct list_head *list); 112void parse_events__set_leader(char *name, struct list_head *list);
99void parse_events_update_lists(struct list_head *list_event, 113void parse_events_update_lists(struct list_head *list_event,
100 struct list_head *list_all); 114 struct list_head *list_all);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 343299575b30..906630bbf8eb 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -51,6 +51,24 @@ static int str(yyscan_t scanner, int token)
51 return token; 51 return token;
52} 52}
53 53
54static int pmu_str_check(yyscan_t scanner)
55{
56 YYSTYPE *yylval = parse_events_get_lval(scanner);
57 char *text = parse_events_get_text(scanner);
58
59 yylval->str = strdup(text);
60 switch (perf_pmu__parse_check(text)) {
61 case PMU_EVENT_SYMBOL_PREFIX:
62 return PE_PMU_EVENT_PRE;
63 case PMU_EVENT_SYMBOL_SUFFIX:
64 return PE_PMU_EVENT_SUF;
65 case PMU_EVENT_SYMBOL:
66 return PE_KERNEL_PMU_EVENT;
67 default:
68 return PE_NAME;
69 }
70}
71
54static int sym(yyscan_t scanner, int type, int config) 72static int sym(yyscan_t scanner, int type, int config)
55{ 73{
56 YYSTYPE *yylval = parse_events_get_lval(scanner); 74 YYSTYPE *yylval = parse_events_get_lval(scanner);
@@ -178,6 +196,16 @@ alignment-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_AL
178emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); } 196emulation-faults { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
179dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); } 197dummy { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
180 198
199 /*
200 * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
201 * Because the prefix cycles is mixed up with cpu-cycles.
202 * loads and stores are mixed up with cache event
203 */
204cycles-ct { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
205cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
206mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
207mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
208
181L1-dcache|l1-d|l1d|L1-data | 209L1-dcache|l1-d|l1d|L1-data |
182L1-icache|l1-i|l1i|L1-instruction | 210L1-icache|l1-i|l1i|L1-instruction |
183LLC|L2 | 211LLC|L2 |
@@ -199,7 +227,7 @@ r{num_raw_hex} { return raw(yyscanner); }
199{num_hex} { return value(yyscanner, 16); } 227{num_hex} { return value(yyscanner, 16); }
200 228
201{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } 229{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
202{name} { return str(yyscanner, PE_NAME); } 230{name} { return pmu_str_check(yyscanner); }
203"/" { BEGIN(config); return '/'; } 231"/" { BEGIN(config); return '/'; }
204- { return '-'; } 232- { return '-'; }
205, { BEGIN(event); return ','; } 233, { BEGIN(event); return ','; }
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 55fab6ad609a..93c4c9fbc922 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -47,6 +47,7 @@ static inc_group_count(struct list_head *list,
47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT 47%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP 48%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
49%token PE_ERROR 49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
50%type <num> PE_VALUE 51%type <num> PE_VALUE
51%type <num> PE_VALUE_SYM_HW 52%type <num> PE_VALUE_SYM_HW
52%type <num> PE_VALUE_SYM_SW 53%type <num> PE_VALUE_SYM_SW
@@ -58,6 +59,7 @@ static inc_group_count(struct list_head *list,
58%type <str> PE_MODIFIER_EVENT 59%type <str> PE_MODIFIER_EVENT
59%type <str> PE_MODIFIER_BP 60%type <str> PE_MODIFIER_BP
60%type <str> PE_EVENT_NAME 61%type <str> PE_EVENT_NAME
62%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
61%type <num> value_sym 63%type <num> value_sym
62%type <head> event_config 64%type <head> event_config
63%type <term> event_term 65%type <term> event_term
@@ -220,6 +222,44 @@ PE_NAME '/' '/'
220 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL)); 222 ABORT_ON(parse_events_add_pmu(list, &data->idx, $1, NULL));
221 $$ = list; 223 $$ = list;
222} 224}
225|
226PE_KERNEL_PMU_EVENT sep_dc
227{
228 struct parse_events_evlist *data = _data;
229 struct list_head *head;
230 struct parse_events_term *term;
231 struct list_head *list;
232
233 ALLOC_LIST(head);
234 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
235 $1, 1));
236 list_add_tail(&term->list, head);
237
238 ALLOC_LIST(list);
239 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
240 parse_events__free_terms(head);
241 $$ = list;
242}
243|
244PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
245{
246 struct parse_events_evlist *data = _data;
247 struct list_head *head;
248 struct parse_events_term *term;
249 struct list_head *list;
250 char pmu_name[128];
251 snprintf(&pmu_name, 128, "%s-%s", $1, $3);
252
253 ALLOC_LIST(head);
254 ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
255 &pmu_name, 1));
256 list_add_tail(&term->list, head);
257
258 ALLOC_LIST(list);
259 ABORT_ON(parse_events_add_pmu(list, &data->idx, "cpu", head));
260 parse_events__free_terms(head);
261 $$ = list;
262}
223 263
224value_sym: 264value_sym:
225PE_VALUE_SYM_HW 265PE_VALUE_SYM_HW
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 93a41ca96b8e..e243ad962a4d 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -12,16 +12,6 @@
12#include "parse-events.h" 12#include "parse-events.h"
13#include "cpumap.h" 13#include "cpumap.h"
14 14
15#define UNIT_MAX_LEN 31 /* max length for event unit name */
16
17struct perf_pmu_alias {
18 char *name;
19 struct list_head terms; /* HEAD struct parse_events_term -> list */
20 struct list_head list; /* ELEM */
21 char unit[UNIT_MAX_LEN+1];
22 double scale;
23};
24
25struct perf_pmu_format { 15struct perf_pmu_format {
26 char *name; 16 char *name;
27 int value; 17 int value;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index fe90a012c003..fe9dfbee8eed 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -30,6 +30,16 @@ struct perf_pmu_info {
30 double scale; 30 double scale;
31}; 31};
32 32
33#define UNIT_MAX_LEN 31 /* max length for event unit name */
34
35struct perf_pmu_alias {
36 char *name;
37 struct list_head terms; /* HEAD struct parse_events_term -> list */
38 struct list_head list; /* ELEM */
39 char unit[UNIT_MAX_LEN+1];
40 double scale;
41};
42
33struct perf_pmu *perf_pmu__find(const char *name); 43struct perf_pmu *perf_pmu__find(const char *name);
34int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr, 44int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
35 struct list_head *head_terms); 45 struct list_head *head_terms);
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 56ba07cce549..496f21cadd97 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -28,6 +28,7 @@
28 28
29#include "../../perf.h" 29#include "../../perf.h"
30#include "../debug.h" 30#include "../debug.h"
31#include "../callchain.h"
31#include "../evsel.h" 32#include "../evsel.h"
32#include "../util.h" 33#include "../util.h"
33#include "../event.h" 34#include "../event.h"
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 883406f4b381..6702ac28754b 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -532,17 +532,16 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
532 return -EINVAL; 532 return -EINVAL;
533 } 533 }
534 534
535 new = ordered_events__new(oe, timestamp); 535 new = ordered_events__new(oe, timestamp, event);
536 if (!new) { 536 if (!new) {
537 ordered_events__flush(s, tool, OE_FLUSH__HALF); 537 ordered_events__flush(s, tool, OE_FLUSH__HALF);
538 new = ordered_events__new(oe, timestamp); 538 new = ordered_events__new(oe, timestamp, event);
539 } 539 }
540 540
541 if (!new) 541 if (!new)
542 return -ENOMEM; 542 return -ENOMEM;
543 543
544 new->file_offset = file_offset; 544 new->file_offset = file_offset;
545 new->event = event;
546 return 0; 545 return 0;
547} 546}
548 547
@@ -813,22 +812,6 @@ int perf_session__deliver_event(struct perf_session *session,
813 dump_event(session, event, file_offset, sample); 812 dump_event(session, event, file_offset, sample);
814 813
815 evsel = perf_evlist__id2evsel(session->evlist, sample->id); 814 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
816 if (evsel != NULL && event->header.type != PERF_RECORD_SAMPLE) {
817 /*
818 * XXX We're leaving PERF_RECORD_SAMPLE unnacounted here
819 * because the tools right now may apply filters, discarding
820 * some of the samples. For consistency, in the future we
821 * should have something like nr_filtered_samples and remove
822 * the sample->period from total_sample_period, etc, KISS for
823 * now tho.
824 *
825 * Also testing against NULL allows us to handle files without
826 * attr.sample_id_all and/or without PERF_SAMPLE_ID. In the
827 * future probably it'll be a good idea to restrict event
828 * processing via perf_session to files with both set.
829 */
830 hists__inc_nr_events(&evsel->hists, event->header.type);
831 }
832 815
833 machine = perf_session__find_machine_for_cpumode(session, event, 816 machine = perf_session__find_machine_for_cpumode(session, event,
834 sample); 817 sample);
@@ -1391,16 +1374,9 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp
1391 1374
1392size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) 1375size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1393{ 1376{
1394 struct perf_evsel *pos;
1395 size_t ret = fprintf(fp, "Aggregated stats:\n"); 1377 size_t ret = fprintf(fp, "Aggregated stats:\n");
1396 1378
1397 ret += events_stats__fprintf(&session->stats, fp); 1379 ret += events_stats__fprintf(&session->stats, fp);
1398
1399 evlist__for_each(session->evlist, pos) {
1400 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
1401 ret += events_stats__fprintf(&pos->hists.stats, fp);
1402 }
1403
1404 return ret; 1380 return ret;
1405} 1381}
1406 1382
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index ffb440462008..a4be851f1a90 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -2,7 +2,6 @@
2#define __PERF_SESSION_H 2#define __PERF_SESSION_H
3 3
4#include "trace-event.h" 4#include "trace-event.h"
5#include "hist.h"
6#include "event.h" 5#include "event.h"
7#include "header.h" 6#include "header.h"
8#include "machine.h" 7#include "machine.h"
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 289df9d1e65a..4906cd81cb56 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1218,7 +1218,7 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1218 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1218 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1219 1219
1220 if (!len) 1220 if (!len)
1221 len = hists__col_len(&evsel->hists, hse->se->se_width_idx); 1221 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1222 1222
1223 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); 1223 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1224} 1224}
@@ -1233,7 +1233,7 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1233 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1233 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1234 1234
1235 if (!len) 1235 if (!len)
1236 len = hists__col_len(&evsel->hists, hse->se->se_width_idx); 1236 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
1237 1237
1238 return len; 1238 return len;
1239} 1239}
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d87767f76903..6afd6106ceb5 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -357,27 +357,3 @@ void *memdup(const void *src, size_t len)
357 357
358 return p; 358 return p;
359} 359}
360
361/**
362 * str_append - reallocate string and append another
363 * @s: pointer to string pointer
364 * @len: pointer to len (initialized)
365 * @a: string to append.
366 */
367int str_append(char **s, int *len, const char *a)
368{
369 int olen = *s ? strlen(*s) : 0;
370 int nlen = olen + strlen(a) + 1;
371 if (*len < nlen) {
372 *len = *len * 2;
373 if (*len < nlen)
374 *len = nlen;
375 *s = realloc(*s, *len);
376 if (!*s)
377 return -ENOMEM;
378 if (olen == 0)
379 **s = 0;
380 }
381 strcat(*s, a);
382 return 0;
383}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index be84f7a9838b..078331140d8c 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -186,7 +186,7 @@ void symbols__fixup_end(struct rb_root *symbols)
186 curr = rb_entry(nd, struct symbol, rb_node); 186 curr = rb_entry(nd, struct symbol, rb_node);
187 187
188 if (prev->end == prev->start && prev->end != curr->start) 188 if (prev->end == prev->start && prev->end != curr->start)
189 prev->end = curr->start - 1; 189 prev->end = curr->start;
190 } 190 }
191 191
192 /* Last entry */ 192 /* Last entry */
@@ -207,7 +207,7 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)
207 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) { 207 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
208 prev = curr; 208 prev = curr;
209 curr = rb_entry(nd, struct map, rb_node); 209 curr = rb_entry(nd, struct map, rb_node);
210 prev->end = curr->start - 1; 210 prev->end = curr->start;
211 } 211 }
212 212
213 /* 213 /*
@@ -229,7 +229,7 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
229 sym = ((void *)sym) + symbol_conf.priv_size; 229 sym = ((void *)sym) + symbol_conf.priv_size;
230 230
231 sym->start = start; 231 sym->start = start;
232 sym->end = len ? start + len - 1 : start; 232 sym->end = len ? start + len : start;
233 sym->binding = binding; 233 sym->binding = binding;
234 sym->namelen = namelen - 1; 234 sym->namelen = namelen - 1;
235 235
@@ -325,7 +325,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
325 325
326 if (ip < s->start) 326 if (ip < s->start)
327 n = n->rb_left; 327 n = n->rb_left;
328 else if (ip > s->end) 328 else if (ip >= s->end)
329 n = n->rb_right; 329 n = n->rb_right;
330 else 330 else
331 return s; 331 return s;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index bec4b7bd09de..eb2c19bf8d90 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -95,7 +95,7 @@ void symbols__delete(struct rb_root *symbols);
95 95
96static inline size_t symbol__size(const struct symbol *sym) 96static inline size_t symbol__size(const struct symbol *sym)
97{ 97{
98 return sym->end - sym->start + 1; 98 return sym->end - sym->start;
99} 99}
100 100
101struct strlist; 101struct strlist;
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index a9df7f2c6dc9..2b7b2d91c016 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,6 +7,7 @@
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9#include "comm.h" 9#include "comm.h"
10#include "unwind.h"
10 11
11int thread__init_map_groups(struct thread *thread, struct machine *machine) 12int thread__init_map_groups(struct thread *thread, struct machine *machine)
12{ 13{
@@ -37,6 +38,9 @@ struct thread *thread__new(pid_t pid, pid_t tid)
37 thread->cpu = -1; 38 thread->cpu = -1;
38 INIT_LIST_HEAD(&thread->comm_list); 39 INIT_LIST_HEAD(&thread->comm_list);
39 40
41 if (unwind__prepare_access(thread) < 0)
42 goto err_thread;
43
40 comm_str = malloc(32); 44 comm_str = malloc(32);
41 if (!comm_str) 45 if (!comm_str)
42 goto err_thread; 46 goto err_thread;
@@ -48,6 +52,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
48 goto err_thread; 52 goto err_thread;
49 53
50 list_add(&comm->list, &thread->comm_list); 54 list_add(&comm->list, &thread->comm_list);
55
51 } 56 }
52 57
53 return thread; 58 return thread;
@@ -69,6 +74,7 @@ void thread__delete(struct thread *thread)
69 list_del(&comm->list); 74 list_del(&comm->list);
70 comm__free(comm); 75 comm__free(comm);
71 } 76 }
77 unwind__finish_access(thread);
72 78
73 free(thread); 79 free(thread);
74} 80}
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 5d3215912105..f93b9734735b 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -214,6 +214,17 @@ out_free_threads:
214 goto out; 214 goto out;
215} 215}
216 216
217struct thread_map *thread_map__new_dummy(void)
218{
219 struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
220
221 if (threads != NULL) {
222 threads->map[0] = -1;
223 threads->nr = 1;
224 }
225 return threads;
226}
227
217static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 228static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
218{ 229{
219 struct thread_map *threads = NULL, *nt; 230 struct thread_map *threads = NULL, *nt;
@@ -224,14 +235,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
224 struct strlist *slist; 235 struct strlist *slist;
225 236
226 /* perf-stat expects threads to be generated even if tid not given */ 237 /* perf-stat expects threads to be generated even if tid not given */
227 if (!tid_str) { 238 if (!tid_str)
228 threads = malloc(sizeof(*threads) + sizeof(pid_t)); 239 return thread_map__new_dummy();
229 if (threads != NULL) {
230 threads->map[0] = -1;
231 threads->nr = 1;
232 }
233 return threads;
234 }
235 240
236 slist = strlist__new(false, tid_str); 241 slist = strlist__new(false, tid_str);
237 if (!slist) 242 if (!slist)
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 0cd8b3108084..95313f43cc0f 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -9,6 +9,7 @@ struct thread_map {
9 pid_t map[]; 9 pid_t map[];
10}; 10};
11 11
12struct thread_map *thread_map__new_dummy(void);
12struct thread_map *thread_map__new_by_pid(pid_t pid); 13struct thread_map *thread_map__new_by_pid(pid_t pid);
13struct thread_map *thread_map__new_by_tid(pid_t tid); 14struct thread_map *thread_map__new_by_tid(pid_t tid);
14struct thread_map *thread_map__new_by_uid(uid_t uid); 15struct thread_map *thread_map__new_by_uid(uid_t uid);
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 92b56db52471..e060386165c5 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -24,6 +24,7 @@
24#include <linux/list.h> 24#include <linux/list.h>
25#include <libunwind.h> 25#include <libunwind.h>
26#include <libunwind-ptrace.h> 26#include <libunwind-ptrace.h>
27#include "callchain.h"
27#include "thread.h" 28#include "thread.h"
28#include "session.h" 29#include "session.h"
29#include "perf_regs.h" 30#include "perf_regs.h"
@@ -525,12 +526,12 @@ static unw_accessors_t accessors = {
525 .get_proc_name = get_proc_name, 526 .get_proc_name = get_proc_name,
526}; 527};
527 528
528static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, 529int unwind__prepare_access(struct thread *thread)
529 void *arg, int max_stack)
530{ 530{
531 unw_addr_space_t addr_space; 531 unw_addr_space_t addr_space;
532 unw_cursor_t c; 532
533 int ret; 533 if (callchain_param.record_mode != CALLCHAIN_DWARF)
534 return 0;
534 535
535 addr_space = unw_create_addr_space(&accessors, 0); 536 addr_space = unw_create_addr_space(&accessors, 0);
536 if (!addr_space) { 537 if (!addr_space) {
@@ -538,6 +539,33 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
538 return -ENOMEM; 539 return -ENOMEM;
539 } 540 }
540 541
542 thread__set_priv(thread, addr_space);
543
544 return 0;
545}
546
547void unwind__finish_access(struct thread *thread)
548{
549 unw_addr_space_t addr_space;
550
551 if (callchain_param.record_mode != CALLCHAIN_DWARF)
552 return;
553
554 addr_space = thread__priv(thread);
555 unw_destroy_addr_space(addr_space);
556}
557
558static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
559 void *arg, int max_stack)
560{
561 unw_addr_space_t addr_space;
562 unw_cursor_t c;
563 int ret;
564
565 addr_space = thread__priv(ui->thread);
566 if (addr_space == NULL)
567 return -1;
568
541 ret = unw_init_remote(&c, addr_space, ui); 569 ret = unw_init_remote(&c, addr_space, ui);
542 if (ret) 570 if (ret)
543 display_error(ret); 571 display_error(ret);
@@ -549,7 +577,6 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
549 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0; 577 ret = ip ? entry(ip, ui->thread, ui->machine, cb, arg) : 0;
550 } 578 }
551 579
552 unw_destroy_addr_space(addr_space);
553 return ret; 580 return ret;
554} 581}
555 582
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index f03061260b4e..c17c4855bdbc 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -4,6 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include "event.h" 5#include "event.h"
6#include "symbol.h" 6#include "symbol.h"
7#include "thread.h"
7 8
8struct unwind_entry { 9struct unwind_entry {
9 struct map *map; 10 struct map *map;
@@ -21,6 +22,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
21/* libunwind specific */ 22/* libunwind specific */
22#ifdef HAVE_LIBUNWIND_SUPPORT 23#ifdef HAVE_LIBUNWIND_SUPPORT
23int libunwind__arch_reg_id(int regnum); 24int libunwind__arch_reg_id(int regnum);
25int unwind__prepare_access(struct thread *thread);
26void unwind__finish_access(struct thread *thread);
27#else
28static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
29{
30 return 0;
31}
32
33static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
24#endif 34#endif
25#else 35#else
26static inline int 36static inline int
@@ -33,5 +43,12 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
33{ 43{
34 return 0; 44 return 0;
35} 45}
46
47static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
48{
49 return 0;
50}
51
52static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
36#endif /* HAVE_DWARF_UNWIND_SUPPORT */ 53#endif /* HAVE_DWARF_UNWIND_SUPPORT */
37#endif /* __UNWIND_H */ 54#endif /* __UNWIND_H */
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 24e8d871b74e..d5eab3f3323f 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -14,6 +14,14 @@
14#include <byteswap.h> 14#include <byteswap.h>
15#include <linux/kernel.h> 15#include <linux/kernel.h>
16#include <unistd.h> 16#include <unistd.h>
17#include "callchain.h"
18
19struct callchain_param callchain_param = {
20 .mode = CHAIN_GRAPH_REL,
21 .min_percent = 0.5,
22 .order = ORDER_CALLEE,
23 .key = CCKEY_FUNCTION
24};
17 25
18/* 26/*
19 * XXX We need to find a better place for these things... 27 * XXX We need to find a better place for these things...