aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-data.c2
-rw-r--r--tools/perf/builtin-stat.c30
-rw-r--r--tools/perf/ui/browsers/annotate.c36
-rw-r--r--tools/perf/util/annotate.c11
-rw-r--r--tools/perf/util/counts.h1
-rw-r--r--tools/perf/util/data-convert-bt.c127
-rw-r--r--tools/perf/util/evlist.h5
-rw-r--r--tools/perf/util/evsel.c139
-rw-r--r--tools/perf/util/evsel.h2
-rw-r--r--tools/perf/util/sort.c2
-rw-r--r--tools/perf/util/stat.c4
-rw-r--r--tools/perf/util/stat.h5
13 files changed, 334 insertions, 32 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 6db782dfce96..658c920d74b9 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -177,8 +177,6 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
177 */ 177 */
178 process_branch_stack(sample->branch_stack, al, sample); 178 process_branch_stack(sample->branch_stack, al, sample);
179 179
180 sample->weight = 1;
181
182 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 180 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
183 if (he == NULL) 181 if (he == NULL)
184 return -ENOMEM; 182 return -ENOMEM;
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index 0adb5f82335a..46cd8490baf4 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -69,7 +69,7 @@ static int cmd_data_convert(int argc, const char **argv)
69 }; 69 };
70 70
71#ifndef HAVE_LIBBABELTRACE_SUPPORT 71#ifndef HAVE_LIBBABELTRACE_SUPPORT
72 pr_err("No conversion support compiled in.\n"); 72 pr_err("No conversion support compiled in. perf should be compiled with environment variables LIBBABELTRACE=1 and LIBBABELTRACE_DIR=/path/to/libbabeltrace/\n");
73 return -1; 73 return -1;
74#endif 74#endif
75 75
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 48ac53b199fc..866da7aa54bf 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -213,10 +213,20 @@ static void perf_stat__reset_stats(void)
213static int create_perf_stat_counter(struct perf_evsel *evsel) 213static int create_perf_stat_counter(struct perf_evsel *evsel)
214{ 214{
215 struct perf_event_attr *attr = &evsel->attr; 215 struct perf_event_attr *attr = &evsel->attr;
216 struct perf_evsel *leader = evsel->leader;
216 217
217 if (stat_config.scale) 218 if (stat_config.scale) {
218 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 219 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
219 PERF_FORMAT_TOTAL_TIME_RUNNING; 220 PERF_FORMAT_TOTAL_TIME_RUNNING;
221 }
222
223 /*
224 * The event is part of non trivial group, let's enable
225 * the group read (for leader) and ID retrieval for all
226 * members.
227 */
228 if (leader->nr_members > 1)
229 attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
220 230
221 attr->inherit = !no_inherit; 231 attr->inherit = !no_inherit;
222 232
@@ -333,13 +343,21 @@ static int read_counter(struct perf_evsel *counter)
333 struct perf_counts_values *count; 343 struct perf_counts_values *count;
334 344
335 count = perf_counts(counter->counts, cpu, thread); 345 count = perf_counts(counter->counts, cpu, thread);
336 if (perf_evsel__read(counter, cpu, thread, count)) { 346
347 /*
348 * The leader's group read loads data into its group members
349 * (via perf_evsel__read_counter) and sets threir count->loaded.
350 */
351 if (!count->loaded &&
352 perf_evsel__read_counter(counter, cpu, thread)) {
337 counter->counts->scaled = -1; 353 counter->counts->scaled = -1;
338 perf_counts(counter->counts, cpu, thread)->ena = 0; 354 perf_counts(counter->counts, cpu, thread)->ena = 0;
339 perf_counts(counter->counts, cpu, thread)->run = 0; 355 perf_counts(counter->counts, cpu, thread)->run = 0;
340 return -1; 356 return -1;
341 } 357 }
342 358
359 count->loaded = false;
360
343 if (STAT_RECORD) { 361 if (STAT_RECORD) {
344 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { 362 if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
345 pr_err("failed to write stat event\n"); 363 pr_err("failed to write stat event\n");
@@ -559,6 +577,11 @@ static int store_counter_ids(struct perf_evsel *counter)
559 return __store_counter_ids(counter, cpus, threads); 577 return __store_counter_ids(counter, cpus, threads);
560} 578}
561 579
580static bool perf_evsel__should_store_id(struct perf_evsel *counter)
581{
582 return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
583}
584
562static int __run_perf_stat(int argc, const char **argv) 585static int __run_perf_stat(int argc, const char **argv)
563{ 586{
564 int interval = stat_config.interval; 587 int interval = stat_config.interval;
@@ -631,7 +654,8 @@ try_again:
631 if (l > unit_width) 654 if (l > unit_width)
632 unit_width = l; 655 unit_width = l;
633 656
634 if (STAT_RECORD && store_counter_ids(counter)) 657 if (perf_evsel__should_store_id(counter) &&
658 store_counter_ids(counter))
635 return -1; 659 return -1;
636 } 660 }
637 661
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index dbe4e630b90f..80f38dab9c3a 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -17,8 +17,8 @@
17#include <sys/ttydefaults.h> 17#include <sys/ttydefaults.h>
18 18
19struct disasm_line_samples { 19struct disasm_line_samples {
20 double percent; 20 double percent;
21 u64 nr; 21 struct sym_hist_entry he;
22}; 22};
23 23
24#define IPC_WIDTH 6 24#define IPC_WIDTH 6
@@ -110,11 +110,12 @@ static int annotate_browser__set_jumps_percent_color(struct annotate_browser *br
110 110
111static int annotate_browser__pcnt_width(struct annotate_browser *ab) 111static int annotate_browser__pcnt_width(struct annotate_browser *ab)
112{ 112{
113 int w = 7 * ab->nr_events; 113 return (annotate_browser__opts.show_total_period ? 12 : 7) * ab->nr_events;
114}
114 115
115 if (ab->have_cycles) 116static int annotate_browser__cycles_width(struct annotate_browser *ab)
116 w += IPC_WIDTH + CYCLES_WIDTH; 117{
117 return w; 118 return ab->have_cycles ? IPC_WIDTH + CYCLES_WIDTH : 0;
118} 119}
119 120
120static void annotate_browser__write(struct ui_browser *browser, void *entry, int row) 121static void annotate_browser__write(struct ui_browser *browser, void *entry, int row)
@@ -127,7 +128,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
127 (!current_entry || (browser->use_navkeypressed && 128 (!current_entry || (browser->use_navkeypressed &&
128 !browser->navkeypressed))); 129 !browser->navkeypressed)));
129 int width = browser->width, printed; 130 int width = browser->width, printed;
130 int i, pcnt_width = annotate_browser__pcnt_width(ab); 131 int i, pcnt_width = annotate_browser__pcnt_width(ab),
132 cycles_width = annotate_browser__cycles_width(ab);
131 double percent_max = 0.0; 133 double percent_max = 0.0;
132 char bf[256]; 134 char bf[256];
133 bool show_title = false; 135 bool show_title = false;
@@ -151,8 +153,8 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
151 bdl->samples[i].percent, 153 bdl->samples[i].percent,
152 current_entry); 154 current_entry);
153 if (annotate_browser__opts.show_total_period) { 155 if (annotate_browser__opts.show_total_period) {
154 ui_browser__printf(browser, "%6" PRIu64 " ", 156 ui_browser__printf(browser, "%11" PRIu64 " ",
155 bdl->samples[i].nr); 157 bdl->samples[i].he.period);
156 } else { 158 } else {
157 ui_browser__printf(browser, "%6.2f ", 159 ui_browser__printf(browser, "%6.2f ",
158 bdl->samples[i].percent); 160 bdl->samples[i].percent);
@@ -162,9 +164,11 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
162 ui_browser__set_percent_color(browser, 0, current_entry); 164 ui_browser__set_percent_color(browser, 0, current_entry);
163 165
164 if (!show_title) 166 if (!show_title)
165 ui_browser__write_nstring(browser, " ", 7 * ab->nr_events); 167 ui_browser__write_nstring(browser, " ", pcnt_width);
166 else 168 else {
167 ui_browser__printf(browser, "%*s", 7, "Percent"); 169 ui_browser__printf(browser, "%*s", pcnt_width,
170 annotate_browser__opts.show_total_period ? "Period" : "Percent");
171 }
168 } 172 }
169 if (ab->have_cycles) { 173 if (ab->have_cycles) {
170 if (dl->ipc) 174 if (dl->ipc)
@@ -190,7 +194,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
190 width += 1; 194 width += 1;
191 195
192 if (!*dl->line) 196 if (!*dl->line)
193 ui_browser__write_nstring(browser, " ", width - pcnt_width); 197 ui_browser__write_nstring(browser, " ", width - pcnt_width - cycles_width);
194 else if (dl->offset == -1) { 198 else if (dl->offset == -1) {
195 if (dl->line_nr && annotate_browser__opts.show_linenr) 199 if (dl->line_nr && annotate_browser__opts.show_linenr)
196 printed = scnprintf(bf, sizeof(bf), "%-*d ", 200 printed = scnprintf(bf, sizeof(bf), "%-*d ",
@@ -199,7 +203,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
199 printed = scnprintf(bf, sizeof(bf), "%*s ", 203 printed = scnprintf(bf, sizeof(bf), "%*s ",
200 ab->addr_width, " "); 204 ab->addr_width, " ");
201 ui_browser__write_nstring(browser, bf, printed); 205 ui_browser__write_nstring(browser, bf, printed);
202 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width + 1); 206 ui_browser__write_nstring(browser, dl->line, width - printed - pcnt_width - cycles_width + 1);
203 } else { 207 } else {
204 u64 addr = dl->offset; 208 u64 addr = dl->offset;
205 int color = -1; 209 int color = -1;
@@ -256,7 +260,7 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
256 } 260 }
257 261
258 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 262 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
259 ui_browser__write_nstring(browser, bf, width - pcnt_width - 3 - printed); 263 ui_browser__write_nstring(browser, bf, width - pcnt_width - cycles_width - 3 - printed);
260 } 264 }
261 265
262 if (current_entry) 266 if (current_entry)
@@ -457,7 +461,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
457 pos->offset, 461 pos->offset,
458 next ? next->offset : len, 462 next ? next->offset : len,
459 &path, &sample); 463 &path, &sample);
460 bpos->samples[i].nr = sample.nr_samples; 464 bpos->samples[i].he = sample;
461 465
462 if (max_percent < bpos->samples[i].percent) 466 if (max_percent < bpos->samples[i].percent)
463 max_percent = bpos->samples[i].percent; 467 max_percent = bpos->samples[i].percent;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index c2b4b00166ed..2dab0e5a7f2f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -963,8 +963,9 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
963 u64 period = 0; 963 u64 period = 0;
964 964
965 while (offset < end) { 965 while (offset < end) {
966 hits += h->addr[offset++].nr_samples; 966 hits += h->addr[offset].nr_samples;
967 period += h->addr[offset++].period; 967 period += h->addr[offset].period;
968 ++offset;
968 } 969 }
969 970
970 if (h->nr_samples) { 971 if (h->nr_samples) {
@@ -1142,7 +1143,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1142 color = get_percent_color(percent); 1143 color = get_percent_color(percent);
1143 1144
1144 if (symbol_conf.show_total_period) 1145 if (symbol_conf.show_total_period)
1145 color_fprintf(stdout, color, " %7" PRIu64, 1146 color_fprintf(stdout, color, " %11" PRIu64,
1146 sample.period); 1147 sample.period);
1147 else 1148 else
1148 color_fprintf(stdout, color, " %7.2f", percent); 1149 color_fprintf(stdout, color, " %7.2f", percent);
@@ -1165,7 +1166,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
1165 } else if (max_lines && printed >= max_lines) 1166 } else if (max_lines && printed >= max_lines)
1166 return 1; 1167 return 1;
1167 else { 1168 else {
1168 int width = 8; 1169 int width = symbol_conf.show_total_period ? 12 : 8;
1169 1170
1170 if (queue) 1171 if (queue)
1171 return -1; 1172 return -1;
@@ -1806,7 +1807,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1806 int printed = 2, queue_len = 0; 1807 int printed = 2, queue_len = 0;
1807 int more = 0; 1808 int more = 0;
1808 u64 len; 1809 u64 len;
1809 int width = 8; 1810 int width = symbol_conf.show_total_period ? 12 : 8;
1810 int graph_dotted_len; 1811 int graph_dotted_len;
1811 1812
1812 filename = strdup(dso->long_name); 1813 filename = strdup(dso->long_name);
diff --git a/tools/perf/util/counts.h b/tools/perf/util/counts.h
index 34d8baaf558a..cb45a6aecf9d 100644
--- a/tools/perf/util/counts.h
+++ b/tools/perf/util/counts.h
@@ -12,6 +12,7 @@ struct perf_counts_values {
12 }; 12 };
13 u64 values[3]; 13 u64 values[3];
14 }; 14 };
15 bool loaded;
15}; 16};
16 17
17struct perf_counts { 18struct perf_counts {
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 3149b70799fd..2346cecb8ea2 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -76,6 +76,8 @@ struct ctf_writer {
76 struct bt_ctf_event_class *comm_class; 76 struct bt_ctf_event_class *comm_class;
77 struct bt_ctf_event_class *exit_class; 77 struct bt_ctf_event_class *exit_class;
78 struct bt_ctf_event_class *fork_class; 78 struct bt_ctf_event_class *fork_class;
79 struct bt_ctf_event_class *mmap_class;
80 struct bt_ctf_event_class *mmap2_class;
79}; 81};
80 82
81struct convert { 83struct convert {
@@ -506,6 +508,81 @@ put_len_type:
506 return ret; 508 return ret;
507} 509}
508 510
511static int
512add_callchain_output_values(struct bt_ctf_event_class *event_class,
513 struct bt_ctf_event *event,
514 struct ip_callchain *callchain)
515{
516 struct bt_ctf_field_type *len_type, *seq_type;
517 struct bt_ctf_field *len_field, *seq_field;
518 unsigned int nr_elements = callchain->nr;
519 unsigned int i;
520 int ret;
521
522 len_type = bt_ctf_event_class_get_field_by_name(
523 event_class, "perf_callchain_size");
524 len_field = bt_ctf_field_create(len_type);
525 if (!len_field) {
526 pr_err("failed to create 'perf_callchain_size' for callchain output event\n");
527 ret = -1;
528 goto put_len_type;
529 }
530
531 ret = bt_ctf_field_unsigned_integer_set_value(len_field, nr_elements);
532 if (ret) {
533 pr_err("failed to set field value for perf_callchain_size\n");
534 goto put_len_field;
535 }
536 ret = bt_ctf_event_set_payload(event, "perf_callchain_size", len_field);
537 if (ret) {
538 pr_err("failed to set payload to perf_callchain_size\n");
539 goto put_len_field;
540 }
541
542 seq_type = bt_ctf_event_class_get_field_by_name(
543 event_class, "perf_callchain");
544 seq_field = bt_ctf_field_create(seq_type);
545 if (!seq_field) {
546 pr_err("failed to create 'perf_callchain' for callchain output event\n");
547 ret = -1;
548 goto put_seq_type;
549 }
550
551 ret = bt_ctf_field_sequence_set_length(seq_field, len_field);
552 if (ret) {
553 pr_err("failed to set length of 'perf_callchain'\n");
554 goto put_seq_field;
555 }
556
557 for (i = 0; i < nr_elements; i++) {
558 struct bt_ctf_field *elem_field =
559 bt_ctf_field_sequence_get_field(seq_field, i);
560
561 ret = bt_ctf_field_unsigned_integer_set_value(elem_field,
562 ((u64 *)(callchain->ips))[i]);
563
564 bt_ctf_field_put(elem_field);
565 if (ret) {
566 pr_err("failed to set callchain[%d]\n", i);
567 goto put_seq_field;
568 }
569 }
570
571 ret = bt_ctf_event_set_payload(event, "perf_callchain", seq_field);
572 if (ret)
573 pr_err("failed to set payload for raw_data\n");
574
575put_seq_field:
576 bt_ctf_field_put(seq_field);
577put_seq_type:
578 bt_ctf_field_type_put(seq_type);
579put_len_field:
580 bt_ctf_field_put(len_field);
581put_len_type:
582 bt_ctf_field_type_put(len_type);
583 return ret;
584}
585
509static int add_generic_values(struct ctf_writer *cw, 586static int add_generic_values(struct ctf_writer *cw,
510 struct bt_ctf_event *event, 587 struct bt_ctf_event *event,
511 struct perf_evsel *evsel, 588 struct perf_evsel *evsel,
@@ -519,7 +596,6 @@ static int add_generic_values(struct ctf_writer *cw,
519 * PERF_SAMPLE_TIME - not needed as we have it in 596 * PERF_SAMPLE_TIME - not needed as we have it in
520 * ctf event header 597 * ctf event header
521 * PERF_SAMPLE_READ - TODO 598 * PERF_SAMPLE_READ - TODO
522 * PERF_SAMPLE_CALLCHAIN - TODO
523 * PERF_SAMPLE_RAW - tracepoint fields are handled separately 599 * PERF_SAMPLE_RAW - tracepoint fields are handled separately
524 * PERF_SAMPLE_BRANCH_STACK - TODO 600 * PERF_SAMPLE_BRANCH_STACK - TODO
525 * PERF_SAMPLE_REGS_USER - TODO 601 * PERF_SAMPLE_REGS_USER - TODO
@@ -720,6 +796,7 @@ static int process_sample_event(struct perf_tool *tool,
720 struct bt_ctf_event_class *event_class; 796 struct bt_ctf_event_class *event_class;
721 struct bt_ctf_event *event; 797 struct bt_ctf_event *event;
722 int ret; 798 int ret;
799 unsigned long type = evsel->attr.sample_type;
723 800
724 if (WARN_ONCE(!priv, "Failed to setup all events.\n")) 801 if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
725 return 0; 802 return 0;
@@ -751,6 +828,13 @@ static int process_sample_event(struct perf_tool *tool,
751 return -1; 828 return -1;
752 } 829 }
753 830
831 if (type & PERF_SAMPLE_CALLCHAIN) {
832 ret = add_callchain_output_values(event_class,
833 event, sample->callchain);
834 if (ret)
835 return -1;
836 }
837
754 if (perf_evsel__is_bpf_output(evsel)) { 838 if (perf_evsel__is_bpf_output(evsel)) {
755 ret = add_bpf_output_values(event_class, event, sample); 839 ret = add_bpf_output_values(event_class, event, sample);
756 if (ret) 840 if (ret)
@@ -833,6 +917,18 @@ __FUNC_PROCESS_NON_SAMPLE(exit,
833 __NON_SAMPLE_SET_FIELD(fork, u32, ptid); 917 __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
834 __NON_SAMPLE_SET_FIELD(fork, u64, time); 918 __NON_SAMPLE_SET_FIELD(fork, u64, time);
835) 919)
920__FUNC_PROCESS_NON_SAMPLE(mmap,
921 __NON_SAMPLE_SET_FIELD(mmap, u32, pid);
922 __NON_SAMPLE_SET_FIELD(mmap, u32, tid);
923 __NON_SAMPLE_SET_FIELD(mmap, u64_hex, start);
924 __NON_SAMPLE_SET_FIELD(mmap, string, filename);
925)
926__FUNC_PROCESS_NON_SAMPLE(mmap2,
927 __NON_SAMPLE_SET_FIELD(mmap2, u32, pid);
928 __NON_SAMPLE_SET_FIELD(mmap2, u32, tid);
929 __NON_SAMPLE_SET_FIELD(mmap2, u64_hex, start);
930 __NON_SAMPLE_SET_FIELD(mmap2, string, filename);
931)
836#undef __NON_SAMPLE_SET_FIELD 932#undef __NON_SAMPLE_SET_FIELD
837#undef __FUNC_PROCESS_NON_SAMPLE 933#undef __FUNC_PROCESS_NON_SAMPLE
838 934
@@ -1043,6 +1139,14 @@ static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
1043 if (type & PERF_SAMPLE_TRANSACTION) 1139 if (type & PERF_SAMPLE_TRANSACTION)
1044 ADD_FIELD(event_class, cw->data.u64, "perf_transaction"); 1140 ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
1045 1141
1142 if (type & PERF_SAMPLE_CALLCHAIN) {
1143 ADD_FIELD(event_class, cw->data.u32, "perf_callchain_size");
1144 ADD_FIELD(event_class,
1145 bt_ctf_field_type_sequence_create(
1146 cw->data.u64_hex, "perf_callchain_size"),
1147 "perf_callchain");
1148 }
1149
1046#undef ADD_FIELD 1150#undef ADD_FIELD
1047 return 0; 1151 return 0;
1048} 1152}
@@ -1164,6 +1268,19 @@ __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1164 __NON_SAMPLE_ADD_FIELD(u64, time); 1268 __NON_SAMPLE_ADD_FIELD(u64, time);
1165) 1269)
1166 1270
1271__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap,
1272 __NON_SAMPLE_ADD_FIELD(u32, pid);
1273 __NON_SAMPLE_ADD_FIELD(u32, tid);
1274 __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1275 __NON_SAMPLE_ADD_FIELD(string, filename);
1276)
1277
1278__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(mmap2,
1279 __NON_SAMPLE_ADD_FIELD(u32, pid);
1280 __NON_SAMPLE_ADD_FIELD(u32, tid);
1281 __NON_SAMPLE_ADD_FIELD(u64_hex, start);
1282 __NON_SAMPLE_ADD_FIELD(string, filename);
1283)
1167#undef __NON_SAMPLE_ADD_FIELD 1284#undef __NON_SAMPLE_ADD_FIELD
1168#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS 1285#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1169 1286
@@ -1181,6 +1298,12 @@ static int setup_non_sample_events(struct ctf_writer *cw,
1181 ret = add_fork_event(cw); 1298 ret = add_fork_event(cw);
1182 if (ret) 1299 if (ret)
1183 return ret; 1300 return ret;
1301 ret = add_mmap_event(cw);
1302 if (ret)
1303 return ret;
1304 ret = add_mmap2_event(cw);
1305 if (ret)
1306 return ret;
1184 return 0; 1307 return 0;
1185} 1308}
1186 1309
@@ -1482,6 +1605,8 @@ int bt_convert__perf2ctf(const char *input, const char *path,
1482 c.tool.comm = process_comm_event; 1605 c.tool.comm = process_comm_event;
1483 c.tool.exit = process_exit_event; 1606 c.tool.exit = process_exit_event;
1484 c.tool.fork = process_fork_event; 1607 c.tool.fork = process_fork_event;
1608 c.tool.mmap = process_mmap_event;
1609 c.tool.mmap2 = process_mmap2_event;
1485 } 1610 }
1486 1611
1487 err = perf_config(convert__config, &c); 1612 err = perf_config(convert__config, &c);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0843746bc389..bf2c4936e35f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -265,6 +265,11 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
265void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 265void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
266 struct list_head *list); 266 struct list_head *list);
267 267
268static inline bool perf_evlist__empty(struct perf_evlist *evlist)
269{
270 return list_empty(&evlist->entries);
271}
272
268static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist) 273static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
269{ 274{
270 return list_entry(evlist->entries.next, struct perf_evsel, node); 275 return list_entry(evlist->entries.next, struct perf_evsel, node);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 450b5fadf8cb..3735c9e0080d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -49,6 +49,7 @@ static struct {
49 bool clockid_wrong; 49 bool clockid_wrong;
50 bool lbr_flags; 50 bool lbr_flags;
51 bool write_backward; 51 bool write_backward;
52 bool group_read;
52} perf_missing_features; 53} perf_missing_features;
53 54
54static clockid_t clockid; 55static clockid_t clockid;
@@ -1261,20 +1262,148 @@ void perf_counts_values__scale(struct perf_counts_values *count,
1261 *pscaled = scaled; 1262 *pscaled = scaled;
1262} 1263}
1263 1264
1265static int perf_evsel__read_size(struct perf_evsel *evsel)
1266{
1267 u64 read_format = evsel->attr.read_format;
1268 int entry = sizeof(u64); /* value */
1269 int size = 0;
1270 int nr = 1;
1271
1272 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1273 size += sizeof(u64);
1274
1275 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1276 size += sizeof(u64);
1277
1278 if (read_format & PERF_FORMAT_ID)
1279 entry += sizeof(u64);
1280
1281 if (read_format & PERF_FORMAT_GROUP) {
1282 nr = evsel->nr_members;
1283 size += sizeof(u64);
1284 }
1285
1286 size += entry * nr;
1287 return size;
1288}
1289
1264int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 1290int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
1265 struct perf_counts_values *count) 1291 struct perf_counts_values *count)
1266{ 1292{
1293 size_t size = perf_evsel__read_size(evsel);
1294
1267 memset(count, 0, sizeof(*count)); 1295 memset(count, 0, sizeof(*count));
1268 1296
1269 if (FD(evsel, cpu, thread) < 0) 1297 if (FD(evsel, cpu, thread) < 0)
1270 return -EINVAL; 1298 return -EINVAL;
1271 1299
1272 if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0) 1300 if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
1273 return -errno; 1301 return -errno;
1274 1302
1275 return 0; 1303 return 0;
1276} 1304}
1277 1305
1306static int
1307perf_evsel__read_one(struct perf_evsel *evsel, int cpu, int thread)
1308{
1309 struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
1310
1311 return perf_evsel__read(evsel, cpu, thread, count);
1312}
1313
1314static void
1315perf_evsel__set_count(struct perf_evsel *counter, int cpu, int thread,
1316 u64 val, u64 ena, u64 run)
1317{
1318 struct perf_counts_values *count;
1319
1320 count = perf_counts(counter->counts, cpu, thread);
1321
1322 count->val = val;
1323 count->ena = ena;
1324 count->run = run;
1325 count->loaded = true;
1326}
1327
1328static int
1329perf_evsel__process_group_data(struct perf_evsel *leader,
1330 int cpu, int thread, u64 *data)
1331{
1332 u64 read_format = leader->attr.read_format;
1333 struct sample_read_value *v;
1334 u64 nr, ena = 0, run = 0, i;
1335
1336 nr = *data++;
1337
1338 if (nr != (u64) leader->nr_members)
1339 return -EINVAL;
1340
1341 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
1342 ena = *data++;
1343
1344 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
1345 run = *data++;
1346
1347 v = (struct sample_read_value *) data;
1348
1349 perf_evsel__set_count(leader, cpu, thread,
1350 v[0].value, ena, run);
1351
1352 for (i = 1; i < nr; i++) {
1353 struct perf_evsel *counter;
1354
1355 counter = perf_evlist__id2evsel(leader->evlist, v[i].id);
1356 if (!counter)
1357 return -EINVAL;
1358
1359 perf_evsel__set_count(counter, cpu, thread,
1360 v[i].value, ena, run);
1361 }
1362
1363 return 0;
1364}
1365
1366static int
1367perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
1368{
1369 struct perf_stat_evsel *ps = leader->priv;
1370 u64 read_format = leader->attr.read_format;
1371 int size = perf_evsel__read_size(leader);
1372 u64 *data = ps->group_data;
1373
1374 if (!(read_format & PERF_FORMAT_ID))
1375 return -EINVAL;
1376
1377 if (!perf_evsel__is_group_leader(leader))
1378 return -EINVAL;
1379
1380 if (!data) {
1381 data = zalloc(size);
1382 if (!data)
1383 return -ENOMEM;
1384
1385 ps->group_data = data;
1386 }
1387
1388 if (FD(leader, cpu, thread) < 0)
1389 return -EINVAL;
1390
1391 if (readn(FD(leader, cpu, thread), data, size) <= 0)
1392 return -errno;
1393
1394 return perf_evsel__process_group_data(leader, cpu, thread, data);
1395}
1396
1397int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread)
1398{
1399 u64 read_format = evsel->attr.read_format;
1400
1401 if (read_format & PERF_FORMAT_GROUP)
1402 return perf_evsel__read_group(evsel, cpu, thread);
1403 else
1404 return perf_evsel__read_one(evsel, cpu, thread);
1405}
1406
1278int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 1407int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
1279 int cpu, int thread, bool scale) 1408 int cpu, int thread, bool scale)
1280{ 1409{
@@ -1550,6 +1679,8 @@ fallback_missing_features:
1550 if (perf_missing_features.lbr_flags) 1679 if (perf_missing_features.lbr_flags)
1551 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | 1680 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1552 PERF_SAMPLE_BRANCH_NO_CYCLES); 1681 PERF_SAMPLE_BRANCH_NO_CYCLES);
1682 if (perf_missing_features.group_read && evsel->attr.inherit)
1683 evsel->attr.read_format &= ~(PERF_FORMAT_GROUP|PERF_FORMAT_ID);
1553retry_sample_id: 1684retry_sample_id:
1554 if (perf_missing_features.sample_id_all) 1685 if (perf_missing_features.sample_id_all)
1555 evsel->attr.sample_id_all = 0; 1686 evsel->attr.sample_id_all = 0;
@@ -1705,6 +1836,12 @@ try_fallback:
1705 perf_missing_features.lbr_flags = true; 1836 perf_missing_features.lbr_flags = true;
1706 pr_debug2("switching off branch sample type no (cycles/flags)\n"); 1837 pr_debug2("switching off branch sample type no (cycles/flags)\n");
1707 goto fallback_missing_features; 1838 goto fallback_missing_features;
1839 } else if (!perf_missing_features.group_read &&
1840 evsel->attr.inherit &&
1841 (evsel->attr.read_format & PERF_FORMAT_GROUP)) {
1842 perf_missing_features.group_read = true;
1843 pr_debug2("switching off group read\n");
1844 goto fallback_missing_features;
1708 } 1845 }
1709out_close: 1846out_close:
1710 do { 1847 do {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index fb40ca3c6519..de03c18daaf0 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -299,6 +299,8 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
299int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, 299int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
300 struct perf_counts_values *count); 300 struct perf_counts_values *count);
301 301
302int perf_evsel__read_counter(struct perf_evsel *evsel, int cpu, int thread);
303
302int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, 304int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
303 int cpu, int thread, bool scale); 305 int cpu, int thread, bool scale);
304 306
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 8b327c955a4f..12359bd986db 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -2563,7 +2563,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
2563 2563
2564 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders)); 2564 BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
2565 2565
2566 if (evlist == NULL) 2566 if (evlist == NULL || perf_evlist__empty(evlist))
2567 goto out_no_evlist; 2567 goto out_no_evlist;
2568 2568
2569 evlist__for_each_entry(evlist, evsel) { 2569 evlist__for_each_entry(evlist, evsel) {
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 53b9a994a3dc..35e9848734d6 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -128,6 +128,10 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
128 128
129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) 129static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
130{ 130{
131 struct perf_stat_evsel *ps = evsel->priv;
132
133 if (ps)
134 free(ps->group_data);
131 zfree(&evsel->priv); 135 zfree(&evsel->priv);
132} 136}
133 137
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 7522bf10b03e..eacaf958e19d 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -28,8 +28,9 @@ enum perf_stat_evsel_id {
28}; 28};
29 29
30struct perf_stat_evsel { 30struct perf_stat_evsel {
31 struct stats res_stats[3]; 31 struct stats res_stats[3];
32 enum perf_stat_evsel_id id; 32 enum perf_stat_evsel_id id;
33 u64 *group_data;
33}; 34};
34 35
35enum aggr_mode { 36enum aggr_mode {