diff options
author | Ingo Molnar <mingo@kernel.org> | 2017-11-03 10:06:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2017-11-03 10:06:53 -0400 |
commit | 340b5319c98eb14f7a70947a38e17d06f5beea88 (patch) | |
tree | ece6aeb203be9207ae16eb2ffb985fddc42db46d /tools/perf | |
parent | 0d3d73aac2ff05c78387aa9dcc2c8aa3804405e7 (diff) | |
parent | 7285cf3325b4a1dfb336d31eebc27dfbc30fb9aa (diff) |
Merge tag 'perf-core-for-mingo-4.15-20171103' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
- Beautify the 'kcmp' and 'prctl' syscall arguments in 'perf trace'
(Arnaldo Carvalho de Melo)
- Implement a way to print formatted output to per-event files in 'perf script'
to facilitate generate flamegraphs, elliminating the need to write scripts to
do that separation (yuzhoujian, Arnaldo Carvalho de Melo)
Make 'perf stat --per-thread' update shadow stats to show metrics (Jiri Olsa)
- Fix double mapping al->addr in callchain processing for children without self
period (Namhyung Kim)
- Fix memory leak in addr2inlines() when libbfd is not used (Namhyung Kim)
- Show correct function name for srcline of callchains when libbfd is not used
(Namhyung Kim)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
45 files changed, 772 insertions, 381 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt index 25e677344728..2811fcf684cb 100644 --- a/tools/perf/Documentation/perf-script.txt +++ b/tools/perf/Documentation/perf-script.txt | |||
@@ -325,6 +325,10 @@ include::itrace.txt[] | |||
325 | Set the maximum number of program blocks to print with brstackasm for | 325 | Set the maximum number of program blocks to print with brstackasm for |
326 | each sample. | 326 | each sample. |
327 | 327 | ||
328 | --per-event-dump:: | ||
329 | Create per event files with a "perf.data.EVENT.dump" name instead of | ||
330 | printing to stdout, useful, for instance, for generating flamegraphs. | ||
331 | |||
328 | --inline:: | 332 | --inline:: |
329 | If a callgraph address belongs to an inlined function, the inline stack | 333 | If a callgraph address belongs to an inlined function, the inline stack |
330 | will be printed. Each entry has function name and file/line. Enabled by | 334 | will be printed. Each entry has function name and file/line. Enabled by |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 5f7408118a2d..68cf1360a3f3 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -420,6 +420,13 @@ sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh | |||
420 | $(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl) | 420 | $(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl) |
421 | $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@ | 421 | $(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@ |
422 | 422 | ||
423 | kcmp_type_array := $(beauty_outdir)/kcmp_type_array.c | ||
424 | kcmp_hdr_dir := $(srctree)/tools/include/uapi/linux/ | ||
425 | kcmp_type_tbl := $(srctree)/tools/perf/trace/beauty/kcmp_type.sh | ||
426 | |||
427 | $(kcmp_type_array): $(kcmp_hdr_dir)/kcmp.h $(kcmp_type_tbl) | ||
428 | $(Q)$(SHELL) '$(kcmp_type_tbl)' $(kcmp_hdr_dir) > $@ | ||
429 | |||
423 | kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c | 430 | kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c |
424 | kvm_hdr_dir := $(srctree)/tools/include/uapi/linux | 431 | kvm_hdr_dir := $(srctree)/tools/include/uapi/linux |
425 | kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh | 432 | kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh |
@@ -448,6 +455,13 @@ madvise_behavior_tbl := $(srctree)/tools/perf/trace/beauty/madvise_behavior.sh | |||
448 | $(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) | 455 | $(madvise_behavior_array): $(madvise_hdr_dir)/mman-common.h $(madvise_behavior_tbl) |
449 | $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ | 456 | $(Q)$(SHELL) '$(madvise_behavior_tbl)' $(madvise_hdr_dir) > $@ |
450 | 457 | ||
458 | prctl_option_array := $(beauty_outdir)/prctl_option_array.c | ||
459 | prctl_hdr_dir := $(srctree)/tools/include/uapi/linux/ | ||
460 | prctl_option_tbl := $(srctree)/tools/perf/trace/beauty/prctl_option.sh | ||
461 | |||
462 | $(prctl_option_array): $(prctl_hdr_dir)/prctl.h $(prctl_option_tbl) | ||
463 | $(Q)$(SHELL) '$(prctl_option_tbl)' $(prctl_hdr_dir) > $@ | ||
464 | |||
451 | all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) | 465 | all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS) |
452 | 466 | ||
453 | $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) | 467 | $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) |
@@ -546,10 +560,12 @@ prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioc | |||
546 | $(pkey_alloc_access_rights_array) \ | 560 | $(pkey_alloc_access_rights_array) \ |
547 | $(sndrv_pcm_ioctl_array) \ | 561 | $(sndrv_pcm_ioctl_array) \ |
548 | $(sndrv_ctl_ioctl_array) \ | 562 | $(sndrv_ctl_ioctl_array) \ |
563 | $(kcmp_type_array) \ | ||
549 | $(kvm_ioctl_array) \ | 564 | $(kvm_ioctl_array) \ |
550 | $(vhost_virtio_ioctl_array) \ | 565 | $(vhost_virtio_ioctl_array) \ |
551 | $(madvise_behavior_array) \ | 566 | $(madvise_behavior_array) \ |
552 | $(perf_ioctl_array) | 567 | $(perf_ioctl_array) \ |
568 | $(prctl_option_array) | ||
553 | 569 | ||
554 | $(OUTPUT)%.o: %.c prepare FORCE | 570 | $(OUTPUT)%.o: %.c prepare FORCE |
555 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ | 571 | $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ |
@@ -828,8 +844,10 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea | |||
828 | $(OUTPUT)$(sndrv_ctl_ioctl_array) \ | 844 | $(OUTPUT)$(sndrv_ctl_ioctl_array) \ |
829 | $(OUTPUT)$(sndrv_pcm_ioctl_array) \ | 845 | $(OUTPUT)$(sndrv_pcm_ioctl_array) \ |
830 | $(OUTPUT)$(kvm_ioctl_array) \ | 846 | $(OUTPUT)$(kvm_ioctl_array) \ |
847 | $(OUTPUT)$(kcmp_type_array) \ | ||
831 | $(OUTPUT)$(vhost_virtio_ioctl_array) \ | 848 | $(OUTPUT)$(vhost_virtio_ioctl_array) \ |
832 | $(OUTPUT)$(perf_ioctl_array) | 849 | $(OUTPUT)$(perf_ioctl_array) \ |
850 | $(OUTPUT)$(prctl_option_array) | ||
833 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean | 851 | $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean |
834 | 852 | ||
835 | # | 853 | # |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index c38373195c4a..2d5c87578f83 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -356,7 +356,7 @@ static int __cmd_annotate(struct perf_annotate *ann) | |||
356 | } | 356 | } |
357 | 357 | ||
358 | if (total_nr_samples == 0) { | 358 | if (total_nr_samples == 0) { |
359 | ui__error("The %s file has no samples!\n", session->file->path); | 359 | ui__error("The %s file has no samples!\n", session->data->file.path); |
360 | goto out; | 360 | goto out; |
361 | } | 361 | } |
362 | 362 | ||
@@ -400,7 +400,7 @@ int cmd_annotate(int argc, const char **argv) | |||
400 | .ordering_requires_timestamps = true, | 400 | .ordering_requires_timestamps = true, |
401 | }, | 401 | }, |
402 | }; | 402 | }; |
403 | struct perf_data_file file = { | 403 | struct perf_data data = { |
404 | .mode = PERF_DATA_MODE_READ, | 404 | .mode = PERF_DATA_MODE_READ, |
405 | }; | 405 | }; |
406 | struct option options[] = { | 406 | struct option options[] = { |
@@ -410,7 +410,7 @@ int cmd_annotate(int argc, const char **argv) | |||
410 | "only consider symbols in these dsos"), | 410 | "only consider symbols in these dsos"), |
411 | OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", | 411 | OPT_STRING('s', "symbol", &annotate.sym_hist_filter, "symbol", |
412 | "symbol to annotate"), | 412 | "symbol to annotate"), |
413 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), | 413 | OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), |
414 | OPT_INCR('v', "verbose", &verbose, | 414 | OPT_INCR('v', "verbose", &verbose, |
415 | "be more verbose (show symbol address, etc)"), | 415 | "be more verbose (show symbol address, etc)"), |
416 | OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"), | 416 | OPT_BOOLEAN('q', "quiet", &quiet, "do now show any message"), |
@@ -482,9 +482,9 @@ int cmd_annotate(int argc, const char **argv) | |||
482 | if (quiet) | 482 | if (quiet) |
483 | perf_quiet_option(); | 483 | perf_quiet_option(); |
484 | 484 | ||
485 | file.path = input_name; | 485 | data.file.path = input_name; |
486 | 486 | ||
487 | annotate.session = perf_session__new(&file, false, &annotate.tool); | 487 | annotate.session = perf_session__new(&data, false, &annotate.tool); |
488 | if (annotate.session == NULL) | 488 | if (annotate.session == NULL) |
489 | return -1; | 489 | return -1; |
490 | 490 | ||
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index e3eb6240ced0..cb2453b29365 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -311,7 +311,7 @@ int cmd_buildid_cache(int argc, const char **argv) | |||
311 | *kcore_filename = NULL; | 311 | *kcore_filename = NULL; |
312 | char sbuf[STRERR_BUFSIZE]; | 312 | char sbuf[STRERR_BUFSIZE]; |
313 | 313 | ||
314 | struct perf_data_file file = { | 314 | struct perf_data data = { |
315 | .mode = PERF_DATA_MODE_READ, | 315 | .mode = PERF_DATA_MODE_READ, |
316 | }; | 316 | }; |
317 | struct perf_session *session = NULL; | 317 | struct perf_session *session = NULL; |
@@ -352,10 +352,10 @@ int cmd_buildid_cache(int argc, const char **argv) | |||
352 | nsi = nsinfo__new(ns_id); | 352 | nsi = nsinfo__new(ns_id); |
353 | 353 | ||
354 | if (missing_filename) { | 354 | if (missing_filename) { |
355 | file.path = missing_filename; | 355 | data.file.path = missing_filename; |
356 | file.force = force; | 356 | data.force = force; |
357 | 357 | ||
358 | session = perf_session__new(&file, false, NULL); | 358 | session = perf_session__new(&data, false, NULL); |
359 | if (session == NULL) | 359 | if (session == NULL) |
360 | return -1; | 360 | return -1; |
361 | } | 361 | } |
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index fdaca16e0c74..00099a830b0d 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c | |||
@@ -50,10 +50,12 @@ static bool dso__skip_buildid(struct dso *dso, int with_hits) | |||
50 | static int perf_session__list_build_ids(bool force, bool with_hits) | 50 | static int perf_session__list_build_ids(bool force, bool with_hits) |
51 | { | 51 | { |
52 | struct perf_session *session; | 52 | struct perf_session *session; |
53 | struct perf_data_file file = { | 53 | struct perf_data data = { |
54 | .path = input_name, | 54 | .file = { |
55 | .mode = PERF_DATA_MODE_READ, | 55 | .path = input_name, |
56 | .force = force, | 56 | }, |
57 | .mode = PERF_DATA_MODE_READ, | ||
58 | .force = force, | ||
57 | }; | 59 | }; |
58 | 60 | ||
59 | symbol__elf_init(); | 61 | symbol__elf_init(); |
@@ -63,7 +65,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits) | |||
63 | if (filename__fprintf_build_id(input_name, stdout) > 0) | 65 | if (filename__fprintf_build_id(input_name, stdout) > 0) |
64 | goto out; | 66 | goto out; |
65 | 67 | ||
66 | session = perf_session__new(&file, false, &build_id__mark_dso_hit_ops); | 68 | session = perf_session__new(&data, false, &build_id__mark_dso_hit_ops); |
67 | if (session == NULL) | 69 | if (session == NULL) |
68 | return -1; | 70 | return -1; |
69 | 71 | ||
@@ -71,7 +73,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits) | |||
71 | * We take all buildids when the file contains AUX area tracing data | 73 | * We take all buildids when the file contains AUX area tracing data |
72 | * because we do not decode the trace because it would take too long. | 74 | * because we do not decode the trace because it would take too long. |
73 | */ | 75 | */ |
74 | if (!perf_data_file__is_pipe(&file) && | 76 | if (!perf_data__is_pipe(&data) && |
75 | perf_header__has_feat(&session->header, HEADER_AUXTRACE)) | 77 | perf_header__has_feat(&session->header, HEADER_AUXTRACE)) |
76 | with_hits = false; | 78 | with_hits = false; |
77 | 79 | ||
@@ -79,7 +81,7 @@ static int perf_session__list_build_ids(bool force, bool with_hits) | |||
79 | * in pipe-mode, the only way to get the buildids is to parse | 81 | * in pipe-mode, the only way to get the buildids is to parse |
80 | * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID | 82 | * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID |
81 | */ | 83 | */ |
82 | if (with_hits || perf_data_file__is_pipe(&file)) | 84 | if (with_hits || perf_data__is_pipe(&data)) |
83 | perf_session__process_events(session); | 85 | perf_session__process_events(session); |
84 | 86 | ||
85 | perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); | 87 | perf_session__fprintf_dsos_buildid(session, stdout, dso__skip_buildid, with_hits); |
diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index bb1ee22bd221..9590fdcc6484 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c | |||
@@ -2523,7 +2523,7 @@ static int perf_c2c__report(int argc, const char **argv) | |||
2523 | { | 2523 | { |
2524 | struct perf_session *session; | 2524 | struct perf_session *session; |
2525 | struct ui_progress prog; | 2525 | struct ui_progress prog; |
2526 | struct perf_data_file file = { | 2526 | struct perf_data data = { |
2527 | .mode = PERF_DATA_MODE_READ, | 2527 | .mode = PERF_DATA_MODE_READ, |
2528 | }; | 2528 | }; |
2529 | char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; | 2529 | char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; |
@@ -2572,8 +2572,8 @@ static int perf_c2c__report(int argc, const char **argv) | |||
2572 | if (!input_name || !strlen(input_name)) | 2572 | if (!input_name || !strlen(input_name)) |
2573 | input_name = "perf.data"; | 2573 | input_name = "perf.data"; |
2574 | 2574 | ||
2575 | file.path = input_name; | 2575 | data.file.path = input_name; |
2576 | file.force = symbol_conf.force; | 2576 | data.force = symbol_conf.force; |
2577 | 2577 | ||
2578 | err = setup_display(display); | 2578 | err = setup_display(display); |
2579 | if (err) | 2579 | if (err) |
@@ -2591,7 +2591,7 @@ static int perf_c2c__report(int argc, const char **argv) | |||
2591 | goto out; | 2591 | goto out; |
2592 | } | 2592 | } |
2593 | 2593 | ||
2594 | session = perf_session__new(&file, 0, &c2c.tool); | 2594 | session = perf_session__new(&data, 0, &c2c.tool); |
2595 | if (session == NULL) { | 2595 | if (session == NULL) { |
2596 | pr_debug("No memory for session\n"); | 2596 | pr_debug("No memory for session\n"); |
2597 | goto out; | 2597 | goto out; |
@@ -2611,7 +2611,7 @@ static int perf_c2c__report(int argc, const char **argv) | |||
2611 | goto out_session; | 2611 | goto out_session; |
2612 | 2612 | ||
2613 | /* No pipe support at the moment. */ | 2613 | /* No pipe support at the moment. */ |
2614 | if (perf_data_file__is_pipe(session->file)) { | 2614 | if (perf_data__is_pipe(session->data)) { |
2615 | pr_debug("No pipe support at the moment.\n"); | 2615 | pr_debug("No pipe support at the moment.\n"); |
2616 | goto out_session; | 2616 | goto out_session; |
2617 | } | 2617 | } |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 0cd4cf6a344b..67570e6417e5 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -47,7 +47,7 @@ struct diff_hpp_fmt { | |||
47 | 47 | ||
48 | struct data__file { | 48 | struct data__file { |
49 | struct perf_session *session; | 49 | struct perf_session *session; |
50 | struct perf_data_file file; | 50 | struct perf_data data; |
51 | int idx; | 51 | int idx; |
52 | struct hists *hists; | 52 | struct hists *hists; |
53 | struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; | 53 | struct diff_hpp_fmt fmt[PERF_HPP_DIFF__MAX_INDEX]; |
@@ -707,7 +707,7 @@ static void data__fprintf(void) | |||
707 | 707 | ||
708 | data__for_each_file(i, d) | 708 | data__for_each_file(i, d) |
709 | fprintf(stdout, "# [%d] %s %s\n", | 709 | fprintf(stdout, "# [%d] %s %s\n", |
710 | d->idx, d->file.path, | 710 | d->idx, d->data.file.path, |
711 | !d->idx ? "(Baseline)" : ""); | 711 | !d->idx ? "(Baseline)" : ""); |
712 | 712 | ||
713 | fprintf(stdout, "#\n"); | 713 | fprintf(stdout, "#\n"); |
@@ -776,16 +776,16 @@ static int __cmd_diff(void) | |||
776 | int ret = -EINVAL, i; | 776 | int ret = -EINVAL, i; |
777 | 777 | ||
778 | data__for_each_file(i, d) { | 778 | data__for_each_file(i, d) { |
779 | d->session = perf_session__new(&d->file, false, &tool); | 779 | d->session = perf_session__new(&d->data, false, &tool); |
780 | if (!d->session) { | 780 | if (!d->session) { |
781 | pr_err("Failed to open %s\n", d->file.path); | 781 | pr_err("Failed to open %s\n", d->data.file.path); |
782 | ret = -1; | 782 | ret = -1; |
783 | goto out_delete; | 783 | goto out_delete; |
784 | } | 784 | } |
785 | 785 | ||
786 | ret = perf_session__process_events(d->session); | 786 | ret = perf_session__process_events(d->session); |
787 | if (ret) { | 787 | if (ret) { |
788 | pr_err("Failed to process %s\n", d->file.path); | 788 | pr_err("Failed to process %s\n", d->data.file.path); |
789 | goto out_delete; | 789 | goto out_delete; |
790 | } | 790 | } |
791 | 791 | ||
@@ -1286,11 +1286,11 @@ static int data_init(int argc, const char **argv) | |||
1286 | return -ENOMEM; | 1286 | return -ENOMEM; |
1287 | 1287 | ||
1288 | data__for_each_file(i, d) { | 1288 | data__for_each_file(i, d) { |
1289 | struct perf_data_file *file = &d->file; | 1289 | struct perf_data *data = &d->data; |
1290 | 1290 | ||
1291 | file->path = use_default ? defaults[i] : argv[i]; | 1291 | data->file.path = use_default ? defaults[i] : argv[i]; |
1292 | file->mode = PERF_DATA_MODE_READ, | 1292 | data->mode = PERF_DATA_MODE_READ, |
1293 | file->force = force, | 1293 | data->force = force, |
1294 | 1294 | ||
1295 | d->idx = i; | 1295 | d->idx = i; |
1296 | } | 1296 | } |
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 6d210e40d611..93b85dc857b6 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c | |||
@@ -21,14 +21,16 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details | |||
21 | { | 21 | { |
22 | struct perf_session *session; | 22 | struct perf_session *session; |
23 | struct perf_evsel *pos; | 23 | struct perf_evsel *pos; |
24 | struct perf_data_file file = { | 24 | struct perf_data data = { |
25 | .path = file_name, | 25 | .file = { |
26 | .mode = PERF_DATA_MODE_READ, | 26 | .path = file_name, |
27 | .force = details->force, | 27 | }, |
28 | .mode = PERF_DATA_MODE_READ, | ||
29 | .force = details->force, | ||
28 | }; | 30 | }; |
29 | bool has_tracepoint = false; | 31 | bool has_tracepoint = false; |
30 | 32 | ||
31 | session = perf_session__new(&file, 0, NULL); | 33 | session = perf_session__new(&data, 0, NULL); |
32 | if (session == NULL) | 34 | if (session == NULL) |
33 | return -1; | 35 | return -1; |
34 | 36 | ||
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 2b8032908fb2..91e65093d3c2 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -35,7 +35,7 @@ struct perf_inject { | |||
35 | bool strip; | 35 | bool strip; |
36 | bool jit_mode; | 36 | bool jit_mode; |
37 | const char *input_name; | 37 | const char *input_name; |
38 | struct perf_data_file output; | 38 | struct perf_data output; |
39 | u64 bytes_written; | 39 | u64 bytes_written; |
40 | u64 aux_id; | 40 | u64 aux_id; |
41 | struct list_head samples; | 41 | struct list_head samples; |
@@ -52,7 +52,7 @@ static int output_bytes(struct perf_inject *inject, void *buf, size_t sz) | |||
52 | { | 52 | { |
53 | ssize_t size; | 53 | ssize_t size; |
54 | 54 | ||
55 | size = perf_data_file__write(&inject->output, buf, sz); | 55 | size = perf_data__write(&inject->output, buf, sz); |
56 | if (size < 0) | 56 | if (size < 0) |
57 | return -errno; | 57 | return -errno; |
58 | 58 | ||
@@ -145,7 +145,7 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, | |||
145 | if (!inject->output.is_pipe) { | 145 | if (!inject->output.is_pipe) { |
146 | off_t offset; | 146 | off_t offset; |
147 | 147 | ||
148 | offset = lseek(inject->output.fd, 0, SEEK_CUR); | 148 | offset = lseek(inject->output.file.fd, 0, SEEK_CUR); |
149 | if (offset == -1) | 149 | if (offset == -1) |
150 | return -errno; | 150 | return -errno; |
151 | ret = auxtrace_index__auxtrace_event(&session->auxtrace_index, | 151 | ret = auxtrace_index__auxtrace_event(&session->auxtrace_index, |
@@ -154,11 +154,11 @@ static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, | |||
154 | return ret; | 154 | return ret; |
155 | } | 155 | } |
156 | 156 | ||
157 | if (perf_data_file__is_pipe(session->file) || !session->one_mmap) { | 157 | if (perf_data__is_pipe(session->data) || !session->one_mmap) { |
158 | ret = output_bytes(inject, event, event->header.size); | 158 | ret = output_bytes(inject, event, event->header.size); |
159 | if (ret < 0) | 159 | if (ret < 0) |
160 | return ret; | 160 | return ret; |
161 | ret = copy_bytes(inject, perf_data_file__fd(session->file), | 161 | ret = copy_bytes(inject, perf_data__fd(session->data), |
162 | event->auxtrace.size); | 162 | event->auxtrace.size); |
163 | } else { | 163 | } else { |
164 | ret = output_bytes(inject, event, | 164 | ret = output_bytes(inject, event, |
@@ -637,8 +637,8 @@ static int __cmd_inject(struct perf_inject *inject) | |||
637 | { | 637 | { |
638 | int ret = -EINVAL; | 638 | int ret = -EINVAL; |
639 | struct perf_session *session = inject->session; | 639 | struct perf_session *session = inject->session; |
640 | struct perf_data_file *file_out = &inject->output; | 640 | struct perf_data *data_out = &inject->output; |
641 | int fd = perf_data_file__fd(file_out); | 641 | int fd = perf_data__fd(data_out); |
642 | u64 output_data_offset; | 642 | u64 output_data_offset; |
643 | 643 | ||
644 | signal(SIGINT, sig_handler); | 644 | signal(SIGINT, sig_handler); |
@@ -693,14 +693,14 @@ static int __cmd_inject(struct perf_inject *inject) | |||
693 | if (!inject->itrace_synth_opts.set) | 693 | if (!inject->itrace_synth_opts.set) |
694 | auxtrace_index__free(&session->auxtrace_index); | 694 | auxtrace_index__free(&session->auxtrace_index); |
695 | 695 | ||
696 | if (!file_out->is_pipe) | 696 | if (!data_out->is_pipe) |
697 | lseek(fd, output_data_offset, SEEK_SET); | 697 | lseek(fd, output_data_offset, SEEK_SET); |
698 | 698 | ||
699 | ret = perf_session__process_events(session); | 699 | ret = perf_session__process_events(session); |
700 | if (ret) | 700 | if (ret) |
701 | return ret; | 701 | return ret; |
702 | 702 | ||
703 | if (!file_out->is_pipe) { | 703 | if (!data_out->is_pipe) { |
704 | if (inject->build_ids) | 704 | if (inject->build_ids) |
705 | perf_header__set_feat(&session->header, | 705 | perf_header__set_feat(&session->header, |
706 | HEADER_BUILD_ID); | 706 | HEADER_BUILD_ID); |
@@ -775,11 +775,13 @@ int cmd_inject(int argc, const char **argv) | |||
775 | .input_name = "-", | 775 | .input_name = "-", |
776 | .samples = LIST_HEAD_INIT(inject.samples), | 776 | .samples = LIST_HEAD_INIT(inject.samples), |
777 | .output = { | 777 | .output = { |
778 | .path = "-", | 778 | .file = { |
779 | .mode = PERF_DATA_MODE_WRITE, | 779 | .path = "-", |
780 | }, | ||
781 | .mode = PERF_DATA_MODE_WRITE, | ||
780 | }, | 782 | }, |
781 | }; | 783 | }; |
782 | struct perf_data_file file = { | 784 | struct perf_data data = { |
783 | .mode = PERF_DATA_MODE_READ, | 785 | .mode = PERF_DATA_MODE_READ, |
784 | }; | 786 | }; |
785 | int ret; | 787 | int ret; |
@@ -789,7 +791,7 @@ int cmd_inject(int argc, const char **argv) | |||
789 | "Inject build-ids into the output stream"), | 791 | "Inject build-ids into the output stream"), |
790 | OPT_STRING('i', "input", &inject.input_name, "file", | 792 | OPT_STRING('i', "input", &inject.input_name, "file", |
791 | "input file name"), | 793 | "input file name"), |
792 | OPT_STRING('o', "output", &inject.output.path, "file", | 794 | OPT_STRING('o', "output", &inject.output.file.path, "file", |
793 | "output file name"), | 795 | "output file name"), |
794 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, | 796 | OPT_BOOLEAN('s', "sched-stat", &inject.sched_stat, |
795 | "Merge sched-stat and sched-switch for getting events " | 797 | "Merge sched-stat and sched-switch for getting events " |
@@ -801,7 +803,7 @@ int cmd_inject(int argc, const char **argv) | |||
801 | "be more verbose (show build ids, etc)"), | 803 | "be more verbose (show build ids, etc)"), |
802 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", | 804 | OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file", |
803 | "kallsyms pathname"), | 805 | "kallsyms pathname"), |
804 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), | 806 | OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), |
805 | OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, | 807 | OPT_CALLBACK_OPTARG(0, "itrace", &inject.itrace_synth_opts, |
806 | NULL, "opts", "Instruction Tracing options", | 808 | NULL, "opts", "Instruction Tracing options", |
807 | itrace_parse_synth_opts), | 809 | itrace_parse_synth_opts), |
@@ -829,15 +831,15 @@ int cmd_inject(int argc, const char **argv) | |||
829 | return -1; | 831 | return -1; |
830 | } | 832 | } |
831 | 833 | ||
832 | if (perf_data_file__open(&inject.output)) { | 834 | if (perf_data__open(&inject.output)) { |
833 | perror("failed to create output file"); | 835 | perror("failed to create output file"); |
834 | return -1; | 836 | return -1; |
835 | } | 837 | } |
836 | 838 | ||
837 | inject.tool.ordered_events = inject.sched_stat; | 839 | inject.tool.ordered_events = inject.sched_stat; |
838 | 840 | ||
839 | file.path = inject.input_name; | 841 | data.file.path = inject.input_name; |
840 | inject.session = perf_session__new(&file, true, &inject.tool); | 842 | inject.session = perf_session__new(&data, true, &inject.tool); |
841 | if (inject.session == NULL) | 843 | if (inject.session == NULL) |
842 | return -1; | 844 | return -1; |
843 | 845 | ||
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index d8f25ef8157b..abcab75cc5b9 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -1893,7 +1893,7 @@ int cmd_kmem(int argc, const char **argv) | |||
1893 | { | 1893 | { |
1894 | const char * const default_slab_sort = "frag,hit,bytes"; | 1894 | const char * const default_slab_sort = "frag,hit,bytes"; |
1895 | const char * const default_page_sort = "bytes,hit"; | 1895 | const char * const default_page_sort = "bytes,hit"; |
1896 | struct perf_data_file file = { | 1896 | struct perf_data data = { |
1897 | .mode = PERF_DATA_MODE_READ, | 1897 | .mode = PERF_DATA_MODE_READ, |
1898 | }; | 1898 | }; |
1899 | const struct option kmem_options[] = { | 1899 | const struct option kmem_options[] = { |
@@ -1909,7 +1909,7 @@ int cmd_kmem(int argc, const char **argv) | |||
1909 | "page, order, migtype, gfp", parse_sort_opt), | 1909 | "page, order, migtype, gfp", parse_sort_opt), |
1910 | OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), | 1910 | OPT_CALLBACK('l', "line", NULL, "num", "show n lines", parse_line_opt), |
1911 | OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), | 1911 | OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"), |
1912 | OPT_BOOLEAN('f', "force", &file.force, "don't complain, do it"), | 1912 | OPT_BOOLEAN('f', "force", &data.force, "don't complain, do it"), |
1913 | OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator", | 1913 | OPT_CALLBACK_NOOPT(0, "slab", NULL, NULL, "Analyze slab allocator", |
1914 | parse_slab_opt), | 1914 | parse_slab_opt), |
1915 | OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", | 1915 | OPT_CALLBACK_NOOPT(0, "page", NULL, NULL, "Analyze page allocator", |
@@ -1949,9 +1949,9 @@ int cmd_kmem(int argc, const char **argv) | |||
1949 | return __cmd_record(argc, argv); | 1949 | return __cmd_record(argc, argv); |
1950 | } | 1950 | } |
1951 | 1951 | ||
1952 | file.path = input_name; | 1952 | data.file.path = input_name; |
1953 | 1953 | ||
1954 | kmem_session = session = perf_session__new(&file, false, &perf_kmem); | 1954 | kmem_session = session = perf_session__new(&data, false, &perf_kmem); |
1955 | if (session == NULL) | 1955 | if (session == NULL) |
1956 | return -1; | 1956 | return -1; |
1957 | 1957 | ||
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 721f4f91291a..0af4c092b471 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -1067,10 +1067,12 @@ static int read_events(struct perf_kvm_stat *kvm) | |||
1067 | .namespaces = perf_event__process_namespaces, | 1067 | .namespaces = perf_event__process_namespaces, |
1068 | .ordered_events = true, | 1068 | .ordered_events = true, |
1069 | }; | 1069 | }; |
1070 | struct perf_data_file file = { | 1070 | struct perf_data file = { |
1071 | .path = kvm->file_name, | 1071 | .file = { |
1072 | .mode = PERF_DATA_MODE_READ, | 1072 | .path = kvm->file_name, |
1073 | .force = kvm->force, | 1073 | }, |
1074 | .mode = PERF_DATA_MODE_READ, | ||
1075 | .force = kvm->force, | ||
1074 | }; | 1076 | }; |
1075 | 1077 | ||
1076 | kvm->tool = eops; | 1078 | kvm->tool = eops; |
@@ -1358,7 +1360,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1358 | "perf kvm stat live [<options>]", | 1360 | "perf kvm stat live [<options>]", |
1359 | NULL | 1361 | NULL |
1360 | }; | 1362 | }; |
1361 | struct perf_data_file file = { | 1363 | struct perf_data data = { |
1362 | .mode = PERF_DATA_MODE_WRITE, | 1364 | .mode = PERF_DATA_MODE_WRITE, |
1363 | }; | 1365 | }; |
1364 | 1366 | ||
@@ -1432,7 +1434,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1432 | /* | 1434 | /* |
1433 | * perf session | 1435 | * perf session |
1434 | */ | 1436 | */ |
1435 | kvm->session = perf_session__new(&file, false, &kvm->tool); | 1437 | kvm->session = perf_session__new(&data, false, &kvm->tool); |
1436 | if (kvm->session == NULL) { | 1438 | if (kvm->session == NULL) { |
1437 | err = -1; | 1439 | err = -1; |
1438 | goto out; | 1440 | goto out; |
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index ff98652484a7..81af29400b64 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c | |||
@@ -864,13 +864,15 @@ static int __cmd_report(bool display_info) | |||
864 | .namespaces = perf_event__process_namespaces, | 864 | .namespaces = perf_event__process_namespaces, |
865 | .ordered_events = true, | 865 | .ordered_events = true, |
866 | }; | 866 | }; |
867 | struct perf_data_file file = { | 867 | struct perf_data data = { |
868 | .path = input_name, | 868 | .file = { |
869 | .mode = PERF_DATA_MODE_READ, | 869 | .path = input_name, |
870 | .force = force, | 870 | }, |
871 | .mode = PERF_DATA_MODE_READ, | ||
872 | .force = force, | ||
871 | }; | 873 | }; |
872 | 874 | ||
873 | session = perf_session__new(&file, false, &eops); | 875 | session = perf_session__new(&data, false, &eops); |
874 | if (!session) { | 876 | if (!session) { |
875 | pr_err("Initializing perf session failed\n"); | 877 | pr_err("Initializing perf session failed\n"); |
876 | return -1; | 878 | return -1; |
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 6940490bc3f9..f09fd1a1b813 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -236,13 +236,15 @@ static int process_sample_event(struct perf_tool *tool, | |||
236 | 236 | ||
237 | static int report_raw_events(struct perf_mem *mem) | 237 | static int report_raw_events(struct perf_mem *mem) |
238 | { | 238 | { |
239 | struct perf_data_file file = { | 239 | struct perf_data data = { |
240 | .path = input_name, | 240 | .file = { |
241 | .mode = PERF_DATA_MODE_READ, | 241 | .path = input_name, |
242 | .force = mem->force, | 242 | }, |
243 | .mode = PERF_DATA_MODE_READ, | ||
244 | .force = mem->force, | ||
243 | }; | 245 | }; |
244 | int ret; | 246 | int ret; |
245 | struct perf_session *session = perf_session__new(&file, false, | 247 | struct perf_session *session = perf_session__new(&data, false, |
246 | &mem->tool); | 248 | &mem->tool); |
247 | 249 | ||
248 | if (session == NULL) | 250 | if (session == NULL) |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a6cbf1640269..f4d9fc54b382 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -66,7 +66,7 @@ struct record { | |||
66 | struct perf_tool tool; | 66 | struct perf_tool tool; |
67 | struct record_opts opts; | 67 | struct record_opts opts; |
68 | u64 bytes_written; | 68 | u64 bytes_written; |
69 | struct perf_data_file file; | 69 | struct perf_data data; |
70 | struct auxtrace_record *itr; | 70 | struct auxtrace_record *itr; |
71 | struct perf_evlist *evlist; | 71 | struct perf_evlist *evlist; |
72 | struct perf_session *session; | 72 | struct perf_session *session; |
@@ -107,7 +107,7 @@ static bool switch_output_time(struct record *rec) | |||
107 | 107 | ||
108 | static int record__write(struct record *rec, void *bf, size_t size) | 108 | static int record__write(struct record *rec, void *bf, size_t size) |
109 | { | 109 | { |
110 | if (perf_data_file__write(rec->session->file, bf, size) < 0) { | 110 | if (perf_data__write(rec->session->data, bf, size) < 0) { |
111 | pr_err("failed to write perf data, error: %m\n"); | 111 | pr_err("failed to write perf data, error: %m\n"); |
112 | return -1; | 112 | return -1; |
113 | } | 113 | } |
@@ -173,13 +173,13 @@ static int record__process_auxtrace(struct perf_tool *tool, | |||
173 | size_t len1, void *data2, size_t len2) | 173 | size_t len1, void *data2, size_t len2) |
174 | { | 174 | { |
175 | struct record *rec = container_of(tool, struct record, tool); | 175 | struct record *rec = container_of(tool, struct record, tool); |
176 | struct perf_data_file *file = &rec->file; | 176 | struct perf_data *data = &rec->data; |
177 | size_t padding; | 177 | size_t padding; |
178 | u8 pad[8] = {0}; | 178 | u8 pad[8] = {0}; |
179 | 179 | ||
180 | if (!perf_data_file__is_pipe(file)) { | 180 | if (!perf_data__is_pipe(data)) { |
181 | off_t file_offset; | 181 | off_t file_offset; |
182 | int fd = perf_data_file__fd(file); | 182 | int fd = perf_data__fd(data); |
183 | int err; | 183 | int err; |
184 | 184 | ||
185 | file_offset = lseek(fd, 0, SEEK_CUR); | 185 | file_offset = lseek(fd, 0, SEEK_CUR); |
@@ -398,10 +398,10 @@ static int process_sample_event(struct perf_tool *tool, | |||
398 | 398 | ||
399 | static int process_buildids(struct record *rec) | 399 | static int process_buildids(struct record *rec) |
400 | { | 400 | { |
401 | struct perf_data_file *file = &rec->file; | 401 | struct perf_data *data = &rec->data; |
402 | struct perf_session *session = rec->session; | 402 | struct perf_session *session = rec->session; |
403 | 403 | ||
404 | if (file->size == 0) | 404 | if (data->size == 0) |
405 | return 0; | 405 | return 0; |
406 | 406 | ||
407 | /* | 407 | /* |
@@ -544,14 +544,14 @@ static void record__init_features(struct record *rec) | |||
544 | static void | 544 | static void |
545 | record__finish_output(struct record *rec) | 545 | record__finish_output(struct record *rec) |
546 | { | 546 | { |
547 | struct perf_data_file *file = &rec->file; | 547 | struct perf_data *data = &rec->data; |
548 | int fd = perf_data_file__fd(file); | 548 | int fd = perf_data__fd(data); |
549 | 549 | ||
550 | if (file->is_pipe) | 550 | if (data->is_pipe) |
551 | return; | 551 | return; |
552 | 552 | ||
553 | rec->session->header.data_size += rec->bytes_written; | 553 | rec->session->header.data_size += rec->bytes_written; |
554 | file->size = lseek(perf_data_file__fd(file), 0, SEEK_CUR); | 554 | data->size = lseek(perf_data__fd(data), 0, SEEK_CUR); |
555 | 555 | ||
556 | if (!rec->no_buildid) { | 556 | if (!rec->no_buildid) { |
557 | process_buildids(rec); | 557 | process_buildids(rec); |
@@ -590,7 +590,7 @@ static int record__synthesize(struct record *rec, bool tail); | |||
590 | static int | 590 | static int |
591 | record__switch_output(struct record *rec, bool at_exit) | 591 | record__switch_output(struct record *rec, bool at_exit) |
592 | { | 592 | { |
593 | struct perf_data_file *file = &rec->file; | 593 | struct perf_data *data = &rec->data; |
594 | int fd, err; | 594 | int fd, err; |
595 | 595 | ||
596 | /* Same Size: "2015122520103046"*/ | 596 | /* Same Size: "2015122520103046"*/ |
@@ -608,7 +608,7 @@ record__switch_output(struct record *rec, bool at_exit) | |||
608 | return -EINVAL; | 608 | return -EINVAL; |
609 | } | 609 | } |
610 | 610 | ||
611 | fd = perf_data_file__switch(file, timestamp, | 611 | fd = perf_data__switch(data, timestamp, |
612 | rec->session->header.data_offset, | 612 | rec->session->header.data_offset, |
613 | at_exit); | 613 | at_exit); |
614 | if (fd >= 0 && !at_exit) { | 614 | if (fd >= 0 && !at_exit) { |
@@ -618,7 +618,7 @@ record__switch_output(struct record *rec, bool at_exit) | |||
618 | 618 | ||
619 | if (!quiet) | 619 | if (!quiet) |
620 | fprintf(stderr, "[ perf record: Dump %s.%s ]\n", | 620 | fprintf(stderr, "[ perf record: Dump %s.%s ]\n", |
621 | file->path, timestamp); | 621 | data->file.path, timestamp); |
622 | 622 | ||
623 | /* Output tracking events */ | 623 | /* Output tracking events */ |
624 | if (!at_exit) { | 624 | if (!at_exit) { |
@@ -693,16 +693,16 @@ static int record__synthesize(struct record *rec, bool tail) | |||
693 | { | 693 | { |
694 | struct perf_session *session = rec->session; | 694 | struct perf_session *session = rec->session; |
695 | struct machine *machine = &session->machines.host; | 695 | struct machine *machine = &session->machines.host; |
696 | struct perf_data_file *file = &rec->file; | 696 | struct perf_data *data = &rec->data; |
697 | struct record_opts *opts = &rec->opts; | 697 | struct record_opts *opts = &rec->opts; |
698 | struct perf_tool *tool = &rec->tool; | 698 | struct perf_tool *tool = &rec->tool; |
699 | int fd = perf_data_file__fd(file); | 699 | int fd = perf_data__fd(data); |
700 | int err = 0; | 700 | int err = 0; |
701 | 701 | ||
702 | if (rec->opts.tail_synthesize != tail) | 702 | if (rec->opts.tail_synthesize != tail) |
703 | return 0; | 703 | return 0; |
704 | 704 | ||
705 | if (file->is_pipe) { | 705 | if (data->is_pipe) { |
706 | err = perf_event__synthesize_features( | 706 | err = perf_event__synthesize_features( |
707 | tool, session, rec->evlist, process_synthesized_event); | 707 | tool, session, rec->evlist, process_synthesized_event); |
708 | if (err < 0) { | 708 | if (err < 0) { |
@@ -781,7 +781,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
781 | struct machine *machine; | 781 | struct machine *machine; |
782 | struct perf_tool *tool = &rec->tool; | 782 | struct perf_tool *tool = &rec->tool; |
783 | struct record_opts *opts = &rec->opts; | 783 | struct record_opts *opts = &rec->opts; |
784 | struct perf_data_file *file = &rec->file; | 784 | struct perf_data *data = &rec->data; |
785 | struct perf_session *session; | 785 | struct perf_session *session; |
786 | bool disabled = false, draining = false; | 786 | bool disabled = false, draining = false; |
787 | int fd; | 787 | int fd; |
@@ -807,20 +807,20 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
807 | signal(SIGUSR2, SIG_IGN); | 807 | signal(SIGUSR2, SIG_IGN); |
808 | } | 808 | } |
809 | 809 | ||
810 | session = perf_session__new(file, false, tool); | 810 | session = perf_session__new(data, false, tool); |
811 | if (session == NULL) { | 811 | if (session == NULL) { |
812 | pr_err("Perf session creation failed.\n"); | 812 | pr_err("Perf session creation failed.\n"); |
813 | return -1; | 813 | return -1; |
814 | } | 814 | } |
815 | 815 | ||
816 | fd = perf_data_file__fd(file); | 816 | fd = perf_data__fd(data); |
817 | rec->session = session; | 817 | rec->session = session; |
818 | 818 | ||
819 | record__init_features(rec); | 819 | record__init_features(rec); |
820 | 820 | ||
821 | if (forks) { | 821 | if (forks) { |
822 | err = perf_evlist__prepare_workload(rec->evlist, &opts->target, | 822 | err = perf_evlist__prepare_workload(rec->evlist, &opts->target, |
823 | argv, file->is_pipe, | 823 | argv, data->is_pipe, |
824 | workload_exec_failed_signal); | 824 | workload_exec_failed_signal); |
825 | if (err < 0) { | 825 | if (err < 0) { |
826 | pr_err("Couldn't run the workload!\n"); | 826 | pr_err("Couldn't run the workload!\n"); |
@@ -856,7 +856,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) | |||
856 | if (!rec->evlist->nr_groups) | 856 | if (!rec->evlist->nr_groups) |
857 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); | 857 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); |
858 | 858 | ||
859 | if (file->is_pipe) { | 859 | if (data->is_pipe) { |
860 | err = perf_header__write_pipe(fd); | 860 | err = perf_header__write_pipe(fd); |
861 | if (err < 0) | 861 | if (err < 0) |
862 | goto out_child; | 862 | goto out_child; |
@@ -1117,8 +1117,8 @@ out_child: | |||
1117 | samples[0] = '\0'; | 1117 | samples[0] = '\0'; |
1118 | 1118 | ||
1119 | fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", | 1119 | fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n", |
1120 | perf_data_file__size(file) / 1024.0 / 1024.0, | 1120 | perf_data__size(data) / 1024.0 / 1024.0, |
1121 | file->path, postfix, samples); | 1121 | data->file.path, postfix, samples); |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | out_delete_session: | 1124 | out_delete_session: |
@@ -1482,7 +1482,7 @@ static struct option __record_options[] = { | |||
1482 | OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", | 1482 | OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu", |
1483 | "list of cpus to monitor"), | 1483 | "list of cpus to monitor"), |
1484 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), | 1484 | OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"), |
1485 | OPT_STRING('o', "output", &record.file.path, "file", | 1485 | OPT_STRING('o', "output", &record.data.file.path, "file", |
1486 | "output file name"), | 1486 | "output file name"), |
1487 | OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, | 1487 | OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, |
1488 | &record.opts.no_inherit_set, | 1488 | &record.opts.no_inherit_set, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f9dff652dcbd..3c2d9d4932f3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -257,7 +257,7 @@ static int report__setup_sample_type(struct report *rep) | |||
257 | { | 257 | { |
258 | struct perf_session *session = rep->session; | 258 | struct perf_session *session = rep->session; |
259 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); | 259 | u64 sample_type = perf_evlist__combined_sample_type(session->evlist); |
260 | bool is_pipe = perf_data_file__is_pipe(session->file); | 260 | bool is_pipe = perf_data__is_pipe(session->data); |
261 | 261 | ||
262 | if (session->itrace_synth_opts->callchain || | 262 | if (session->itrace_synth_opts->callchain || |
263 | (!is_pipe && | 263 | (!is_pipe && |
@@ -568,7 +568,7 @@ static int __cmd_report(struct report *rep) | |||
568 | int ret; | 568 | int ret; |
569 | struct perf_session *session = rep->session; | 569 | struct perf_session *session = rep->session; |
570 | struct perf_evsel *pos; | 570 | struct perf_evsel *pos; |
571 | struct perf_data_file *file = session->file; | 571 | struct perf_data *data = session->data; |
572 | 572 | ||
573 | signal(SIGINT, sig_handler); | 573 | signal(SIGINT, sig_handler); |
574 | 574 | ||
@@ -637,7 +637,7 @@ static int __cmd_report(struct report *rep) | |||
637 | rep->nr_entries += evsel__hists(pos)->nr_entries; | 637 | rep->nr_entries += evsel__hists(pos)->nr_entries; |
638 | 638 | ||
639 | if (rep->nr_entries == 0) { | 639 | if (rep->nr_entries == 0) { |
640 | ui__error("The %s file has no samples!\n", file->path); | 640 | ui__error("The %s file has no samples!\n", data->file.path); |
641 | return 0; | 641 | return 0; |
642 | } | 642 | } |
643 | 643 | ||
@@ -879,7 +879,7 @@ int cmd_report(int argc, const char **argv) | |||
879 | "Show inline function"), | 879 | "Show inline function"), |
880 | OPT_END() | 880 | OPT_END() |
881 | }; | 881 | }; |
882 | struct perf_data_file file = { | 882 | struct perf_data data = { |
883 | .mode = PERF_DATA_MODE_READ, | 883 | .mode = PERF_DATA_MODE_READ, |
884 | }; | 884 | }; |
885 | int ret = hists__init(); | 885 | int ret = hists__init(); |
@@ -940,11 +940,11 @@ int cmd_report(int argc, const char **argv) | |||
940 | input_name = "perf.data"; | 940 | input_name = "perf.data"; |
941 | } | 941 | } |
942 | 942 | ||
943 | file.path = input_name; | 943 | data.file.path = input_name; |
944 | file.force = symbol_conf.force; | 944 | data.force = symbol_conf.force; |
945 | 945 | ||
946 | repeat: | 946 | repeat: |
947 | session = perf_session__new(&file, false, &report.tool); | 947 | session = perf_session__new(&data, false, &report.tool); |
948 | if (session == NULL) | 948 | if (session == NULL) |
949 | return -1; | 949 | return -1; |
950 | 950 | ||
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index b7e8812ee80c..47e54348b5ed 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1700,14 +1700,16 @@ static int perf_sched__read_events(struct perf_sched *sched) | |||
1700 | { "sched:sched_migrate_task", process_sched_migrate_task_event, }, | 1700 | { "sched:sched_migrate_task", process_sched_migrate_task_event, }, |
1701 | }; | 1701 | }; |
1702 | struct perf_session *session; | 1702 | struct perf_session *session; |
1703 | struct perf_data_file file = { | 1703 | struct perf_data data = { |
1704 | .path = input_name, | 1704 | .file = { |
1705 | .mode = PERF_DATA_MODE_READ, | 1705 | .path = input_name, |
1706 | .force = sched->force, | 1706 | }, |
1707 | .mode = PERF_DATA_MODE_READ, | ||
1708 | .force = sched->force, | ||
1707 | }; | 1709 | }; |
1708 | int rc = -1; | 1710 | int rc = -1; |
1709 | 1711 | ||
1710 | session = perf_session__new(&file, false, &sched->tool); | 1712 | session = perf_session__new(&data, false, &sched->tool); |
1711 | if (session == NULL) { | 1713 | if (session == NULL) { |
1712 | pr_debug("No Memory for session\n"); | 1714 | pr_debug("No Memory for session\n"); |
1713 | return -1; | 1715 | return -1; |
@@ -2902,10 +2904,12 @@ static int perf_sched__timehist(struct perf_sched *sched) | |||
2902 | const struct perf_evsel_str_handler migrate_handlers[] = { | 2904 | const struct perf_evsel_str_handler migrate_handlers[] = { |
2903 | { "sched:sched_migrate_task", timehist_migrate_task_event, }, | 2905 | { "sched:sched_migrate_task", timehist_migrate_task_event, }, |
2904 | }; | 2906 | }; |
2905 | struct perf_data_file file = { | 2907 | struct perf_data data = { |
2906 | .path = input_name, | 2908 | .file = { |
2907 | .mode = PERF_DATA_MODE_READ, | 2909 | .path = input_name, |
2908 | .force = sched->force, | 2910 | }, |
2911 | .mode = PERF_DATA_MODE_READ, | ||
2912 | .force = sched->force, | ||
2909 | }; | 2913 | }; |
2910 | 2914 | ||
2911 | struct perf_session *session; | 2915 | struct perf_session *session; |
@@ -2930,7 +2934,7 @@ static int perf_sched__timehist(struct perf_sched *sched) | |||
2930 | 2934 | ||
2931 | symbol_conf.use_callchain = sched->show_callchain; | 2935 | symbol_conf.use_callchain = sched->show_callchain; |
2932 | 2936 | ||
2933 | session = perf_session__new(&file, false, &sched->tool); | 2937 | session = perf_session__new(&data, false, &sched->tool); |
2934 | if (session == NULL) | 2938 | if (session == NULL) |
2935 | return -ENOMEM; | 2939 | return -ENOMEM; |
2936 | 2940 | ||
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a3add2cd7856..89975e30c0ba 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -210,6 +210,51 @@ static struct { | |||
210 | }, | 210 | }, |
211 | }; | 211 | }; |
212 | 212 | ||
213 | struct perf_evsel_script { | ||
214 | char *filename; | ||
215 | FILE *fp; | ||
216 | u64 samples; | ||
217 | }; | ||
218 | |||
219 | static struct perf_evsel_script *perf_evsel_script__new(struct perf_evsel *evsel, | ||
220 | struct perf_data *data) | ||
221 | { | ||
222 | struct perf_evsel_script *es = malloc(sizeof(*es)); | ||
223 | |||
224 | if (es != NULL) { | ||
225 | if (asprintf(&es->filename, "%s.%s.dump", data->file.path, perf_evsel__name(evsel)) < 0) | ||
226 | goto out_free; | ||
227 | es->fp = fopen(es->filename, "w"); | ||
228 | if (es->fp == NULL) | ||
229 | goto out_free_filename; | ||
230 | es->samples = 0; | ||
231 | } | ||
232 | |||
233 | return es; | ||
234 | out_free_filename: | ||
235 | zfree(&es->filename); | ||
236 | out_free: | ||
237 | free(es); | ||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | static void perf_evsel_script__delete(struct perf_evsel_script *es) | ||
242 | { | ||
243 | zfree(&es->filename); | ||
244 | fclose(es->fp); | ||
245 | es->fp = NULL; | ||
246 | free(es); | ||
247 | } | ||
248 | |||
249 | static int perf_evsel_script__fprintf(struct perf_evsel_script *es, FILE *fp) | ||
250 | { | ||
251 | struct stat st; | ||
252 | |||
253 | fstat(fileno(es->fp), &st); | ||
254 | return fprintf(fp, "[ perf script: Wrote %.3f MB %s (%" PRIu64 " samples) ]\n", | ||
255 | st.st_size / 1024.0 / 1024.0, es->filename, es->samples); | ||
256 | } | ||
257 | |||
213 | static inline int output_type(unsigned int type) | 258 | static inline int output_type(unsigned int type) |
214 | { | 259 | { |
215 | switch (type) { | 260 | switch (type) { |
@@ -769,27 +814,26 @@ static int grab_bb(u8 *buffer, u64 start, u64 end, | |||
769 | * but the exit is not. Let the caller patch it up. | 814 | * but the exit is not. Let the caller patch it up. |
770 | */ | 815 | */ |
771 | if (kernel != machine__kernel_ip(machine, end)) { | 816 | if (kernel != machine__kernel_ip(machine, end)) { |
772 | printf("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", | 817 | pr_debug("\tblock %" PRIx64 "-%" PRIx64 " transfers between kernel and user\n", start, end); |
773 | start, end); | ||
774 | return -ENXIO; | 818 | return -ENXIO; |
775 | } | 819 | } |
776 | 820 | ||
777 | memset(&al, 0, sizeof(al)); | 821 | memset(&al, 0, sizeof(al)); |
778 | if (end - start > MAXBB - MAXINSN) { | 822 | if (end - start > MAXBB - MAXINSN) { |
779 | if (last) | 823 | if (last) |
780 | printf("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end); | 824 | pr_debug("\tbrstack does not reach to final jump (%" PRIx64 "-%" PRIx64 ")\n", start, end); |
781 | else | 825 | else |
782 | printf("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start); | 826 | pr_debug("\tblock %" PRIx64 "-%" PRIx64 " (%" PRIu64 ") too long to dump\n", start, end, end - start); |
783 | return 0; | 827 | return 0; |
784 | } | 828 | } |
785 | 829 | ||
786 | thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al); | 830 | thread__find_addr_map(thread, *cpumode, MAP__FUNCTION, start, &al); |
787 | if (!al.map || !al.map->dso) { | 831 | if (!al.map || !al.map->dso) { |
788 | printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); | 832 | pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); |
789 | return 0; | 833 | return 0; |
790 | } | 834 | } |
791 | if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) { | 835 | if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR) { |
792 | printf("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); | 836 | pr_debug("\tcannot resolve %" PRIx64 "-%" PRIx64 "\n", start, end); |
793 | return 0; | 837 | return 0; |
794 | } | 838 | } |
795 | 839 | ||
@@ -802,7 +846,7 @@ static int grab_bb(u8 *buffer, u64 start, u64 end, | |||
802 | 846 | ||
803 | *is64bit = al.map->dso->is_64_bit; | 847 | *is64bit = al.map->dso->is_64_bit; |
804 | if (len <= 0) | 848 | if (len <= 0) |
805 | printf("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n", | 849 | pr_debug("\tcannot fetch code for block at %" PRIx64 "-%" PRIx64 "\n", |
806 | start, end); | 850 | start, end); |
807 | return len; | 851 | return len; |
808 | } | 852 | } |
@@ -1393,6 +1437,7 @@ struct perf_script { | |||
1393 | bool show_switch_events; | 1437 | bool show_switch_events; |
1394 | bool show_namespace_events; | 1438 | bool show_namespace_events; |
1395 | bool allocated; | 1439 | bool allocated; |
1440 | bool per_event_dump; | ||
1396 | struct cpu_map *cpus; | 1441 | struct cpu_map *cpus; |
1397 | struct thread_map *threads; | 1442 | struct thread_map *threads; |
1398 | int name_width; | 1443 | int name_width; |
@@ -1439,15 +1484,18 @@ static void process_event(struct perf_script *script, | |||
1439 | struct thread *thread = al->thread; | 1484 | struct thread *thread = al->thread; |
1440 | struct perf_event_attr *attr = &evsel->attr; | 1485 | struct perf_event_attr *attr = &evsel->attr; |
1441 | unsigned int type = output_type(attr->type); | 1486 | unsigned int type = output_type(attr->type); |
1442 | FILE *fp = stdout; | 1487 | struct perf_evsel_script *es = evsel->priv; |
1488 | FILE *fp = es->fp; | ||
1443 | 1489 | ||
1444 | if (output[type].fields == 0) | 1490 | if (output[type].fields == 0) |
1445 | return; | 1491 | return; |
1446 | 1492 | ||
1493 | ++es->samples; | ||
1494 | |||
1447 | perf_sample__fprintf_start(sample, thread, evsel, fp); | 1495 | perf_sample__fprintf_start(sample, thread, evsel, fp); |
1448 | 1496 | ||
1449 | if (PRINT_FIELD(PERIOD)) | 1497 | if (PRINT_FIELD(PERIOD)) |
1450 | printf("%10" PRIu64 " ", sample->period); | 1498 | fprintf(fp, "%10" PRIu64 " ", sample->period); |
1451 | 1499 | ||
1452 | if (PRINT_FIELD(EVNAME)) { | 1500 | if (PRINT_FIELD(EVNAME)) { |
1453 | const char *evname = perf_evsel__name(evsel); | 1501 | const char *evname = perf_evsel__name(evsel); |
@@ -1455,8 +1503,7 @@ static void process_event(struct perf_script *script, | |||
1455 | if (!script->name_width) | 1503 | if (!script->name_width) |
1456 | script->name_width = perf_evlist__max_name_len(script->session->evlist); | 1504 | script->name_width = perf_evlist__max_name_len(script->session->evlist); |
1457 | 1505 | ||
1458 | printf("%*s: ", script->name_width, | 1506 | fprintf(fp, "%*s: ", script->name_width, evname ?: "[unknown]"); |
1459 | evname ? evname : "[unknown]"); | ||
1460 | } | 1507 | } |
1461 | 1508 | ||
1462 | if (print_flags) | 1509 | if (print_flags) |
@@ -1467,9 +1514,10 @@ static void process_event(struct perf_script *script, | |||
1467 | return; | 1514 | return; |
1468 | } | 1515 | } |
1469 | 1516 | ||
1470 | if (PRINT_FIELD(TRACE)) | 1517 | if (PRINT_FIELD(TRACE)) { |
1471 | event_format__print(evsel->tp_format, sample->cpu, | 1518 | event_format__fprintf(evsel->tp_format, sample->cpu, |
1472 | sample->raw_data, sample->raw_size); | 1519 | sample->raw_data, sample->raw_size, fp); |
1520 | } | ||
1473 | 1521 | ||
1474 | if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH)) | 1522 | if (attr->type == PERF_TYPE_SYNTH && PRINT_FIELD(SYNTH)) |
1475 | perf_sample__fprintf_synth(sample, evsel, fp); | 1523 | perf_sample__fprintf_synth(sample, evsel, fp); |
@@ -1513,8 +1561,8 @@ static void process_event(struct perf_script *script, | |||
1513 | perf_sample__fprintf_insn(sample, attr, thread, machine, fp); | 1561 | perf_sample__fprintf_insn(sample, attr, thread, machine, fp); |
1514 | 1562 | ||
1515 | if (PRINT_FIELD(PHYS_ADDR)) | 1563 | if (PRINT_FIELD(PHYS_ADDR)) |
1516 | printf("%16" PRIx64, sample->phys_addr); | 1564 | fprintf(fp, "%16" PRIx64, sample->phys_addr); |
1517 | printf("\n"); | 1565 | fprintf(fp, "\n"); |
1518 | } | 1566 | } |
1519 | 1567 | ||
1520 | static struct scripting_ops *scripting_ops; | 1568 | static struct scripting_ops *scripting_ops; |
@@ -1888,6 +1936,65 @@ static void sig_handler(int sig __maybe_unused) | |||
1888 | session_done = 1; | 1936 | session_done = 1; |
1889 | } | 1937 | } |
1890 | 1938 | ||
1939 | static void perf_script__fclose_per_event_dump(struct perf_script *script) | ||
1940 | { | ||
1941 | struct perf_evlist *evlist = script->session->evlist; | ||
1942 | struct perf_evsel *evsel; | ||
1943 | |||
1944 | evlist__for_each_entry(evlist, evsel) { | ||
1945 | if (!evsel->priv) | ||
1946 | break; | ||
1947 | perf_evsel_script__delete(evsel->priv); | ||
1948 | evsel->priv = NULL; | ||
1949 | } | ||
1950 | } | ||
1951 | |||
1952 | static int perf_script__fopen_per_event_dump(struct perf_script *script) | ||
1953 | { | ||
1954 | struct perf_evsel *evsel; | ||
1955 | |||
1956 | evlist__for_each_entry(script->session->evlist, evsel) { | ||
1957 | evsel->priv = perf_evsel_script__new(evsel, script->session->data); | ||
1958 | if (evsel->priv == NULL) | ||
1959 | goto out_err_fclose; | ||
1960 | } | ||
1961 | |||
1962 | return 0; | ||
1963 | |||
1964 | out_err_fclose: | ||
1965 | perf_script__fclose_per_event_dump(script); | ||
1966 | return -1; | ||
1967 | } | ||
1968 | |||
1969 | static int perf_script__setup_per_event_dump(struct perf_script *script) | ||
1970 | { | ||
1971 | struct perf_evsel *evsel; | ||
1972 | static struct perf_evsel_script es_stdout; | ||
1973 | |||
1974 | if (script->per_event_dump) | ||
1975 | return perf_script__fopen_per_event_dump(script); | ||
1976 | |||
1977 | es_stdout.fp = stdout; | ||
1978 | |||
1979 | evlist__for_each_entry(script->session->evlist, evsel) | ||
1980 | evsel->priv = &es_stdout; | ||
1981 | |||
1982 | return 0; | ||
1983 | } | ||
1984 | |||
1985 | static void perf_script__exit_per_event_dump_stats(struct perf_script *script) | ||
1986 | { | ||
1987 | struct perf_evsel *evsel; | ||
1988 | |||
1989 | evlist__for_each_entry(script->session->evlist, evsel) { | ||
1990 | struct perf_evsel_script *es = evsel->priv; | ||
1991 | |||
1992 | perf_evsel_script__fprintf(es, stdout); | ||
1993 | perf_evsel_script__delete(es); | ||
1994 | evsel->priv = NULL; | ||
1995 | } | ||
1996 | } | ||
1997 | |||
1891 | static int __cmd_script(struct perf_script *script) | 1998 | static int __cmd_script(struct perf_script *script) |
1892 | { | 1999 | { |
1893 | int ret; | 2000 | int ret; |
@@ -1909,8 +2016,16 @@ static int __cmd_script(struct perf_script *script) | |||
1909 | if (script->show_namespace_events) | 2016 | if (script->show_namespace_events) |
1910 | script->tool.namespaces = process_namespaces_event; | 2017 | script->tool.namespaces = process_namespaces_event; |
1911 | 2018 | ||
2019 | if (perf_script__setup_per_event_dump(script)) { | ||
2020 | pr_err("Couldn't create the per event dump files\n"); | ||
2021 | return -1; | ||
2022 | } | ||
2023 | |||
1912 | ret = perf_session__process_events(script->session); | 2024 | ret = perf_session__process_events(script->session); |
1913 | 2025 | ||
2026 | if (script->per_event_dump) | ||
2027 | perf_script__exit_per_event_dump_stats(script); | ||
2028 | |||
1914 | if (debug_mode) | 2029 | if (debug_mode) |
1915 | pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); | 2030 | pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered); |
1916 | 2031 | ||
@@ -2475,14 +2590,16 @@ int find_scripts(char **scripts_array, char **scripts_path_array) | |||
2475 | char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; | 2590 | char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN]; |
2476 | DIR *scripts_dir, *lang_dir; | 2591 | DIR *scripts_dir, *lang_dir; |
2477 | struct perf_session *session; | 2592 | struct perf_session *session; |
2478 | struct perf_data_file file = { | 2593 | struct perf_data data = { |
2479 | .path = input_name, | 2594 | .file = { |
2480 | .mode = PERF_DATA_MODE_READ, | 2595 | .path = input_name, |
2596 | }, | ||
2597 | .mode = PERF_DATA_MODE_READ, | ||
2481 | }; | 2598 | }; |
2482 | char *temp; | 2599 | char *temp; |
2483 | int i = 0; | 2600 | int i = 0; |
2484 | 2601 | ||
2485 | session = perf_session__new(&file, false, NULL); | 2602 | session = perf_session__new(&data, false, NULL); |
2486 | if (!session) | 2603 | if (!session) |
2487 | return -1; | 2604 | return -1; |
2488 | 2605 | ||
@@ -2760,7 +2877,7 @@ int cmd_script(int argc, const char **argv) | |||
2760 | .ordering_requires_timestamps = true, | 2877 | .ordering_requires_timestamps = true, |
2761 | }, | 2878 | }, |
2762 | }; | 2879 | }; |
2763 | struct perf_data_file file = { | 2880 | struct perf_data data = { |
2764 | .mode = PERF_DATA_MODE_READ, | 2881 | .mode = PERF_DATA_MODE_READ, |
2765 | }; | 2882 | }; |
2766 | const struct option options[] = { | 2883 | const struct option options[] = { |
@@ -2828,6 +2945,8 @@ int cmd_script(int argc, const char **argv) | |||
2828 | "Show context switch events (if recorded)"), | 2945 | "Show context switch events (if recorded)"), |
2829 | OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events, | 2946 | OPT_BOOLEAN('\0', "show-namespace-events", &script.show_namespace_events, |
2830 | "Show namespace events (if recorded)"), | 2947 | "Show namespace events (if recorded)"), |
2948 | OPT_BOOLEAN('\0', "per-event-dump", &script.per_event_dump, | ||
2949 | "Dump trace output to files named by the monitored events"), | ||
2831 | OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), | 2950 | OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), |
2832 | OPT_INTEGER(0, "max-blocks", &max_blocks, | 2951 | OPT_INTEGER(0, "max-blocks", &max_blocks, |
2833 | "Maximum number of code blocks to dump with brstackinsn"), | 2952 | "Maximum number of code blocks to dump with brstackinsn"), |
@@ -2865,8 +2984,8 @@ int cmd_script(int argc, const char **argv) | |||
2865 | argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, | 2984 | argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, |
2866 | PARSE_OPT_STOP_AT_NON_OPTION); | 2985 | PARSE_OPT_STOP_AT_NON_OPTION); |
2867 | 2986 | ||
2868 | file.path = input_name; | 2987 | data.file.path = input_name; |
2869 | file.force = symbol_conf.force; | 2988 | data.force = symbol_conf.force; |
2870 | 2989 | ||
2871 | if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { | 2990 | if (argc > 1 && !strncmp(argv[0], "rec", strlen("rec"))) { |
2872 | rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); | 2991 | rec_script_path = get_script_path(argv[1], RECORD_SUFFIX); |
@@ -3033,7 +3152,7 @@ int cmd_script(int argc, const char **argv) | |||
3033 | if (!script_name) | 3152 | if (!script_name) |
3034 | setup_pager(); | 3153 | setup_pager(); |
3035 | 3154 | ||
3036 | session = perf_session__new(&file, false, &script.tool); | 3155 | session = perf_session__new(&data, false, &script.tool); |
3037 | if (session == NULL) | 3156 | if (session == NULL) |
3038 | return -1; | 3157 | return -1; |
3039 | 3158 | ||
@@ -3089,7 +3208,7 @@ int cmd_script(int argc, const char **argv) | |||
3089 | goto out_delete; | 3208 | goto out_delete; |
3090 | } | 3209 | } |
3091 | 3210 | ||
3092 | input = open(file.path, O_RDONLY); /* input_name */ | 3211 | input = open(data.file.path, O_RDONLY); /* input_name */ |
3093 | if (input < 0) { | 3212 | if (input < 0) { |
3094 | err = -errno; | 3213 | err = -errno; |
3095 | perror("failed to open file"); | 3214 | perror("failed to open file"); |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index dd525417880a..59af5a8419e2 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -175,7 +175,7 @@ static int print_free_counters_hint; | |||
175 | 175 | ||
176 | struct perf_stat { | 176 | struct perf_stat { |
177 | bool record; | 177 | bool record; |
178 | struct perf_data_file file; | 178 | struct perf_data data; |
179 | struct perf_session *session; | 179 | struct perf_session *session; |
180 | u64 bytes_written; | 180 | u64 bytes_written; |
181 | struct perf_tool tool; | 181 | struct perf_tool tool; |
@@ -253,7 +253,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) | |||
253 | * by attr->sample_type != 0, and we can't run it on | 253 | * by attr->sample_type != 0, and we can't run it on |
254 | * stat sessions. | 254 | * stat sessions. |
255 | */ | 255 | */ |
256 | if (!(STAT_RECORD && perf_stat.file.is_pipe)) | 256 | if (!(STAT_RECORD && perf_stat.data.is_pipe)) |
257 | attr->sample_type = PERF_SAMPLE_IDENTIFIER; | 257 | attr->sample_type = PERF_SAMPLE_IDENTIFIER; |
258 | 258 | ||
259 | /* | 259 | /* |
@@ -295,7 +295,7 @@ static int process_synthesized_event(struct perf_tool *tool __maybe_unused, | |||
295 | struct perf_sample *sample __maybe_unused, | 295 | struct perf_sample *sample __maybe_unused, |
296 | struct machine *machine __maybe_unused) | 296 | struct machine *machine __maybe_unused) |
297 | { | 297 | { |
298 | if (perf_data_file__write(&perf_stat.file, event, event->header.size) < 0) { | 298 | if (perf_data__write(&perf_stat.data, event, event->header.size) < 0) { |
299 | pr_err("failed to write perf data, error: %m\n"); | 299 | pr_err("failed to write perf data, error: %m\n"); |
300 | return -1; | 300 | return -1; |
301 | } | 301 | } |
@@ -628,7 +628,7 @@ static int __run_perf_stat(int argc, const char **argv) | |||
628 | size_t l; | 628 | size_t l; |
629 | int status = 0; | 629 | int status = 0; |
630 | const bool forks = (argc > 0); | 630 | const bool forks = (argc > 0); |
631 | bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false; | 631 | bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false; |
632 | struct perf_evsel_config_term *err_term; | 632 | struct perf_evsel_config_term *err_term; |
633 | 633 | ||
634 | if (interval) { | 634 | if (interval) { |
@@ -719,10 +719,10 @@ try_again: | |||
719 | } | 719 | } |
720 | 720 | ||
721 | if (STAT_RECORD) { | 721 | if (STAT_RECORD) { |
722 | int err, fd = perf_data_file__fd(&perf_stat.file); | 722 | int err, fd = perf_data__fd(&perf_stat.data); |
723 | 723 | ||
724 | if (is_pipe) { | 724 | if (is_pipe) { |
725 | err = perf_header__write_pipe(perf_data_file__fd(&perf_stat.file)); | 725 | err = perf_header__write_pipe(perf_data__fd(&perf_stat.data)); |
726 | } else { | 726 | } else { |
727 | err = perf_session__write_header(perf_stat.session, evsel_list, | 727 | err = perf_session__write_header(perf_stat.session, evsel_list, |
728 | fd, false); | 728 | fd, false); |
@@ -845,7 +845,7 @@ static void print_noise(struct perf_evsel *evsel, double avg) | |||
845 | if (run_count == 1) | 845 | if (run_count == 1) |
846 | return; | 846 | return; |
847 | 847 | ||
848 | ps = evsel->priv; | 848 | ps = evsel->stats; |
849 | print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); | 849 | print_noise_pct(stddev_stats(&ps->res_stats[0]), avg); |
850 | } | 850 | } |
851 | 851 | ||
@@ -1267,8 +1267,7 @@ static void aggr_update_shadow(void) | |||
1267 | continue; | 1267 | continue; |
1268 | val += perf_counts(counter->counts, cpu, 0)->val; | 1268 | val += perf_counts(counter->counts, cpu, 0)->val; |
1269 | } | 1269 | } |
1270 | val = val * counter->scale; | 1270 | perf_stat__update_shadow_stats(counter, val, |
1271 | perf_stat__update_shadow_stats(counter, &val, | ||
1272 | first_shadow_cpu(counter, id)); | 1271 | first_shadow_cpu(counter, id)); |
1273 | } | 1272 | } |
1274 | } | 1273 | } |
@@ -1432,7 +1431,7 @@ static void counter_aggr_cb(struct perf_evsel *counter, void *data, | |||
1432 | bool first __maybe_unused) | 1431 | bool first __maybe_unused) |
1433 | { | 1432 | { |
1434 | struct caggr_data *cd = data; | 1433 | struct caggr_data *cd = data; |
1435 | struct perf_stat_evsel *ps = counter->priv; | 1434 | struct perf_stat_evsel *ps = counter->stats; |
1436 | 1435 | ||
1437 | cd->avg += avg_stats(&ps->res_stats[0]); | 1436 | cd->avg += avg_stats(&ps->res_stats[0]); |
1438 | cd->avg_enabled += avg_stats(&ps->res_stats[1]); | 1437 | cd->avg_enabled += avg_stats(&ps->res_stats[1]); |
@@ -1696,7 +1695,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv) | |||
1696 | char buf[64], *prefix = NULL; | 1695 | char buf[64], *prefix = NULL; |
1697 | 1696 | ||
1698 | /* Do not print anything if we record to the pipe. */ | 1697 | /* Do not print anything if we record to the pipe. */ |
1699 | if (STAT_RECORD && perf_stat.file.is_pipe) | 1698 | if (STAT_RECORD && perf_stat.data.is_pipe) |
1700 | return; | 1699 | return; |
1701 | 1700 | ||
1702 | if (interval) | 1701 | if (interval) |
@@ -2406,20 +2405,20 @@ static void init_features(struct perf_session *session) | |||
2406 | static int __cmd_record(int argc, const char **argv) | 2405 | static int __cmd_record(int argc, const char **argv) |
2407 | { | 2406 | { |
2408 | struct perf_session *session; | 2407 | struct perf_session *session; |
2409 | struct perf_data_file *file = &perf_stat.file; | 2408 | struct perf_data *data = &perf_stat.data; |
2410 | 2409 | ||
2411 | argc = parse_options(argc, argv, stat_options, stat_record_usage, | 2410 | argc = parse_options(argc, argv, stat_options, stat_record_usage, |
2412 | PARSE_OPT_STOP_AT_NON_OPTION); | 2411 | PARSE_OPT_STOP_AT_NON_OPTION); |
2413 | 2412 | ||
2414 | if (output_name) | 2413 | if (output_name) |
2415 | file->path = output_name; | 2414 | data->file.path = output_name; |
2416 | 2415 | ||
2417 | if (run_count != 1 || forever) { | 2416 | if (run_count != 1 || forever) { |
2418 | pr_err("Cannot use -r option with perf stat record.\n"); | 2417 | pr_err("Cannot use -r option with perf stat record.\n"); |
2419 | return -1; | 2418 | return -1; |
2420 | } | 2419 | } |
2421 | 2420 | ||
2422 | session = perf_session__new(file, false, NULL); | 2421 | session = perf_session__new(data, false, NULL); |
2423 | if (session == NULL) { | 2422 | if (session == NULL) { |
2424 | pr_err("Perf session creation failed.\n"); | 2423 | pr_err("Perf session creation failed.\n"); |
2425 | return -1; | 2424 | return -1; |
@@ -2477,7 +2476,7 @@ int process_stat_config_event(struct perf_tool *tool, | |||
2477 | if (st->aggr_mode != AGGR_UNSET) | 2476 | if (st->aggr_mode != AGGR_UNSET) |
2478 | stat_config.aggr_mode = st->aggr_mode; | 2477 | stat_config.aggr_mode = st->aggr_mode; |
2479 | 2478 | ||
2480 | if (perf_stat.file.is_pipe) | 2479 | if (perf_stat.data.is_pipe) |
2481 | perf_stat_init_aggr_mode(); | 2480 | perf_stat_init_aggr_mode(); |
2482 | else | 2481 | else |
2483 | perf_stat_init_aggr_mode_file(st); | 2482 | perf_stat_init_aggr_mode_file(st); |
@@ -2585,10 +2584,10 @@ static int __cmd_report(int argc, const char **argv) | |||
2585 | input_name = "perf.data"; | 2584 | input_name = "perf.data"; |
2586 | } | 2585 | } |
2587 | 2586 | ||
2588 | perf_stat.file.path = input_name; | 2587 | perf_stat.data.file.path = input_name; |
2589 | perf_stat.file.mode = PERF_DATA_MODE_READ; | 2588 | perf_stat.data.mode = PERF_DATA_MODE_READ; |
2590 | 2589 | ||
2591 | session = perf_session__new(&perf_stat.file, false, &perf_stat.tool); | 2590 | session = perf_session__new(&perf_stat.data, false, &perf_stat.tool); |
2592 | if (session == NULL) | 2591 | if (session == NULL) |
2593 | return -1; | 2592 | return -1; |
2594 | 2593 | ||
@@ -2859,7 +2858,7 @@ int cmd_stat(int argc, const char **argv) | |||
2859 | * records, but the need to suppress the kptr_restrict messages in older | 2858 | * records, but the need to suppress the kptr_restrict messages in older |
2860 | * tools remain -acme | 2859 | * tools remain -acme |
2861 | */ | 2860 | */ |
2862 | int fd = perf_data_file__fd(&perf_stat.file); | 2861 | int fd = perf_data__fd(&perf_stat.data); |
2863 | int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat, | 2862 | int err = perf_event__synthesize_kernel_mmap((void *)&perf_stat, |
2864 | process_synthesized_event, | 2863 | process_synthesized_event, |
2865 | &perf_stat.session->machines.host); | 2864 | &perf_stat.session->machines.host); |
@@ -2873,7 +2872,7 @@ int cmd_stat(int argc, const char **argv) | |||
2873 | pr_err("failed to write stat round event\n"); | 2872 | pr_err("failed to write stat round event\n"); |
2874 | } | 2873 | } |
2875 | 2874 | ||
2876 | if (!perf_stat.file.is_pipe) { | 2875 | if (!perf_stat.data.is_pipe) { |
2877 | perf_stat.session->header.data_size += perf_stat.bytes_written; | 2876 | perf_stat.session->header.data_size += perf_stat.bytes_written; |
2878 | perf_session__write_header(perf_stat.session, evsel_list, fd, true); | 2877 | perf_session__write_header(perf_stat.session, evsel_list, fd, true); |
2879 | } | 2878 | } |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 01de01ca14f2..813698a9b8c7 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -1601,13 +1601,15 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) | |||
1601 | { "syscalls:sys_exit_pselect6", process_exit_poll }, | 1601 | { "syscalls:sys_exit_pselect6", process_exit_poll }, |
1602 | { "syscalls:sys_exit_select", process_exit_poll }, | 1602 | { "syscalls:sys_exit_select", process_exit_poll }, |
1603 | }; | 1603 | }; |
1604 | struct perf_data_file file = { | 1604 | struct perf_data data = { |
1605 | .path = input_name, | 1605 | .file = { |
1606 | .mode = PERF_DATA_MODE_READ, | 1606 | .path = input_name, |
1607 | .force = tchart->force, | 1607 | }, |
1608 | .mode = PERF_DATA_MODE_READ, | ||
1609 | .force = tchart->force, | ||
1608 | }; | 1610 | }; |
1609 | 1611 | ||
1610 | struct perf_session *session = perf_session__new(&file, false, | 1612 | struct perf_session *session = perf_session__new(&data, false, |
1611 | &tchart->tool); | 1613 | &tchart->tool); |
1612 | int ret = -EINVAL; | 1614 | int ret = -EINVAL; |
1613 | 1615 | ||
@@ -1617,7 +1619,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) | |||
1617 | symbol__init(&session->header.env); | 1619 | symbol__init(&session->header.env); |
1618 | 1620 | ||
1619 | (void)perf_header__process_sections(&session->header, | 1621 | (void)perf_header__process_sections(&session->header, |
1620 | perf_data_file__fd(session->file), | 1622 | perf_data__fd(session->data), |
1621 | tchart, | 1623 | tchart, |
1622 | process_header); | 1624 | process_header); |
1623 | 1625 | ||
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8b23982dd9f2..505b871fdc82 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -578,7 +578,6 @@ static struct syscall_fmt { | |||
578 | } syscall_fmts[] = { | 578 | } syscall_fmts[] = { |
579 | { .name = "access", | 579 | { .name = "access", |
580 | .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, | 580 | .arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, }, |
581 | { .name = "arch_prctl", .alias = "prctl", }, | ||
582 | { .name = "bpf", | 581 | { .name = "bpf", |
583 | .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, | 582 | .arg = { [0] = STRARRAY(cmd, bpf_cmd), }, }, |
584 | { .name = "brk", .hexret = true, | 583 | { .name = "brk", .hexret = true, |
@@ -634,6 +633,12 @@ static struct syscall_fmt { | |||
634 | #else | 633 | #else |
635 | [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, }, | 634 | [2] = { .scnprintf = SCA_HEX, /* arg */ }, }, }, |
636 | #endif | 635 | #endif |
636 | { .name = "kcmp", .nr_args = 5, | ||
637 | .arg = { [0] = { .name = "pid1", .scnprintf = SCA_PID, }, | ||
638 | [1] = { .name = "pid2", .scnprintf = SCA_PID, }, | ||
639 | [2] = { .name = "type", .scnprintf = SCA_KCMP_TYPE, }, | ||
640 | [3] = { .name = "idx1", .scnprintf = SCA_KCMP_IDX, }, | ||
641 | [4] = { .name = "idx2", .scnprintf = SCA_KCMP_IDX, }, }, }, | ||
637 | { .name = "keyctl", | 642 | { .name = "keyctl", |
638 | .arg = { [0] = STRARRAY(option, keyctl_options), }, }, | 643 | .arg = { [0] = STRARRAY(option, keyctl_options), }, }, |
639 | { .name = "kill", | 644 | { .name = "kill", |
@@ -703,6 +708,10 @@ static struct syscall_fmt { | |||
703 | [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, }, | 708 | [3] = { .scnprintf = SCA_INT, /* pkey */ }, }, }, |
704 | { .name = "poll", .timeout = true, }, | 709 | { .name = "poll", .timeout = true, }, |
705 | { .name = "ppoll", .timeout = true, }, | 710 | { .name = "ppoll", .timeout = true, }, |
711 | { .name = "prctl", .alias = "arch_prctl", | ||
712 | .arg = { [0] = { .scnprintf = SCA_PRCTL_OPTION, /* option */ }, | ||
713 | [1] = { .scnprintf = SCA_PRCTL_ARG2, /* arg2 */ }, | ||
714 | [2] = { .scnprintf = SCA_PRCTL_ARG3, /* arg3 */ }, }, }, | ||
706 | { .name = "pread", .alias = "pread64", }, | 715 | { .name = "pread", .alias = "pread64", }, |
707 | { .name = "preadv", .alias = "pread", }, | 716 | { .name = "preadv", .alias = "pread", }, |
708 | { .name = "prlimit64", | 717 | { .name = "prlimit64", |
@@ -985,6 +994,23 @@ size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg) | |||
985 | return printed; | 994 | return printed; |
986 | } | 995 | } |
987 | 996 | ||
997 | size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size) | ||
998 | { | ||
999 | size_t printed = scnprintf(bf, size, "%d", fd); | ||
1000 | struct thread *thread = machine__find_thread(trace->host, pid, pid); | ||
1001 | |||
1002 | if (thread) { | ||
1003 | const char *path = thread__fd_path(thread, fd, trace); | ||
1004 | |||
1005 | if (path) | ||
1006 | printed += scnprintf(bf + printed, size - printed, "<%s>", path); | ||
1007 | |||
1008 | thread__put(thread); | ||
1009 | } | ||
1010 | |||
1011 | return printed; | ||
1012 | } | ||
1013 | |||
988 | static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, | 1014 | static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size, |
989 | struct syscall_arg *arg) | 1015 | struct syscall_arg *arg) |
990 | { | 1016 | { |
@@ -2529,10 +2555,12 @@ static int trace__replay(struct trace *trace) | |||
2529 | const struct perf_evsel_str_handler handlers[] = { | 2555 | const struct perf_evsel_str_handler handlers[] = { |
2530 | { "probe:vfs_getname", trace__vfs_getname, }, | 2556 | { "probe:vfs_getname", trace__vfs_getname, }, |
2531 | }; | 2557 | }; |
2532 | struct perf_data_file file = { | 2558 | struct perf_data data = { |
2533 | .path = input_name, | 2559 | .file = { |
2534 | .mode = PERF_DATA_MODE_READ, | 2560 | .path = input_name, |
2535 | .force = trace->force, | 2561 | }, |
2562 | .mode = PERF_DATA_MODE_READ, | ||
2563 | .force = trace->force, | ||
2536 | }; | 2564 | }; |
2537 | struct perf_session *session; | 2565 | struct perf_session *session; |
2538 | struct perf_evsel *evsel; | 2566 | struct perf_evsel *evsel; |
@@ -2555,7 +2583,7 @@ static int trace__replay(struct trace *trace) | |||
2555 | /* add tid to output */ | 2583 | /* add tid to output */ |
2556 | trace->multiple_threads = true; | 2584 | trace->multiple_threads = true; |
2557 | 2585 | ||
2558 | session = perf_session__new(&file, false, &trace->tool); | 2586 | session = perf_session__new(&data, false, &trace->tool); |
2559 | if (session == NULL) | 2587 | if (session == NULL) |
2560 | return -1; | 2588 | return -1; |
2561 | 2589 | ||
diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index 322629423b49..a3a041b0d35e 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh | |||
@@ -4,8 +4,10 @@ HEADERS=' | |||
4 | include/uapi/drm/drm.h | 4 | include/uapi/drm/drm.h |
5 | include/uapi/drm/i915_drm.h | 5 | include/uapi/drm/i915_drm.h |
6 | include/uapi/linux/fcntl.h | 6 | include/uapi/linux/fcntl.h |
7 | include/uapi/linux/kcmp.h | ||
7 | include/uapi/linux/kvm.h | 8 | include/uapi/linux/kvm.h |
8 | include/uapi/linux/perf_event.h | 9 | include/uapi/linux/perf_event.h |
10 | include/uapi/linux/prctl.h | ||
9 | include/uapi/linux/sched.h | 11 | include/uapi/linux/sched.h |
10 | include/uapi/linux/stat.h | 12 | include/uapi/linux/stat.h |
11 | include/uapi/linux/vhost.h | 13 | include/uapi/linux/vhost.h |
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 19b0561fd6f6..9bbfed51f1d6 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c | |||
@@ -29,12 +29,14 @@ static int get_temp(char *path) | |||
29 | static int session_write_header(char *path) | 29 | static int session_write_header(char *path) |
30 | { | 30 | { |
31 | struct perf_session *session; | 31 | struct perf_session *session; |
32 | struct perf_data_file file = { | 32 | struct perf_data data = { |
33 | .path = path, | 33 | .file = { |
34 | .mode = PERF_DATA_MODE_WRITE, | 34 | .path = path, |
35 | }, | ||
36 | .mode = PERF_DATA_MODE_WRITE, | ||
35 | }; | 37 | }; |
36 | 38 | ||
37 | session = perf_session__new(&file, false, NULL); | 39 | session = perf_session__new(&data, false, NULL); |
38 | TEST_ASSERT_VAL("can't get session", session); | 40 | TEST_ASSERT_VAL("can't get session", session); |
39 | 41 | ||
40 | session->evlist = perf_evlist__new_default(); | 42 | session->evlist = perf_evlist__new_default(); |
@@ -46,7 +48,7 @@ static int session_write_header(char *path) | |||
46 | session->header.data_size += DATA_SIZE; | 48 | session->header.data_size += DATA_SIZE; |
47 | 49 | ||
48 | TEST_ASSERT_VAL("failed to write header", | 50 | TEST_ASSERT_VAL("failed to write header", |
49 | !perf_session__write_header(session, session->evlist, file.fd, true)); | 51 | !perf_session__write_header(session, session->evlist, data.file.fd, true)); |
50 | 52 | ||
51 | perf_session__delete(session); | 53 | perf_session__delete(session); |
52 | 54 | ||
@@ -56,13 +58,15 @@ static int session_write_header(char *path) | |||
56 | static int check_cpu_topology(char *path, struct cpu_map *map) | 58 | static int check_cpu_topology(char *path, struct cpu_map *map) |
57 | { | 59 | { |
58 | struct perf_session *session; | 60 | struct perf_session *session; |
59 | struct perf_data_file file = { | 61 | struct perf_data data = { |
60 | .path = path, | 62 | .file = { |
61 | .mode = PERF_DATA_MODE_READ, | 63 | .path = path, |
64 | }, | ||
65 | .mode = PERF_DATA_MODE_READ, | ||
62 | }; | 66 | }; |
63 | int i; | 67 | int i; |
64 | 68 | ||
65 | session = perf_session__new(&file, false, NULL); | 69 | session = perf_session__new(&data, false, NULL); |
66 | TEST_ASSERT_VAL("can't get session", session); | 70 | TEST_ASSERT_VAL("can't get session", session); |
67 | 71 | ||
68 | for (i = 0; i < session->header.env.nr_cpus_avail; i++) { | 72 | for (i = 0; i < session->header.env.nr_cpus_avail; i++) { |
diff --git a/tools/perf/trace/beauty/Build b/tools/perf/trace/beauty/Build index 175d633c6b49..066bbf0f4a74 100644 --- a/tools/perf/trace/beauty/Build +++ b/tools/perf/trace/beauty/Build | |||
@@ -3,5 +3,7 @@ libperf-y += fcntl.o | |||
3 | ifeq ($(SRCARCH),$(filter $(SRCARCH),x86)) | 3 | ifeq ($(SRCARCH),$(filter $(SRCARCH),x86)) |
4 | libperf-y += ioctl.o | 4 | libperf-y += ioctl.o |
5 | endif | 5 | endif |
6 | libperf-y += kcmp.o | ||
6 | libperf-y += pkey_alloc.o | 7 | libperf-y += pkey_alloc.o |
8 | libperf-y += prctl.o | ||
7 | libperf-y += statx.o | 9 | libperf-y += statx.o |
diff --git a/tools/perf/trace/beauty/beauty.h b/tools/perf/trace/beauty/beauty.h index 4b58581a6053..3f067bdab84f 100644 --- a/tools/perf/trace/beauty/beauty.h +++ b/tools/perf/trace/beauty/beauty.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <sys/types.h> | ||
6 | 7 | ||
7 | struct strarray { | 8 | struct strarray { |
8 | int offset; | 9 | int offset; |
@@ -26,6 +27,8 @@ size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const cha | |||
26 | struct trace; | 27 | struct trace; |
27 | struct thread; | 28 | struct thread; |
28 | 29 | ||
30 | size_t pid__scnprintf_fd(struct trace *trace, pid_t pid, int fd, char *bf, size_t size); | ||
31 | |||
29 | /** | 32 | /** |
30 | * @val: value of syscall argument being formatted | 33 | * @val: value of syscall argument being formatted |
31 | * @args: All the args, use syscall_args__val(arg, nth) to access one | 34 | * @args: All the args, use syscall_args__val(arg, nth) to access one |
@@ -78,12 +81,27 @@ size_t syscall_arg__scnprintf_fcntl_arg(char *bf, size_t size, struct syscall_ar | |||
78 | size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg); | 81 | size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg); |
79 | #define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd | 82 | #define SCA_IOCTL_CMD syscall_arg__scnprintf_ioctl_cmd |
80 | 83 | ||
84 | size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg); | ||
85 | #define SCA_KCMP_TYPE syscall_arg__scnprintf_kcmp_type | ||
86 | |||
87 | size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg); | ||
88 | #define SCA_KCMP_IDX syscall_arg__scnprintf_kcmp_idx | ||
89 | |||
81 | size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg); | 90 | size_t syscall_arg__scnprintf_pkey_alloc_access_rights(char *bf, size_t size, struct syscall_arg *arg); |
82 | #define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights | 91 | #define SCA_PKEY_ALLOC_ACCESS_RIGHTS syscall_arg__scnprintf_pkey_alloc_access_rights |
83 | 92 | ||
84 | size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg); | 93 | size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, struct syscall_arg *arg); |
85 | #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags | 94 | #define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags |
86 | 95 | ||
96 | size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg); | ||
97 | #define SCA_PRCTL_OPTION syscall_arg__scnprintf_prctl_option | ||
98 | |||
99 | size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg); | ||
100 | #define SCA_PRCTL_ARG2 syscall_arg__scnprintf_prctl_arg2 | ||
101 | |||
102 | size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg); | ||
103 | #define SCA_PRCTL_ARG3 syscall_arg__scnprintf_prctl_arg3 | ||
104 | |||
87 | size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg); | 105 | size_t syscall_arg__scnprintf_statx_flags(char *bf, size_t size, struct syscall_arg *arg); |
88 | #define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags | 106 | #define SCA_STATX_FLAGS syscall_arg__scnprintf_statx_flags |
89 | 107 | ||
diff --git a/tools/perf/trace/beauty/kcmp.c b/tools/perf/trace/beauty/kcmp.c new file mode 100644 index 000000000000..f62040eb9d5c --- /dev/null +++ b/tools/perf/trace/beauty/kcmp.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * trace/beauty/kcmp.c | ||
3 | * | ||
4 | * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> | ||
5 | * | ||
6 | * Released under the GPL v2. (and only v2, not any later version) | ||
7 | */ | ||
8 | |||
9 | #include "trace/beauty/beauty.h" | ||
10 | #include <linux/kernel.h> | ||
11 | #include <sys/types.h> | ||
12 | #include <machine.h> | ||
13 | #include <uapi/linux/kcmp.h> | ||
14 | |||
15 | #include "trace/beauty/generated/kcmp_type_array.c" | ||
16 | |||
17 | size_t syscall_arg__scnprintf_kcmp_idx(char *bf, size_t size, struct syscall_arg *arg) | ||
18 | { | ||
19 | unsigned long fd = arg->val; | ||
20 | int type = syscall_arg__val(arg, 2); | ||
21 | pid_t pid; | ||
22 | |||
23 | if (type != KCMP_FILE) | ||
24 | return syscall_arg__scnprintf_long(bf, size, arg); | ||
25 | |||
26 | pid = syscall_arg__val(arg, arg->idx == 3 ? 0 : 1); /* idx1 -> pid1, idx2 -> pid2 */ | ||
27 | return pid__scnprintf_fd(arg->trace, pid, fd, bf, size); | ||
28 | } | ||
29 | |||
30 | static size_t kcmp__scnprintf_type(int type, char *bf, size_t size) | ||
31 | { | ||
32 | static DEFINE_STRARRAY(kcmp_types); | ||
33 | return strarray__scnprintf(&strarray__kcmp_types, bf, size, "%d", type); | ||
34 | } | ||
35 | |||
36 | size_t syscall_arg__scnprintf_kcmp_type(char *bf, size_t size, struct syscall_arg *arg) | ||
37 | { | ||
38 | unsigned long type = arg->val; | ||
39 | |||
40 | if (type != KCMP_FILE) | ||
41 | arg->mask |= (1 << 3) | (1 << 4); /* Ignore idx1 and idx2 */ | ||
42 | |||
43 | return kcmp__scnprintf_type(type, bf, size); | ||
44 | } | ||
diff --git a/tools/perf/trace/beauty/kcmp_type.sh b/tools/perf/trace/beauty/kcmp_type.sh new file mode 100755 index 000000000000..40d063b8c082 --- /dev/null +++ b/tools/perf/trace/beauty/kcmp_type.sh | |||
@@ -0,0 +1,10 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | header_dir=$1 | ||
4 | |||
5 | printf "static const char *kcmp_types[] = {\n" | ||
6 | regex='^[[:space:]]+(KCMP_(\w+)),' | ||
7 | egrep $regex ${header_dir}/kcmp.h | grep -v KCMP_TYPES, | \ | ||
8 | sed -r "s/$regex/\1 \2/g" | \ | ||
9 | xargs printf "\t[%s]\t= \"%s\",\n" | ||
10 | printf "};\n" | ||
diff --git a/tools/perf/trace/beauty/prctl.c b/tools/perf/trace/beauty/prctl.c new file mode 100644 index 000000000000..246130dad6c4 --- /dev/null +++ b/tools/perf/trace/beauty/prctl.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * trace/beauty/prctl.c | ||
3 | * | ||
4 | * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com> | ||
5 | * | ||
6 | * Released under the GPL v2. (and only v2, not any later version) | ||
7 | */ | ||
8 | |||
9 | #include "trace/beauty/beauty.h" | ||
10 | #include <linux/kernel.h> | ||
11 | #include <uapi/linux/prctl.h> | ||
12 | |||
13 | #include "trace/beauty/generated/prctl_option_array.c" | ||
14 | |||
15 | static size_t prctl__scnprintf_option(int option, char *bf, size_t size) | ||
16 | { | ||
17 | static DEFINE_STRARRAY(prctl_options); | ||
18 | return strarray__scnprintf(&strarray__prctl_options, bf, size, "%d", option); | ||
19 | } | ||
20 | |||
21 | static size_t prctl__scnprintf_set_mm(int option, char *bf, size_t size) | ||
22 | { | ||
23 | static DEFINE_STRARRAY(prctl_set_mm_options); | ||
24 | return strarray__scnprintf(&strarray__prctl_set_mm_options, bf, size, "%d", option); | ||
25 | } | ||
26 | |||
27 | size_t syscall_arg__scnprintf_prctl_arg2(char *bf, size_t size, struct syscall_arg *arg) | ||
28 | { | ||
29 | int option = syscall_arg__val(arg, 0); | ||
30 | |||
31 | if (option == PR_SET_MM) | ||
32 | return prctl__scnprintf_set_mm(arg->val, bf, size); | ||
33 | /* | ||
34 | * We still don't grab the contents of pointers on entry or exit, | ||
35 | * so just print them as hex numbers | ||
36 | */ | ||
37 | if (option == PR_SET_NAME) | ||
38 | return syscall_arg__scnprintf_hex(bf, size, arg); | ||
39 | |||
40 | return syscall_arg__scnprintf_long(bf, size, arg); | ||
41 | } | ||
42 | |||
43 | size_t syscall_arg__scnprintf_prctl_arg3(char *bf, size_t size, struct syscall_arg *arg) | ||
44 | { | ||
45 | int option = syscall_arg__val(arg, 0); | ||
46 | |||
47 | if (option == PR_SET_MM) | ||
48 | return syscall_arg__scnprintf_hex(bf, size, arg); | ||
49 | |||
50 | return syscall_arg__scnprintf_long(bf, size, arg); | ||
51 | } | ||
52 | |||
53 | size_t syscall_arg__scnprintf_prctl_option(char *bf, size_t size, struct syscall_arg *arg) | ||
54 | { | ||
55 | unsigned long option = arg->val; | ||
56 | enum { | ||
57 | SPO_ARG2 = (1 << 1), | ||
58 | SPO_ARG3 = (1 << 2), | ||
59 | SPO_ARG4 = (1 << 3), | ||
60 | SPO_ARG5 = (1 << 4), | ||
61 | SPO_ARG6 = (1 << 5), | ||
62 | }; | ||
63 | const u8 all_but2 = SPO_ARG3 | SPO_ARG4 | SPO_ARG5 | SPO_ARG6; | ||
64 | const u8 all = SPO_ARG2 | all_but2; | ||
65 | const u8 masks[] = { | ||
66 | [PR_GET_DUMPABLE] = all, | ||
67 | [PR_SET_DUMPABLE] = all_but2, | ||
68 | [PR_SET_NAME] = all_but2, | ||
69 | [PR_GET_CHILD_SUBREAPER] = all_but2, | ||
70 | [PR_SET_CHILD_SUBREAPER] = all_but2, | ||
71 | [PR_GET_SECUREBITS] = all, | ||
72 | [PR_SET_SECUREBITS] = all_but2, | ||
73 | [PR_SET_MM] = SPO_ARG4 | SPO_ARG5 | SPO_ARG6, | ||
74 | [PR_GET_PDEATHSIG] = all, | ||
75 | [PR_SET_PDEATHSIG] = all_but2, | ||
76 | }; | ||
77 | |||
78 | if (option < ARRAY_SIZE(masks)) | ||
79 | arg->mask |= masks[option]; | ||
80 | |||
81 | return prctl__scnprintf_option(option, bf, size); | ||
82 | } | ||
diff --git a/tools/perf/trace/beauty/prctl_option.sh b/tools/perf/trace/beauty/prctl_option.sh new file mode 100755 index 000000000000..0be4138fbe71 --- /dev/null +++ b/tools/perf/trace/beauty/prctl_option.sh | |||
@@ -0,0 +1,17 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | header_dir=$1 | ||
4 | |||
5 | printf "static const char *prctl_options[] = {\n" | ||
6 | regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*' | ||
7 | egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \ | ||
8 | sed -r "s/$regex/\2 \1/g" | \ | ||
9 | sort -n | xargs printf "\t[%s] = \"%s\",\n" | ||
10 | printf "};\n" | ||
11 | |||
12 | printf "static const char *prctl_set_mm_options[] = {\n" | ||
13 | regex='^#[[:space:]]+define[[:space:]]+PR_SET_MM_(\w+)[[:space:]]*([[:digit:]]+).*' | ||
14 | egrep $regex ${header_dir}/prctl.h | \ | ||
15 | sed -r "s/$regex/\2 \1/g" | \ | ||
16 | sort -n | xargs printf "\t[%s] = \"%s\",\n" | ||
17 | printf "};\n" | ||
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 5547457566a7..a33491416400 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c | |||
@@ -208,7 +208,7 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues, | |||
208 | 208 | ||
209 | static void *auxtrace_copy_data(u64 size, struct perf_session *session) | 209 | static void *auxtrace_copy_data(u64 size, struct perf_session *session) |
210 | { | 210 | { |
211 | int fd = perf_data_file__fd(session->file); | 211 | int fd = perf_data__fd(session->data); |
212 | void *p; | 212 | void *p; |
213 | ssize_t ret; | 213 | ssize_t ret; |
214 | 214 | ||
@@ -305,7 +305,7 @@ static int auxtrace_queues__add_event_buffer(struct auxtrace_queues *queues, | |||
305 | if (session->one_mmap) { | 305 | if (session->one_mmap) { |
306 | buffer->data = buffer->data_offset - session->one_mmap_offset + | 306 | buffer->data = buffer->data_offset - session->one_mmap_offset + |
307 | session->one_mmap_addr; | 307 | session->one_mmap_addr; |
308 | } else if (perf_data_file__is_pipe(session->file)) { | 308 | } else if (perf_data__is_pipe(session->data)) { |
309 | buffer->data = auxtrace_copy_data(buffer->size, session); | 309 | buffer->data = auxtrace_copy_data(buffer->size, session); |
310 | if (!buffer->data) | 310 | if (!buffer->data) |
311 | return -ENOMEM; | 311 | return -ENOMEM; |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 3a3916934a92..837012147c7b 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -1091,10 +1091,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * | |||
1091 | al->map = node->map; | 1091 | al->map = node->map; |
1092 | al->sym = node->sym; | 1092 | al->sym = node->sym; |
1093 | al->srcline = node->srcline; | 1093 | al->srcline = node->srcline; |
1094 | if (node->map) | 1094 | al->addr = node->ip; |
1095 | al->addr = node->map->map_ip(node->map, node->ip); | ||
1096 | else | ||
1097 | al->addr = node->ip; | ||
1098 | 1095 | ||
1099 | if (al->sym == NULL) { | 1096 | if (al->sym == NULL) { |
1100 | if (hide_unresolved) | 1097 | if (hide_unresolved) |
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 2346cecb8ea2..5744c12641a5 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -1577,10 +1577,10 @@ int bt_convert__perf2ctf(const char *input, const char *path, | |||
1577 | struct perf_data_convert_opts *opts) | 1577 | struct perf_data_convert_opts *opts) |
1578 | { | 1578 | { |
1579 | struct perf_session *session; | 1579 | struct perf_session *session; |
1580 | struct perf_data_file file = { | 1580 | struct perf_data data = { |
1581 | .path = input, | 1581 | .file.path = input, |
1582 | .mode = PERF_DATA_MODE_READ, | 1582 | .mode = PERF_DATA_MODE_READ, |
1583 | .force = opts->force, | 1583 | .force = opts->force, |
1584 | }; | 1584 | }; |
1585 | struct convert c = { | 1585 | struct convert c = { |
1586 | .tool = { | 1586 | .tool = { |
@@ -1619,7 +1619,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, | |||
1619 | 1619 | ||
1620 | err = -1; | 1620 | err = -1; |
1621 | /* perf.data session */ | 1621 | /* perf.data session */ |
1622 | session = perf_session__new(&file, 0, &c.tool); | 1622 | session = perf_session__new(&data, 0, &c.tool); |
1623 | if (!session) | 1623 | if (!session) |
1624 | goto free_writer; | 1624 | goto free_writer; |
1625 | 1625 | ||
@@ -1650,7 +1650,7 @@ int bt_convert__perf2ctf(const char *input, const char *path, | |||
1650 | 1650 | ||
1651 | fprintf(stderr, | 1651 | fprintf(stderr, |
1652 | "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", | 1652 | "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", |
1653 | file.path, path); | 1653 | data.file.path, path); |
1654 | 1654 | ||
1655 | fprintf(stderr, | 1655 | fprintf(stderr, |
1656 | "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", | 1656 | "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", |
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c index 1123b30e3033..f80a23d031d6 100644 --- a/tools/perf/util/data.c +++ b/tools/perf/util/data.c | |||
@@ -21,56 +21,56 @@ | |||
21 | #endif | 21 | #endif |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | static bool check_pipe(struct perf_data_file *file) | 24 | static bool check_pipe(struct perf_data *data) |
25 | { | 25 | { |
26 | struct stat st; | 26 | struct stat st; |
27 | bool is_pipe = false; | 27 | bool is_pipe = false; |
28 | int fd = perf_data_file__is_read(file) ? | 28 | int fd = perf_data__is_read(data) ? |
29 | STDIN_FILENO : STDOUT_FILENO; | 29 | STDIN_FILENO : STDOUT_FILENO; |
30 | 30 | ||
31 | if (!file->path) { | 31 | if (!data->file.path) { |
32 | if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) | 32 | if (!fstat(fd, &st) && S_ISFIFO(st.st_mode)) |
33 | is_pipe = true; | 33 | is_pipe = true; |
34 | } else { | 34 | } else { |
35 | if (!strcmp(file->path, "-")) | 35 | if (!strcmp(data->file.path, "-")) |
36 | is_pipe = true; | 36 | is_pipe = true; |
37 | } | 37 | } |
38 | 38 | ||
39 | if (is_pipe) | 39 | if (is_pipe) |
40 | file->fd = fd; | 40 | data->file.fd = fd; |
41 | 41 | ||
42 | return file->is_pipe = is_pipe; | 42 | return data->is_pipe = is_pipe; |
43 | } | 43 | } |
44 | 44 | ||
45 | static int check_backup(struct perf_data_file *file) | 45 | static int check_backup(struct perf_data *data) |
46 | { | 46 | { |
47 | struct stat st; | 47 | struct stat st; |
48 | 48 | ||
49 | if (!stat(file->path, &st) && st.st_size) { | 49 | if (!stat(data->file.path, &st) && st.st_size) { |
50 | /* TODO check errors properly */ | 50 | /* TODO check errors properly */ |
51 | char oldname[PATH_MAX]; | 51 | char oldname[PATH_MAX]; |
52 | snprintf(oldname, sizeof(oldname), "%s.old", | 52 | snprintf(oldname, sizeof(oldname), "%s.old", |
53 | file->path); | 53 | data->file.path); |
54 | unlink(oldname); | 54 | unlink(oldname); |
55 | rename(file->path, oldname); | 55 | rename(data->file.path, oldname); |
56 | } | 56 | } |
57 | 57 | ||
58 | return 0; | 58 | return 0; |
59 | } | 59 | } |
60 | 60 | ||
61 | static int open_file_read(struct perf_data_file *file) | 61 | static int open_file_read(struct perf_data *data) |
62 | { | 62 | { |
63 | struct stat st; | 63 | struct stat st; |
64 | int fd; | 64 | int fd; |
65 | char sbuf[STRERR_BUFSIZE]; | 65 | char sbuf[STRERR_BUFSIZE]; |
66 | 66 | ||
67 | fd = open(file->path, O_RDONLY); | 67 | fd = open(data->file.path, O_RDONLY); |
68 | if (fd < 0) { | 68 | if (fd < 0) { |
69 | int err = errno; | 69 | int err = errno; |
70 | 70 | ||
71 | pr_err("failed to open %s: %s", file->path, | 71 | pr_err("failed to open %s: %s", data->file.path, |
72 | str_error_r(err, sbuf, sizeof(sbuf))); | 72 | str_error_r(err, sbuf, sizeof(sbuf))); |
73 | if (err == ENOENT && !strcmp(file->path, "perf.data")) | 73 | if (err == ENOENT && !strcmp(data->file.path, "perf.data")) |
74 | pr_err(" (try 'perf record' first)"); | 74 | pr_err(" (try 'perf record' first)"); |
75 | pr_err("\n"); | 75 | pr_err("\n"); |
76 | return -err; | 76 | return -err; |
@@ -79,19 +79,19 @@ static int open_file_read(struct perf_data_file *file) | |||
79 | if (fstat(fd, &st) < 0) | 79 | if (fstat(fd, &st) < 0) |
80 | goto out_close; | 80 | goto out_close; |
81 | 81 | ||
82 | if (!file->force && st.st_uid && (st.st_uid != geteuid())) { | 82 | if (!data->force && st.st_uid && (st.st_uid != geteuid())) { |
83 | pr_err("File %s not owned by current user or root (use -f to override)\n", | 83 | pr_err("File %s not owned by current user or root (use -f to override)\n", |
84 | file->path); | 84 | data->file.path); |
85 | goto out_close; | 85 | goto out_close; |
86 | } | 86 | } |
87 | 87 | ||
88 | if (!st.st_size) { | 88 | if (!st.st_size) { |
89 | pr_info("zero-sized file (%s), nothing to do!\n", | 89 | pr_info("zero-sized data (%s), nothing to do!\n", |
90 | file->path); | 90 | data->file.path); |
91 | goto out_close; | 91 | goto out_close; |
92 | } | 92 | } |
93 | 93 | ||
94 | file->size = st.st_size; | 94 | data->size = st.st_size; |
95 | return fd; | 95 | return fd; |
96 | 96 | ||
97 | out_close: | 97 | out_close: |
@@ -99,49 +99,49 @@ static int open_file_read(struct perf_data_file *file) | |||
99 | return -1; | 99 | return -1; |
100 | } | 100 | } |
101 | 101 | ||
102 | static int open_file_write(struct perf_data_file *file) | 102 | static int open_file_write(struct perf_data *data) |
103 | { | 103 | { |
104 | int fd; | 104 | int fd; |
105 | char sbuf[STRERR_BUFSIZE]; | 105 | char sbuf[STRERR_BUFSIZE]; |
106 | 106 | ||
107 | if (check_backup(file)) | 107 | if (check_backup(data)) |
108 | return -1; | 108 | return -1; |
109 | 109 | ||
110 | fd = open(file->path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, | 110 | fd = open(data->file.path, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, |
111 | S_IRUSR|S_IWUSR); | 111 | S_IRUSR|S_IWUSR); |
112 | 112 | ||
113 | if (fd < 0) | 113 | if (fd < 0) |
114 | pr_err("failed to open %s : %s\n", file->path, | 114 | pr_err("failed to open %s : %s\n", data->file.path, |
115 | str_error_r(errno, sbuf, sizeof(sbuf))); | 115 | str_error_r(errno, sbuf, sizeof(sbuf))); |
116 | 116 | ||
117 | return fd; | 117 | return fd; |
118 | } | 118 | } |
119 | 119 | ||
120 | static int open_file(struct perf_data_file *file) | 120 | static int open_file(struct perf_data *data) |
121 | { | 121 | { |
122 | int fd; | 122 | int fd; |
123 | 123 | ||
124 | fd = perf_data_file__is_read(file) ? | 124 | fd = perf_data__is_read(data) ? |
125 | open_file_read(file) : open_file_write(file); | 125 | open_file_read(data) : open_file_write(data); |
126 | 126 | ||
127 | file->fd = fd; | 127 | data->file.fd = fd; |
128 | return fd < 0 ? -1 : 0; | 128 | return fd < 0 ? -1 : 0; |
129 | } | 129 | } |
130 | 130 | ||
131 | int perf_data_file__open(struct perf_data_file *file) | 131 | int perf_data__open(struct perf_data *data) |
132 | { | 132 | { |
133 | if (check_pipe(file)) | 133 | if (check_pipe(data)) |
134 | return 0; | 134 | return 0; |
135 | 135 | ||
136 | if (!file->path) | 136 | if (!data->file.path) |
137 | file->path = "perf.data"; | 137 | data->file.path = "perf.data"; |
138 | 138 | ||
139 | return open_file(file); | 139 | return open_file(data); |
140 | } | 140 | } |
141 | 141 | ||
142 | void perf_data_file__close(struct perf_data_file *file) | 142 | void perf_data__close(struct perf_data *data) |
143 | { | 143 | { |
144 | close(file->fd); | 144 | close(data->file.fd); |
145 | } | 145 | } |
146 | 146 | ||
147 | ssize_t perf_data_file__write(struct perf_data_file *file, | 147 | ssize_t perf_data_file__write(struct perf_data_file *file, |
@@ -150,42 +150,48 @@ ssize_t perf_data_file__write(struct perf_data_file *file, | |||
150 | return writen(file->fd, buf, size); | 150 | return writen(file->fd, buf, size); |
151 | } | 151 | } |
152 | 152 | ||
153 | int perf_data_file__switch(struct perf_data_file *file, | 153 | ssize_t perf_data__write(struct perf_data *data, |
154 | void *buf, size_t size) | ||
155 | { | ||
156 | return perf_data_file__write(&data->file, buf, size); | ||
157 | } | ||
158 | |||
159 | int perf_data__switch(struct perf_data *data, | ||
154 | const char *postfix, | 160 | const char *postfix, |
155 | size_t pos, bool at_exit) | 161 | size_t pos, bool at_exit) |
156 | { | 162 | { |
157 | char *new_filepath; | 163 | char *new_filepath; |
158 | int ret; | 164 | int ret; |
159 | 165 | ||
160 | if (check_pipe(file)) | 166 | if (check_pipe(data)) |
161 | return -EINVAL; | 167 | return -EINVAL; |
162 | if (perf_data_file__is_read(file)) | 168 | if (perf_data__is_read(data)) |
163 | return -EINVAL; | 169 | return -EINVAL; |
164 | 170 | ||
165 | if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0) | 171 | if (asprintf(&new_filepath, "%s.%s", data->file.path, postfix) < 0) |
166 | return -ENOMEM; | 172 | return -ENOMEM; |
167 | 173 | ||
168 | /* | 174 | /* |
169 | * Only fire a warning, don't return error, continue fill | 175 | * Only fire a warning, don't return error, continue fill |
170 | * original file. | 176 | * original file. |
171 | */ | 177 | */ |
172 | if (rename(file->path, new_filepath)) | 178 | if (rename(data->file.path, new_filepath)) |
173 | pr_warning("Failed to rename %s to %s\n", file->path, new_filepath); | 179 | pr_warning("Failed to rename %s to %s\n", data->file.path, new_filepath); |
174 | 180 | ||
175 | if (!at_exit) { | 181 | if (!at_exit) { |
176 | close(file->fd); | 182 | close(data->file.fd); |
177 | ret = perf_data_file__open(file); | 183 | ret = perf_data__open(data); |
178 | if (ret < 0) | 184 | if (ret < 0) |
179 | goto out; | 185 | goto out; |
180 | 186 | ||
181 | if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) { | 187 | if (lseek(data->file.fd, pos, SEEK_SET) == (off_t)-1) { |
182 | ret = -errno; | 188 | ret = -errno; |
183 | pr_debug("Failed to lseek to %zu: %s", | 189 | pr_debug("Failed to lseek to %zu: %s", |
184 | pos, strerror(errno)); | 190 | pos, strerror(errno)); |
185 | goto out; | 191 | goto out; |
186 | } | 192 | } |
187 | } | 193 | } |
188 | ret = file->fd; | 194 | ret = data->file.fd; |
189 | out: | 195 | out: |
190 | free(new_filepath); | 196 | free(new_filepath); |
191 | return ret; | 197 | return ret; |
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h index ae510ce16cb1..000c43bbb7ac 100644 --- a/tools/perf/util/data.h +++ b/tools/perf/util/data.h | |||
@@ -9,51 +9,57 @@ enum perf_data_mode { | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | struct perf_data_file { | 11 | struct perf_data_file { |
12 | const char *path; | 12 | const char *path; |
13 | int fd; | 13 | int fd; |
14 | }; | ||
15 | |||
16 | struct perf_data { | ||
17 | struct perf_data_file file; | ||
14 | bool is_pipe; | 18 | bool is_pipe; |
15 | bool force; | 19 | bool force; |
16 | unsigned long size; | 20 | unsigned long size; |
17 | enum perf_data_mode mode; | 21 | enum perf_data_mode mode; |
18 | }; | 22 | }; |
19 | 23 | ||
20 | static inline bool perf_data_file__is_read(struct perf_data_file *file) | 24 | static inline bool perf_data__is_read(struct perf_data *data) |
21 | { | 25 | { |
22 | return file->mode == PERF_DATA_MODE_READ; | 26 | return data->mode == PERF_DATA_MODE_READ; |
23 | } | 27 | } |
24 | 28 | ||
25 | static inline bool perf_data_file__is_write(struct perf_data_file *file) | 29 | static inline bool perf_data__is_write(struct perf_data *data) |
26 | { | 30 | { |
27 | return file->mode == PERF_DATA_MODE_WRITE; | 31 | return data->mode == PERF_DATA_MODE_WRITE; |
28 | } | 32 | } |
29 | 33 | ||
30 | static inline int perf_data_file__is_pipe(struct perf_data_file *file) | 34 | static inline int perf_data__is_pipe(struct perf_data *data) |
31 | { | 35 | { |
32 | return file->is_pipe; | 36 | return data->is_pipe; |
33 | } | 37 | } |
34 | 38 | ||
35 | static inline int perf_data_file__fd(struct perf_data_file *file) | 39 | static inline int perf_data__fd(struct perf_data *data) |
36 | { | 40 | { |
37 | return file->fd; | 41 | return data->file.fd; |
38 | } | 42 | } |
39 | 43 | ||
40 | static inline unsigned long perf_data_file__size(struct perf_data_file *file) | 44 | static inline unsigned long perf_data__size(struct perf_data *data) |
41 | { | 45 | { |
42 | return file->size; | 46 | return data->size; |
43 | } | 47 | } |
44 | 48 | ||
45 | int perf_data_file__open(struct perf_data_file *file); | 49 | int perf_data__open(struct perf_data *data); |
46 | void perf_data_file__close(struct perf_data_file *file); | 50 | void perf_data__close(struct perf_data *data); |
51 | ssize_t perf_data__write(struct perf_data *data, | ||
52 | void *buf, size_t size); | ||
47 | ssize_t perf_data_file__write(struct perf_data_file *file, | 53 | ssize_t perf_data_file__write(struct perf_data_file *file, |
48 | void *buf, size_t size); | 54 | void *buf, size_t size); |
49 | /* | 55 | /* |
50 | * If at_exit is set, only rename current perf.data to | 56 | * If at_exit is set, only rename current perf.data to |
51 | * perf.data.<postfix>, continue write on original file. | 57 | * perf.data.<postfix>, continue write on original data. |
52 | * Set at_exit when flushing the last output. | 58 | * Set at_exit when flushing the last output. |
53 | * | 59 | * |
54 | * Return value is fd of new output. | 60 | * Return value is fd of new output. |
55 | */ | 61 | */ |
56 | int perf_data_file__switch(struct perf_data_file *file, | 62 | int perf_data__switch(struct perf_data *data, |
57 | const char *postfix, | 63 | const char *postfix, |
58 | size_t pos, bool at_exit); | 64 | size_t pos, bool at_exit); |
59 | #endif /* __PERF_DATA_H */ | 65 | #endif /* __PERF_DATA_H */ |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index db658785d828..64782b19089d 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -68,6 +68,8 @@ struct perf_evsel_config_term { | |||
68 | } val; | 68 | } val; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | struct perf_stat_evsel; | ||
72 | |||
71 | /** struct perf_evsel - event selector | 73 | /** struct perf_evsel - event selector |
72 | * | 74 | * |
73 | * @evlist - evlist this evsel is in, if it is in one. | 75 | * @evlist - evlist this evsel is in, if it is in one. |
@@ -101,6 +103,7 @@ struct perf_evsel { | |||
101 | const char *unit; | 103 | const char *unit; |
102 | struct event_format *tp_format; | 104 | struct event_format *tp_format; |
103 | off_t id_offset; | 105 | off_t id_offset; |
106 | struct perf_stat_evsel *stats; | ||
104 | void *priv; | 107 | void *priv; |
105 | u64 db_id; | 108 | u64 db_id; |
106 | struct cgroup_sel *cgrp; | 109 | struct cgroup_sel *cgrp; |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 605bbd5404fb..6e59dcca9df2 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1762,7 +1762,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused) | |||
1762 | 1762 | ||
1763 | session = container_of(ff->ph, struct perf_session, header); | 1763 | session = container_of(ff->ph, struct perf_session, header); |
1764 | 1764 | ||
1765 | if (session->file->is_pipe) { | 1765 | if (session->data->is_pipe) { |
1766 | /* Save events for reading later by print_event_desc, | 1766 | /* Save events for reading later by print_event_desc, |
1767 | * since they can't be read again in pipe mode. */ | 1767 | * since they can't be read again in pipe mode. */ |
1768 | ff->events = events; | 1768 | ff->events = events; |
@@ -1771,7 +1771,7 @@ process_event_desc(struct feat_fd *ff, void *data __maybe_unused) | |||
1771 | for (evsel = events; evsel->attr.size; evsel++) | 1771 | for (evsel = events; evsel->attr.size; evsel++) |
1772 | perf_evlist__set_event_name(session->evlist, evsel); | 1772 | perf_evlist__set_event_name(session->evlist, evsel); |
1773 | 1773 | ||
1774 | if (!session->file->is_pipe) | 1774 | if (!session->data->is_pipe) |
1775 | free_event_desc(events); | 1775 | free_event_desc(events); |
1776 | 1776 | ||
1777 | return 0; | 1777 | return 0; |
@@ -2248,7 +2248,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) | |||
2248 | { | 2248 | { |
2249 | struct header_print_data hd; | 2249 | struct header_print_data hd; |
2250 | struct perf_header *header = &session->header; | 2250 | struct perf_header *header = &session->header; |
2251 | int fd = perf_data_file__fd(session->file); | 2251 | int fd = perf_data__fd(session->data); |
2252 | struct stat st; | 2252 | struct stat st; |
2253 | int ret, bit; | 2253 | int ret, bit; |
2254 | 2254 | ||
@@ -2264,7 +2264,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) | |||
2264 | perf_header__process_sections(header, fd, &hd, | 2264 | perf_header__process_sections(header, fd, &hd, |
2265 | perf_file_section__fprintf_info); | 2265 | perf_file_section__fprintf_info); |
2266 | 2266 | ||
2267 | if (session->file->is_pipe) | 2267 | if (session->data->is_pipe) |
2268 | return 0; | 2268 | return 0; |
2269 | 2269 | ||
2270 | fprintf(fp, "# missing features: "); | 2270 | fprintf(fp, "# missing features: "); |
@@ -2757,7 +2757,7 @@ static int perf_header__read_pipe(struct perf_session *session) | |||
2757 | struct perf_pipe_file_header f_header; | 2757 | struct perf_pipe_file_header f_header; |
2758 | 2758 | ||
2759 | if (perf_file_header__read_pipe(&f_header, header, | 2759 | if (perf_file_header__read_pipe(&f_header, header, |
2760 | perf_data_file__fd(session->file), | 2760 | perf_data__fd(session->data), |
2761 | session->repipe) < 0) { | 2761 | session->repipe) < 0) { |
2762 | pr_debug("incompatible file format\n"); | 2762 | pr_debug("incompatible file format\n"); |
2763 | return -EINVAL; | 2763 | return -EINVAL; |
@@ -2860,13 +2860,13 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, | |||
2860 | 2860 | ||
2861 | int perf_session__read_header(struct perf_session *session) | 2861 | int perf_session__read_header(struct perf_session *session) |
2862 | { | 2862 | { |
2863 | struct perf_data_file *file = session->file; | 2863 | struct perf_data *data = session->data; |
2864 | struct perf_header *header = &session->header; | 2864 | struct perf_header *header = &session->header; |
2865 | struct perf_file_header f_header; | 2865 | struct perf_file_header f_header; |
2866 | struct perf_file_attr f_attr; | 2866 | struct perf_file_attr f_attr; |
2867 | u64 f_id; | 2867 | u64 f_id; |
2868 | int nr_attrs, nr_ids, i, j; | 2868 | int nr_attrs, nr_ids, i, j; |
2869 | int fd = perf_data_file__fd(file); | 2869 | int fd = perf_data__fd(data); |
2870 | 2870 | ||
2871 | session->evlist = perf_evlist__new(); | 2871 | session->evlist = perf_evlist__new(); |
2872 | if (session->evlist == NULL) | 2872 | if (session->evlist == NULL) |
@@ -2874,7 +2874,7 @@ int perf_session__read_header(struct perf_session *session) | |||
2874 | 2874 | ||
2875 | session->evlist->env = &header->env; | 2875 | session->evlist->env = &header->env; |
2876 | session->machines.host.env = &header->env; | 2876 | session->machines.host.env = &header->env; |
2877 | if (perf_data_file__is_pipe(file)) | 2877 | if (perf_data__is_pipe(data)) |
2878 | return perf_header__read_pipe(session); | 2878 | return perf_header__read_pipe(session); |
2879 | 2879 | ||
2880 | if (perf_file_header__read(&f_header, header, fd) < 0) | 2880 | if (perf_file_header__read(&f_header, header, fd) < 0) |
@@ -2889,7 +2889,7 @@ int perf_session__read_header(struct perf_session *session) | |||
2889 | if (f_header.data.size == 0) { | 2889 | if (f_header.data.size == 0) { |
2890 | pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" | 2890 | pr_warning("WARNING: The %s file's data size field is 0 which is unexpected.\n" |
2891 | "Was the 'perf record' command properly terminated?\n", | 2891 | "Was the 'perf record' command properly terminated?\n", |
2892 | file->path); | 2892 | data->file.path); |
2893 | } | 2893 | } |
2894 | 2894 | ||
2895 | nr_attrs = f_header.attrs.size / f_header.attr_size; | 2895 | nr_attrs = f_header.attrs.size / f_header.attr_size; |
@@ -3397,7 +3397,7 @@ int perf_event__process_tracing_data(struct perf_tool *tool __maybe_unused, | |||
3397 | struct perf_session *session) | 3397 | struct perf_session *session) |
3398 | { | 3398 | { |
3399 | ssize_t size_read, padding, size = event->tracing_data.size; | 3399 | ssize_t size_read, padding, size = event->tracing_data.size; |
3400 | int fd = perf_data_file__fd(session->file); | 3400 | int fd = perf_data__fd(session->data); |
3401 | off_t offset = lseek(fd, 0, SEEK_CUR); | 3401 | off_t offset = lseek(fd, 0, SEEK_CUR); |
3402 | char buf[BUFSIZ]; | 3402 | char buf[BUFSIZ]; |
3403 | 3403 | ||
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index 218ee2bac9a5..5325e65f9711 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c | |||
@@ -500,7 +500,7 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp) | |||
500 | } | 500 | } |
501 | 501 | ||
502 | if (!buffer->data) { | 502 | if (!buffer->data) { |
503 | int fd = perf_data_file__fd(btsq->bts->session->file); | 503 | int fd = perf_data__fd(btsq->bts->session->data); |
504 | 504 | ||
505 | buffer->data = auxtrace_buffer__get_data(buffer, fd); | 505 | buffer->data = auxtrace_buffer__get_data(buffer, fd); |
506 | if (!buffer->data) { | 506 | if (!buffer->data) { |
@@ -664,10 +664,10 @@ static int intel_bts_process_auxtrace_event(struct perf_session *session, | |||
664 | if (!bts->data_queued) { | 664 | if (!bts->data_queued) { |
665 | struct auxtrace_buffer *buffer; | 665 | struct auxtrace_buffer *buffer; |
666 | off_t data_offset; | 666 | off_t data_offset; |
667 | int fd = perf_data_file__fd(session->file); | 667 | int fd = perf_data__fd(session->data); |
668 | int err; | 668 | int err; |
669 | 669 | ||
670 | if (perf_data_file__is_pipe(session->file)) { | 670 | if (perf_data__is_pipe(session->data)) { |
671 | data_offset = 0; | 671 | data_offset = 0; |
672 | } else { | 672 | } else { |
673 | data_offset = lseek(fd, 0, SEEK_CUR); | 673 | data_offset = lseek(fd, 0, SEEK_CUR); |
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c index b58f9fd1e2ee..23f9ba676df0 100644 --- a/tools/perf/util/intel-pt.c +++ b/tools/perf/util/intel-pt.c | |||
@@ -271,7 +271,7 @@ next: | |||
271 | ptq->buffer = buffer; | 271 | ptq->buffer = buffer; |
272 | 272 | ||
273 | if (!buffer->data) { | 273 | if (!buffer->data) { |
274 | int fd = perf_data_file__fd(ptq->pt->session->file); | 274 | int fd = perf_data__fd(ptq->pt->session->data); |
275 | 275 | ||
276 | buffer->data = auxtrace_buffer__get_data(buffer, fd); | 276 | buffer->data = auxtrace_buffer__get_data(buffer, fd); |
277 | if (!buffer->data) | 277 | if (!buffer->data) |
@@ -2084,10 +2084,10 @@ static int intel_pt_process_auxtrace_event(struct perf_session *session, | |||
2084 | if (!pt->data_queued) { | 2084 | if (!pt->data_queued) { |
2085 | struct auxtrace_buffer *buffer; | 2085 | struct auxtrace_buffer *buffer; |
2086 | off_t data_offset; | 2086 | off_t data_offset; |
2087 | int fd = perf_data_file__fd(session->file); | 2087 | int fd = perf_data__fd(session->data); |
2088 | int err; | 2088 | int err; |
2089 | 2089 | ||
2090 | if (perf_data_file__is_pipe(session->file)) { | 2090 | if (perf_data__is_pipe(session->data)) { |
2091 | data_offset = 0; | 2091 | data_offset = 0; |
2092 | } else { | 2092 | } else { |
2093 | data_offset = lseek(fd, 0, SEEK_CUR); | 2093 | data_offset = lseek(fd, 0, SEEK_CUR); |
diff --git a/tools/perf/util/jit.h b/tools/perf/util/jit.h index 3f42ee4d2a0b..961e7a8a0e17 100644 --- a/tools/perf/util/jit.h +++ b/tools/perf/util/jit.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #include <data.h> | 4 | #include <data.h> |
5 | 5 | ||
6 | int jit_process(struct perf_session *session, struct perf_data_file *output, | 6 | int jit_process(struct perf_session *session, struct perf_data *output, |
7 | struct machine *machine, char *filename, pid_t pid, u64 *nbytes); | 7 | struct machine *machine, char *filename, pid_t pid, u64 *nbytes); |
8 | 8 | ||
9 | int jit_inject_record(const char *filename); | 9 | int jit_inject_record(const char *filename); |
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 9084930e1757..e7645098a323 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "sane_ctype.h" | 29 | #include "sane_ctype.h" |
30 | 30 | ||
31 | struct jit_buf_desc { | 31 | struct jit_buf_desc { |
32 | struct perf_data_file *output; | 32 | struct perf_data *output; |
33 | struct perf_session *session; | 33 | struct perf_session *session; |
34 | struct machine *machine; | 34 | struct machine *machine; |
35 | union jr_entry *entry; | 35 | union jr_entry *entry; |
@@ -60,8 +60,8 @@ struct debug_line_info { | |||
60 | 60 | ||
61 | struct jit_tool { | 61 | struct jit_tool { |
62 | struct perf_tool tool; | 62 | struct perf_tool tool; |
63 | struct perf_data_file output; | 63 | struct perf_data output; |
64 | struct perf_data_file input; | 64 | struct perf_data input; |
65 | u64 bytes_written; | 65 | u64 bytes_written; |
66 | }; | 66 | }; |
67 | 67 | ||
@@ -356,7 +356,7 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event) | |||
356 | { | 356 | { |
357 | ssize_t size; | 357 | ssize_t size; |
358 | 358 | ||
359 | size = perf_data_file__write(jd->output, event, event->header.size); | 359 | size = perf_data__write(jd->output, event, event->header.size); |
360 | if (size < 0) | 360 | if (size < 0) |
361 | return -1; | 361 | return -1; |
362 | 362 | ||
@@ -751,7 +751,7 @@ jit_detect(char *mmap_name, pid_t pid) | |||
751 | 751 | ||
752 | int | 752 | int |
753 | jit_process(struct perf_session *session, | 753 | jit_process(struct perf_session *session, |
754 | struct perf_data_file *output, | 754 | struct perf_data *output, |
755 | struct machine *machine, | 755 | struct machine *machine, |
756 | char *filename, | 756 | char *filename, |
757 | pid_t pid, | 757 | pid_t pid, |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b3fd62f7e4c9..c09b748ab599 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -32,14 +32,14 @@ static int perf_session__deliver_event(struct perf_session *session, | |||
32 | 32 | ||
33 | static int perf_session__open(struct perf_session *session) | 33 | static int perf_session__open(struct perf_session *session) |
34 | { | 34 | { |
35 | struct perf_data_file *file = session->file; | 35 | struct perf_data *data = session->data; |
36 | 36 | ||
37 | if (perf_session__read_header(session) < 0) { | 37 | if (perf_session__read_header(session) < 0) { |
38 | pr_err("incompatible file format (rerun with -v to learn more)\n"); | 38 | pr_err("incompatible file format (rerun with -v to learn more)\n"); |
39 | return -1; | 39 | return -1; |
40 | } | 40 | } |
41 | 41 | ||
42 | if (perf_data_file__is_pipe(file)) | 42 | if (perf_data__is_pipe(data)) |
43 | return 0; | 43 | return 0; |
44 | 44 | ||
45 | if (perf_header__has_feat(&session->header, HEADER_STAT)) | 45 | if (perf_header__has_feat(&session->header, HEADER_STAT)) |
@@ -120,7 +120,7 @@ static int ordered_events__deliver_event(struct ordered_events *oe, | |||
120 | session->tool, event->file_offset); | 120 | session->tool, event->file_offset); |
121 | } | 121 | } |
122 | 122 | ||
123 | struct perf_session *perf_session__new(struct perf_data_file *file, | 123 | struct perf_session *perf_session__new(struct perf_data *data, |
124 | bool repipe, struct perf_tool *tool) | 124 | bool repipe, struct perf_tool *tool) |
125 | { | 125 | { |
126 | struct perf_session *session = zalloc(sizeof(*session)); | 126 | struct perf_session *session = zalloc(sizeof(*session)); |
@@ -134,13 +134,13 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
134 | machines__init(&session->machines); | 134 | machines__init(&session->machines); |
135 | ordered_events__init(&session->ordered_events, ordered_events__deliver_event); | 135 | ordered_events__init(&session->ordered_events, ordered_events__deliver_event); |
136 | 136 | ||
137 | if (file) { | 137 | if (data) { |
138 | if (perf_data_file__open(file)) | 138 | if (perf_data__open(data)) |
139 | goto out_delete; | 139 | goto out_delete; |
140 | 140 | ||
141 | session->file = file; | 141 | session->data = data; |
142 | 142 | ||
143 | if (perf_data_file__is_read(file)) { | 143 | if (perf_data__is_read(data)) { |
144 | if (perf_session__open(session) < 0) | 144 | if (perf_session__open(session) < 0) |
145 | goto out_close; | 145 | goto out_close; |
146 | 146 | ||
@@ -148,7 +148,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
148 | * set session attributes that are present in perf.data | 148 | * set session attributes that are present in perf.data |
149 | * but not in pipe-mode. | 149 | * but not in pipe-mode. |
150 | */ | 150 | */ |
151 | if (!file->is_pipe) { | 151 | if (!data->is_pipe) { |
152 | perf_session__set_id_hdr_size(session); | 152 | perf_session__set_id_hdr_size(session); |
153 | perf_session__set_comm_exec(session); | 153 | perf_session__set_comm_exec(session); |
154 | } | 154 | } |
@@ -157,7 +157,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
157 | session->machines.host.env = &perf_env; | 157 | session->machines.host.env = &perf_env; |
158 | } | 158 | } |
159 | 159 | ||
160 | if (!file || perf_data_file__is_write(file)) { | 160 | if (!data || perf_data__is_write(data)) { |
161 | /* | 161 | /* |
162 | * In O_RDONLY mode this will be performed when reading the | 162 | * In O_RDONLY mode this will be performed when reading the |
163 | * kernel MMAP event, in perf_event__process_mmap(). | 163 | * kernel MMAP event, in perf_event__process_mmap(). |
@@ -170,7 +170,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
170 | * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is | 170 | * In pipe-mode, evlist is empty until PERF_RECORD_HEADER_ATTR is |
171 | * processed, so perf_evlist__sample_id_all is not meaningful here. | 171 | * processed, so perf_evlist__sample_id_all is not meaningful here. |
172 | */ | 172 | */ |
173 | if ((!file || !file->is_pipe) && tool && tool->ordering_requires_timestamps && | 173 | if ((!data || !data->is_pipe) && tool && tool->ordering_requires_timestamps && |
174 | tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { | 174 | tool->ordered_events && !perf_evlist__sample_id_all(session->evlist)) { |
175 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); | 175 | dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n"); |
176 | tool->ordered_events = false; | 176 | tool->ordered_events = false; |
@@ -179,7 +179,7 @@ struct perf_session *perf_session__new(struct perf_data_file *file, | |||
179 | return session; | 179 | return session; |
180 | 180 | ||
181 | out_close: | 181 | out_close: |
182 | perf_data_file__close(file); | 182 | perf_data__close(data); |
183 | out_delete: | 183 | out_delete: |
184 | perf_session__delete(session); | 184 | perf_session__delete(session); |
185 | out: | 185 | out: |
@@ -201,8 +201,8 @@ void perf_session__delete(struct perf_session *session) | |||
201 | perf_session__delete_threads(session); | 201 | perf_session__delete_threads(session); |
202 | perf_env__exit(&session->header.env); | 202 | perf_env__exit(&session->header.env); |
203 | machines__exit(&session->machines); | 203 | machines__exit(&session->machines); |
204 | if (session->file) | 204 | if (session->data) |
205 | perf_data_file__close(session->file); | 205 | perf_data__close(session->data); |
206 | free(session); | 206 | free(session); |
207 | } | 207 | } |
208 | 208 | ||
@@ -290,8 +290,8 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused, | |||
290 | __maybe_unused) | 290 | __maybe_unused) |
291 | { | 291 | { |
292 | dump_printf(": unhandled!\n"); | 292 | dump_printf(": unhandled!\n"); |
293 | if (perf_data_file__is_pipe(session->file)) | 293 | if (perf_data__is_pipe(session->data)) |
294 | skipn(perf_data_file__fd(session->file), event->auxtrace.size); | 294 | skipn(perf_data__fd(session->data), event->auxtrace.size); |
295 | return event->auxtrace.size; | 295 | return event->auxtrace.size; |
296 | } | 296 | } |
297 | 297 | ||
@@ -1349,7 +1349,7 @@ static s64 perf_session__process_user_event(struct perf_session *session, | |||
1349 | { | 1349 | { |
1350 | struct ordered_events *oe = &session->ordered_events; | 1350 | struct ordered_events *oe = &session->ordered_events; |
1351 | struct perf_tool *tool = session->tool; | 1351 | struct perf_tool *tool = session->tool; |
1352 | int fd = perf_data_file__fd(session->file); | 1352 | int fd = perf_data__fd(session->data); |
1353 | int err; | 1353 | int err; |
1354 | 1354 | ||
1355 | dump_event(session->evlist, event, file_offset, NULL); | 1355 | dump_event(session->evlist, event, file_offset, NULL); |
@@ -1449,10 +1449,10 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, | |||
1449 | goto out_parse_sample; | 1449 | goto out_parse_sample; |
1450 | } | 1450 | } |
1451 | 1451 | ||
1452 | if (perf_data_file__is_pipe(session->file)) | 1452 | if (perf_data__is_pipe(session->data)) |
1453 | return -1; | 1453 | return -1; |
1454 | 1454 | ||
1455 | fd = perf_data_file__fd(session->file); | 1455 | fd = perf_data__fd(session->data); |
1456 | hdr_sz = sizeof(struct perf_event_header); | 1456 | hdr_sz = sizeof(struct perf_event_header); |
1457 | 1457 | ||
1458 | if (buf_sz < hdr_sz) | 1458 | if (buf_sz < hdr_sz) |
@@ -1687,7 +1687,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session) | |||
1687 | { | 1687 | { |
1688 | struct ordered_events *oe = &session->ordered_events; | 1688 | struct ordered_events *oe = &session->ordered_events; |
1689 | struct perf_tool *tool = session->tool; | 1689 | struct perf_tool *tool = session->tool; |
1690 | int fd = perf_data_file__fd(session->file); | 1690 | int fd = perf_data__fd(session->data); |
1691 | union perf_event *event; | 1691 | union perf_event *event; |
1692 | uint32_t size, cur_size = 0; | 1692 | uint32_t size, cur_size = 0; |
1693 | void *buf = NULL; | 1693 | void *buf = NULL; |
@@ -1828,7 +1828,7 @@ static int __perf_session__process_events(struct perf_session *session, | |||
1828 | { | 1828 | { |
1829 | struct ordered_events *oe = &session->ordered_events; | 1829 | struct ordered_events *oe = &session->ordered_events; |
1830 | struct perf_tool *tool = session->tool; | 1830 | struct perf_tool *tool = session->tool; |
1831 | int fd = perf_data_file__fd(session->file); | 1831 | int fd = perf_data__fd(session->data); |
1832 | u64 head, page_offset, file_offset, file_pos, size; | 1832 | u64 head, page_offset, file_offset, file_pos, size; |
1833 | int err, mmap_prot, mmap_flags, map_idx = 0; | 1833 | int err, mmap_prot, mmap_flags, map_idx = 0; |
1834 | size_t mmap_size; | 1834 | size_t mmap_size; |
@@ -1945,13 +1945,13 @@ out_err: | |||
1945 | 1945 | ||
1946 | int perf_session__process_events(struct perf_session *session) | 1946 | int perf_session__process_events(struct perf_session *session) |
1947 | { | 1947 | { |
1948 | u64 size = perf_data_file__size(session->file); | 1948 | u64 size = perf_data__size(session->data); |
1949 | int err; | 1949 | int err; |
1950 | 1950 | ||
1951 | if (perf_session__register_idle_thread(session) < 0) | 1951 | if (perf_session__register_idle_thread(session) < 0) |
1952 | return -ENOMEM; | 1952 | return -ENOMEM; |
1953 | 1953 | ||
1954 | if (!perf_data_file__is_pipe(session->file)) | 1954 | if (!perf_data__is_pipe(session->data)) |
1955 | err = __perf_session__process_events(session, | 1955 | err = __perf_session__process_events(session, |
1956 | session->header.data_offset, | 1956 | session->header.data_offset, |
1957 | session->header.data_size, size); | 1957 | session->header.data_size, size); |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 47b5e7dbcb18..cc1c5ea53c39 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -32,13 +32,13 @@ struct perf_session { | |||
32 | void *one_mmap_addr; | 32 | void *one_mmap_addr; |
33 | u64 one_mmap_offset; | 33 | u64 one_mmap_offset; |
34 | struct ordered_events ordered_events; | 34 | struct ordered_events ordered_events; |
35 | struct perf_data_file *file; | 35 | struct perf_data *data; |
36 | struct perf_tool *tool; | 36 | struct perf_tool *tool; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct perf_tool; | 39 | struct perf_tool; |
40 | 40 | ||
41 | struct perf_session *perf_session__new(struct perf_data_file *file, | 41 | struct perf_session *perf_session__new(struct perf_data *data, |
42 | bool repipe, struct perf_tool *tool); | 42 | bool repipe, struct perf_tool *tool); |
43 | void perf_session__delete(struct perf_session *session); | 43 | void perf_session__delete(struct perf_session *session); |
44 | 44 | ||
diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index c143c3bc1ef8..ad1b46f1f2cf 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include "util/debug.h" | 10 | #include "util/debug.h" |
11 | #include "util/callchain.h" | 11 | #include "util/callchain.h" |
12 | #include "srcline.h" | 12 | #include "srcline.h" |
13 | 13 | #include "string2.h" | |
14 | #include "symbol.h" | 14 | #include "symbol.h" |
15 | 15 | ||
16 | bool srcline_full_filename; | 16 | bool srcline_full_filename; |
@@ -77,6 +77,41 @@ static char *srcline_from_fileline(const char *file, unsigned int line) | |||
77 | return srcline; | 77 | return srcline; |
78 | } | 78 | } |
79 | 79 | ||
80 | static struct symbol *new_inline_sym(struct dso *dso, | ||
81 | struct symbol *base_sym, | ||
82 | const char *funcname) | ||
83 | { | ||
84 | struct symbol *inline_sym; | ||
85 | char *demangled = NULL; | ||
86 | |||
87 | if (dso) { | ||
88 | demangled = dso__demangle_sym(dso, 0, funcname); | ||
89 | if (demangled) | ||
90 | funcname = demangled; | ||
91 | } | ||
92 | |||
93 | if (base_sym && strcmp(funcname, base_sym->name) == 0) { | ||
94 | /* reuse the real, existing symbol */ | ||
95 | inline_sym = base_sym; | ||
96 | /* ensure that we don't alias an inlined symbol, which could | ||
97 | * lead to double frees in inline_node__delete | ||
98 | */ | ||
99 | assert(!base_sym->inlined); | ||
100 | } else { | ||
101 | /* create a fake symbol for the inline frame */ | ||
102 | inline_sym = symbol__new(base_sym ? base_sym->start : 0, | ||
103 | base_sym ? base_sym->end : 0, | ||
104 | base_sym ? base_sym->binding : 0, | ||
105 | funcname); | ||
106 | if (inline_sym) | ||
107 | inline_sym->inlined = 1; | ||
108 | } | ||
109 | |||
110 | free(demangled); | ||
111 | |||
112 | return inline_sym; | ||
113 | } | ||
114 | |||
80 | #ifdef HAVE_LIBBFD_SUPPORT | 115 | #ifdef HAVE_LIBBFD_SUPPORT |
81 | 116 | ||
82 | /* | 117 | /* |
@@ -219,41 +254,6 @@ static void addr2line_cleanup(struct a2l_data *a2l) | |||
219 | 254 | ||
220 | #define MAX_INLINE_NEST 1024 | 255 | #define MAX_INLINE_NEST 1024 |
221 | 256 | ||
222 | static struct symbol *new_inline_sym(struct dso *dso, | ||
223 | struct symbol *base_sym, | ||
224 | const char *funcname) | ||
225 | { | ||
226 | struct symbol *inline_sym; | ||
227 | char *demangled = NULL; | ||
228 | |||
229 | if (dso) { | ||
230 | demangled = dso__demangle_sym(dso, 0, funcname); | ||
231 | if (demangled) | ||
232 | funcname = demangled; | ||
233 | } | ||
234 | |||
235 | if (base_sym && strcmp(funcname, base_sym->name) == 0) { | ||
236 | /* reuse the real, existing symbol */ | ||
237 | inline_sym = base_sym; | ||
238 | /* ensure that we don't alias an inlined symbol, which could | ||
239 | * lead to double frees in inline_node__delete | ||
240 | */ | ||
241 | assert(!base_sym->inlined); | ||
242 | } else { | ||
243 | /* create a fake symbol for the inline frame */ | ||
244 | inline_sym = symbol__new(base_sym ? base_sym->start : 0, | ||
245 | base_sym ? base_sym->end : 0, | ||
246 | base_sym ? base_sym->binding : 0, | ||
247 | funcname); | ||
248 | if (inline_sym) | ||
249 | inline_sym->inlined = 1; | ||
250 | } | ||
251 | |||
252 | free(demangled); | ||
253 | |||
254 | return inline_sym; | ||
255 | } | ||
256 | |||
257 | static int inline_list__append_dso_a2l(struct dso *dso, | 257 | static int inline_list__append_dso_a2l(struct dso *dso, |
258 | struct inline_node *node, | 258 | struct inline_node *node, |
259 | struct symbol *sym) | 259 | struct symbol *sym) |
@@ -432,10 +432,11 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr, | |||
432 | char cmd[PATH_MAX]; | 432 | char cmd[PATH_MAX]; |
433 | struct inline_node *node; | 433 | struct inline_node *node; |
434 | char *filename = NULL; | 434 | char *filename = NULL; |
435 | size_t len; | 435 | char *funcname = NULL; |
436 | size_t filelen, funclen; | ||
436 | unsigned int line_nr = 0; | 437 | unsigned int line_nr = 0; |
437 | 438 | ||
438 | scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i %016"PRIx64, | 439 | scnprintf(cmd, sizeof(cmd), "addr2line -e %s -i -f %016"PRIx64, |
439 | dso_name, addr); | 440 | dso_name, addr); |
440 | 441 | ||
441 | fp = popen(cmd, "r"); | 442 | fp = popen(cmd, "r"); |
@@ -453,23 +454,34 @@ static struct inline_node *addr2inlines(const char *dso_name, u64 addr, | |||
453 | INIT_LIST_HEAD(&node->val); | 454 | INIT_LIST_HEAD(&node->val); |
454 | node->addr = addr; | 455 | node->addr = addr; |
455 | 456 | ||
456 | while (getline(&filename, &len, fp) != -1) { | 457 | /* addr2line -f generates two lines for each inlined functions */ |
458 | while (getline(&funcname, &funclen, fp) != -1) { | ||
457 | char *srcline; | 459 | char *srcline; |
460 | struct symbol *inline_sym; | ||
461 | |||
462 | rtrim(funcname); | ||
458 | 463 | ||
459 | if (filename_split(filename, &line_nr) != 1) { | 464 | if (getline(&filename, &filelen, fp) == -1) |
460 | free(filename); | ||
461 | goto out; | 465 | goto out; |
462 | } | ||
463 | 466 | ||
464 | srcline = srcline_from_fileline(filename, line_nr); | 467 | if (filename_split(filename, &line_nr) != 1) |
465 | if (inline_list__append(sym, srcline, node) != 0) | ||
466 | goto out; | 468 | goto out; |
467 | 469 | ||
468 | filename = NULL; | 470 | srcline = srcline_from_fileline(filename, line_nr); |
471 | inline_sym = new_inline_sym(dso, sym, funcname); | ||
472 | |||
473 | if (inline_list__append(inline_sym, srcline, node) != 0) { | ||
474 | free(srcline); | ||
475 | if (inline_sym && inline_sym->inlined) | ||
476 | symbol__delete(inline_sym); | ||
477 | goto out; | ||
478 | } | ||
469 | } | 479 | } |
470 | 480 | ||
471 | out: | 481 | out: |
472 | pclose(fp); | 482 | pclose(fp); |
483 | free(filename); | ||
484 | free(funcname); | ||
473 | 485 | ||
474 | return node; | 486 | return node; |
475 | } | 487 | } |
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index a2c12d1ef32a..51ad03a799ec 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c | |||
@@ -178,58 +178,60 @@ void perf_stat__reset_shadow_stats(void) | |||
178 | * more semantic information such as miss/hit ratios, | 178 | * more semantic information such as miss/hit ratios, |
179 | * instruction rates, etc: | 179 | * instruction rates, etc: |
180 | */ | 180 | */ |
181 | void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, | 181 | void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, |
182 | int cpu) | 182 | int cpu) |
183 | { | 183 | { |
184 | int ctx = evsel_context(counter); | 184 | int ctx = evsel_context(counter); |
185 | 185 | ||
186 | count *= counter->scale; | ||
187 | |||
186 | if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) || | 188 | if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) || |
187 | perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK)) | 189 | perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK)) |
188 | update_stats(&runtime_nsecs_stats[cpu], count[0]); | 190 | update_stats(&runtime_nsecs_stats[cpu], count); |
189 | else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) | 191 | else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) |
190 | update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); | 192 | update_stats(&runtime_cycles_stats[ctx][cpu], count); |
191 | else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) | 193 | else if (perf_stat_evsel__is(counter, CYCLES_IN_TX)) |
192 | update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]); | 194 | update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count); |
193 | else if (perf_stat_evsel__is(counter, TRANSACTION_START)) | 195 | else if (perf_stat_evsel__is(counter, TRANSACTION_START)) |
194 | update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); | 196 | update_stats(&runtime_transaction_stats[ctx][cpu], count); |
195 | else if (perf_stat_evsel__is(counter, ELISION_START)) | 197 | else if (perf_stat_evsel__is(counter, ELISION_START)) |
196 | update_stats(&runtime_elision_stats[ctx][cpu], count[0]); | 198 | update_stats(&runtime_elision_stats[ctx][cpu], count); |
197 | else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS)) | 199 | else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS)) |
198 | update_stats(&runtime_topdown_total_slots[ctx][cpu], count[0]); | 200 | update_stats(&runtime_topdown_total_slots[ctx][cpu], count); |
199 | else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED)) | 201 | else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED)) |
200 | update_stats(&runtime_topdown_slots_issued[ctx][cpu], count[0]); | 202 | update_stats(&runtime_topdown_slots_issued[ctx][cpu], count); |
201 | else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED)) | 203 | else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED)) |
202 | update_stats(&runtime_topdown_slots_retired[ctx][cpu], count[0]); | 204 | update_stats(&runtime_topdown_slots_retired[ctx][cpu], count); |
203 | else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES)) | 205 | else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES)) |
204 | update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu],count[0]); | 206 | update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu], count); |
205 | else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES)) | 207 | else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES)) |
206 | update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count[0]); | 208 | update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count); |
207 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) | 209 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) |
208 | update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); | 210 | update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count); |
209 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) | 211 | else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) |
210 | update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count[0]); | 212 | update_stats(&runtime_stalled_cycles_back_stats[ctx][cpu], count); |
211 | else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) | 213 | else if (perf_evsel__match(counter, HARDWARE, HW_BRANCH_INSTRUCTIONS)) |
212 | update_stats(&runtime_branches_stats[ctx][cpu], count[0]); | 214 | update_stats(&runtime_branches_stats[ctx][cpu], count); |
213 | else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) | 215 | else if (perf_evsel__match(counter, HARDWARE, HW_CACHE_REFERENCES)) |
214 | update_stats(&runtime_cacherefs_stats[ctx][cpu], count[0]); | 216 | update_stats(&runtime_cacherefs_stats[ctx][cpu], count); |
215 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) | 217 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1D)) |
216 | update_stats(&runtime_l1_dcache_stats[ctx][cpu], count[0]); | 218 | update_stats(&runtime_l1_dcache_stats[ctx][cpu], count); |
217 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) | 219 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_L1I)) |
218 | update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]); | 220 | update_stats(&runtime_ll_cache_stats[ctx][cpu], count); |
219 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) | 221 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_LL)) |
220 | update_stats(&runtime_ll_cache_stats[ctx][cpu], count[0]); | 222 | update_stats(&runtime_ll_cache_stats[ctx][cpu], count); |
221 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) | 223 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_DTLB)) |
222 | update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count[0]); | 224 | update_stats(&runtime_dtlb_cache_stats[ctx][cpu], count); |
223 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) | 225 | else if (perf_evsel__match(counter, HW_CACHE, HW_CACHE_ITLB)) |
224 | update_stats(&runtime_itlb_cache_stats[ctx][cpu], count[0]); | 226 | update_stats(&runtime_itlb_cache_stats[ctx][cpu], count); |
225 | else if (perf_stat_evsel__is(counter, SMI_NUM)) | 227 | else if (perf_stat_evsel__is(counter, SMI_NUM)) |
226 | update_stats(&runtime_smi_num_stats[ctx][cpu], count[0]); | 228 | update_stats(&runtime_smi_num_stats[ctx][cpu], count); |
227 | else if (perf_stat_evsel__is(counter, APERF)) | 229 | else if (perf_stat_evsel__is(counter, APERF)) |
228 | update_stats(&runtime_aperf_stats[ctx][cpu], count[0]); | 230 | update_stats(&runtime_aperf_stats[ctx][cpu], count); |
229 | 231 | ||
230 | if (counter->collect_stat) { | 232 | if (counter->collect_stat) { |
231 | struct saved_value *v = saved_value_lookup(counter, cpu, true); | 233 | struct saved_value *v = saved_value_lookup(counter, cpu, true); |
232 | update_stats(&v->stats, count[0]); | 234 | update_stats(&v->stats, count); |
233 | } | 235 | } |
234 | } | 236 | } |
235 | 237 | ||
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c index 35e9848734d6..203f5d8d11d1 100644 --- a/tools/perf/util/stat.c +++ b/tools/perf/util/stat.c | |||
@@ -69,7 +69,7 @@ double rel_stddev_stats(double stddev, double avg) | |||
69 | bool __perf_evsel_stat__is(struct perf_evsel *evsel, | 69 | bool __perf_evsel_stat__is(struct perf_evsel *evsel, |
70 | enum perf_stat_evsel_id id) | 70 | enum perf_stat_evsel_id id) |
71 | { | 71 | { |
72 | struct perf_stat_evsel *ps = evsel->priv; | 72 | struct perf_stat_evsel *ps = evsel->stats; |
73 | 73 | ||
74 | return ps->id == id; | 74 | return ps->id == id; |
75 | } | 75 | } |
@@ -93,7 +93,7 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = { | |||
93 | 93 | ||
94 | void perf_stat_evsel_id_init(struct perf_evsel *evsel) | 94 | void perf_stat_evsel_id_init(struct perf_evsel *evsel) |
95 | { | 95 | { |
96 | struct perf_stat_evsel *ps = evsel->priv; | 96 | struct perf_stat_evsel *ps = evsel->stats; |
97 | int i; | 97 | int i; |
98 | 98 | ||
99 | /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ | 99 | /* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */ |
@@ -109,7 +109,7 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel) | |||
109 | static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) | 109 | static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) |
110 | { | 110 | { |
111 | int i; | 111 | int i; |
112 | struct perf_stat_evsel *ps = evsel->priv; | 112 | struct perf_stat_evsel *ps = evsel->stats; |
113 | 113 | ||
114 | for (i = 0; i < 3; i++) | 114 | for (i = 0; i < 3; i++) |
115 | init_stats(&ps->res_stats[i]); | 115 | init_stats(&ps->res_stats[i]); |
@@ -119,8 +119,8 @@ static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) | |||
119 | 119 | ||
120 | static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) | 120 | static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) |
121 | { | 121 | { |
122 | evsel->priv = zalloc(sizeof(struct perf_stat_evsel)); | 122 | evsel->stats = zalloc(sizeof(struct perf_stat_evsel)); |
123 | if (evsel->priv == NULL) | 123 | if (evsel->stats == NULL) |
124 | return -ENOMEM; | 124 | return -ENOMEM; |
125 | perf_evsel__reset_stat_priv(evsel); | 125 | perf_evsel__reset_stat_priv(evsel); |
126 | return 0; | 126 | return 0; |
@@ -128,11 +128,11 @@ static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) | |||
128 | 128 | ||
129 | static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) | 129 | static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) |
130 | { | 130 | { |
131 | struct perf_stat_evsel *ps = evsel->priv; | 131 | struct perf_stat_evsel *ps = evsel->stats; |
132 | 132 | ||
133 | if (ps) | 133 | if (ps) |
134 | free(ps->group_data); | 134 | free(ps->group_data); |
135 | zfree(&evsel->priv); | 135 | zfree(&evsel->stats); |
136 | } | 136 | } |
137 | 137 | ||
138 | static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, | 138 | static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel, |
@@ -277,7 +277,9 @@ process_counter_values(struct perf_stat_config *config, struct perf_evsel *evsel | |||
277 | perf_evsel__compute_deltas(evsel, cpu, thread, count); | 277 | perf_evsel__compute_deltas(evsel, cpu, thread, count); |
278 | perf_counts_values__scale(count, config->scale, NULL); | 278 | perf_counts_values__scale(count, config->scale, NULL); |
279 | if (config->aggr_mode == AGGR_NONE) | 279 | if (config->aggr_mode == AGGR_NONE) |
280 | perf_stat__update_shadow_stats(evsel, count->values, cpu); | 280 | perf_stat__update_shadow_stats(evsel, count->val, cpu); |
281 | if (config->aggr_mode == AGGR_THREAD) | ||
282 | perf_stat__update_shadow_stats(evsel, count->val, 0); | ||
281 | break; | 283 | break; |
282 | case AGGR_GLOBAL: | 284 | case AGGR_GLOBAL: |
283 | aggr->val += count->val; | 285 | aggr->val += count->val; |
@@ -318,9 +320,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, | |||
318 | struct perf_evsel *counter) | 320 | struct perf_evsel *counter) |
319 | { | 321 | { |
320 | struct perf_counts_values *aggr = &counter->counts->aggr; | 322 | struct perf_counts_values *aggr = &counter->counts->aggr; |
321 | struct perf_stat_evsel *ps = counter->priv; | 323 | struct perf_stat_evsel *ps = counter->stats; |
322 | u64 *count = counter->counts->aggr.values; | 324 | u64 *count = counter->counts->aggr.values; |
323 | u64 val; | ||
324 | int i, ret; | 325 | int i, ret; |
325 | 326 | ||
326 | aggr->val = aggr->ena = aggr->run = 0; | 327 | aggr->val = aggr->ena = aggr->run = 0; |
@@ -360,8 +361,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, | |||
360 | /* | 361 | /* |
361 | * Save the full runtime - to allow normalization during printout: | 362 | * Save the full runtime - to allow normalization during printout: |
362 | */ | 363 | */ |
363 | val = counter->scale * *count; | 364 | perf_stat__update_shadow_stats(counter, *count, 0); |
364 | perf_stat__update_shadow_stats(counter, &val, 0); | ||
365 | 365 | ||
366 | return 0; | 366 | return 0; |
367 | } | 367 | } |
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h index 47915df346fb..490b78aa7230 100644 --- a/tools/perf/util/stat.h +++ b/tools/perf/util/stat.h | |||
@@ -82,7 +82,7 @@ typedef void (*new_line_t )(void *ctx); | |||
82 | 82 | ||
83 | void perf_stat__init_shadow_stats(void); | 83 | void perf_stat__init_shadow_stats(void); |
84 | void perf_stat__reset_shadow_stats(void); | 84 | void perf_stat__reset_shadow_stats(void); |
85 | void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count, | 85 | void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 count, |
86 | int cpu); | 86 | int cpu); |
87 | struct perf_stat_output_ctx { | 87 | struct perf_stat_output_ctx { |
88 | void *ctx; | 88 | void *ctx; |