diff options
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 14 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-top.txt | 18 | ||||
-rw-r--r-- | tools/perf/builtin-kvm.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 73 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 33 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 8 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 1 | ||||
-rw-r--r-- | tools/perf/tests/keep-tracking.c | 1 | ||||
-rw-r--r-- | tools/perf/tests/mmap-basic.c | 1 | ||||
-rw-r--r-- | tools/perf/tests/open-syscall-tp-fields.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/perf-record.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/perf-time-to-tsc.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/sw-clock.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/task-exit.c | 6 | ||||
-rw-r--r-- | tools/perf/ui/stdio/hist.c | 9 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 3 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 13 | ||||
-rw-r--r-- | tools/perf/util/evlist.h | 2 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 13 | ||||
-rw-r--r-- | tools/perf/util/python.c | 2 |
20 files changed, 151 insertions, 67 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index e297b74471b8..ca0d3d9f4bac 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -90,8 +90,20 @@ OPTIONS | |||
90 | Number of mmap data pages. Must be a power of two. | 90 | Number of mmap data pages. Must be a power of two. |
91 | 91 | ||
92 | -g:: | 92 | -g:: |
93 | Enables call-graph (stack chain/backtrace) recording. | ||
94 | |||
93 | --call-graph:: | 95 | --call-graph:: |
94 | Do call-graph (stack chain/backtrace) recording. | 96 | Setup and enable call-graph (stack chain/backtrace) recording, |
97 | implies -g. | ||
98 | |||
99 | Allows specifying "fp" (frame pointer) or "dwarf" | ||
100 | (DWARF's CFI - Call Frame Information) as the method to collect | ||
101 | the information used to show the call graphs. | ||
102 | |||
103 | In some systems, where binaries are build with gcc | ||
104 | --fomit-frame-pointer, using the "fp" method will produce bogus | ||
105 | call graphs, using "dwarf", if available (perf tools linked to | ||
106 | the libunwind library) should be used instead. | ||
95 | 107 | ||
96 | -q:: | 108 | -q:: |
97 | --quiet:: | 109 | --quiet:: |
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 58d6598a9686..6a118e71d003 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -140,20 +140,12 @@ Default is to monitor all CPUS. | |||
140 | --asm-raw:: | 140 | --asm-raw:: |
141 | Show raw instruction encoding of assembly instructions. | 141 | Show raw instruction encoding of assembly instructions. |
142 | 142 | ||
143 | -G [type,min,order]:: | 143 | -G:: |
144 | Enables call-graph (stack chain/backtrace) recording. | ||
145 | |||
144 | --call-graph:: | 146 | --call-graph:: |
145 | Display call chains using type, min percent threshold and order. | 147 | Setup and enable call-graph (stack chain/backtrace) recording, |
146 | type can be either: | 148 | implies -G. |
147 | - flat: single column, linear exposure of call chains. | ||
148 | - graph: use a graph tree, displaying absolute overhead rates. | ||
149 | - fractal: like graph, but displays relative rates. Each branch of | ||
150 | the tree is considered as a new profiled object. | ||
151 | |||
152 | order can be either: | ||
153 | - callee: callee based call graph. | ||
154 | - caller: inverted caller based call graph. | ||
155 | |||
156 | Default: fractal,0.5,callee. | ||
157 | 149 | ||
158 | --ignore-callees=<regex>:: | 150 | --ignore-callees=<regex>:: |
159 | Ignore callees of the function(s) matching the given regex. | 151 | Ignore callees of the function(s) matching the given regex. |
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 935d52216c89..fbc2888d6495 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -888,11 +888,18 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx, | |||
888 | while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { | 888 | while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) { |
889 | err = perf_evlist__parse_sample(kvm->evlist, event, &sample); | 889 | err = perf_evlist__parse_sample(kvm->evlist, event, &sample); |
890 | if (err) { | 890 | if (err) { |
891 | perf_evlist__mmap_consume(kvm->evlist, idx); | ||
891 | pr_err("Failed to parse sample\n"); | 892 | pr_err("Failed to parse sample\n"); |
892 | return -1; | 893 | return -1; |
893 | } | 894 | } |
894 | 895 | ||
895 | err = perf_session_queue_event(kvm->session, event, &sample, 0); | 896 | err = perf_session_queue_event(kvm->session, event, &sample, 0); |
897 | /* | ||
898 | * FIXME: Here we can't consume the event, as perf_session_queue_event will | ||
899 | * point to it, and it'll get possibly overwritten by the kernel. | ||
900 | */ | ||
901 | perf_evlist__mmap_consume(kvm->evlist, idx); | ||
902 | |||
896 | if (err) { | 903 | if (err) { |
897 | pr_err("Failed to enqueue sample: %d\n", err); | 904 | pr_err("Failed to enqueue sample: %d\n", err); |
898 | return -1; | 905 | return -1; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a41ac41546c9..d04651484640 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -712,21 +712,12 @@ static int get_stack_size(char *str, unsigned long *_size) | |||
712 | } | 712 | } |
713 | #endif /* LIBUNWIND_SUPPORT */ | 713 | #endif /* LIBUNWIND_SUPPORT */ |
714 | 714 | ||
715 | int record_parse_callchain_opt(const struct option *opt, | 715 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts) |
716 | const char *arg, int unset) | ||
717 | { | 716 | { |
718 | struct perf_record_opts *opts = opt->value; | ||
719 | char *tok, *name, *saveptr = NULL; | 717 | char *tok, *name, *saveptr = NULL; |
720 | char *buf; | 718 | char *buf; |
721 | int ret = -1; | 719 | int ret = -1; |
722 | 720 | ||
723 | /* --no-call-graph */ | ||
724 | if (unset) | ||
725 | return 0; | ||
726 | |||
727 | /* We specified default option if none is provided. */ | ||
728 | BUG_ON(!arg); | ||
729 | |||
730 | /* We need buffer that we know we can write to. */ | 721 | /* We need buffer that we know we can write to. */ |
731 | buf = malloc(strlen(arg) + 1); | 722 | buf = malloc(strlen(arg) + 1); |
732 | if (!buf) | 723 | if (!buf) |
@@ -764,13 +755,9 @@ int record_parse_callchain_opt(const struct option *opt, | |||
764 | ret = get_stack_size(tok, &size); | 755 | ret = get_stack_size(tok, &size); |
765 | opts->stack_dump_size = size; | 756 | opts->stack_dump_size = size; |
766 | } | 757 | } |
767 | |||
768 | if (!ret) | ||
769 | pr_debug("callchain: stack dump size %d\n", | ||
770 | opts->stack_dump_size); | ||
771 | #endif /* LIBUNWIND_SUPPORT */ | 758 | #endif /* LIBUNWIND_SUPPORT */ |
772 | } else { | 759 | } else { |
773 | pr_err("callchain: Unknown -g option " | 760 | pr_err("callchain: Unknown --call-graph option " |
774 | "value: %s\n", arg); | 761 | "value: %s\n", arg); |
775 | break; | 762 | break; |
776 | } | 763 | } |
@@ -778,13 +765,52 @@ int record_parse_callchain_opt(const struct option *opt, | |||
778 | } while (0); | 765 | } while (0); |
779 | 766 | ||
780 | free(buf); | 767 | free(buf); |
768 | return ret; | ||
769 | } | ||
770 | |||
771 | static void callchain_debug(struct perf_record_opts *opts) | ||
772 | { | ||
773 | pr_debug("callchain: type %d\n", opts->call_graph); | ||
781 | 774 | ||
775 | if (opts->call_graph == CALLCHAIN_DWARF) | ||
776 | pr_debug("callchain: stack dump size %d\n", | ||
777 | opts->stack_dump_size); | ||
778 | } | ||
779 | |||
780 | int record_parse_callchain_opt(const struct option *opt, | ||
781 | const char *arg, | ||
782 | int unset) | ||
783 | { | ||
784 | struct perf_record_opts *opts = opt->value; | ||
785 | int ret; | ||
786 | |||
787 | /* --no-call-graph */ | ||
788 | if (unset) { | ||
789 | opts->call_graph = CALLCHAIN_NONE; | ||
790 | pr_debug("callchain: disabled\n"); | ||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | ret = record_parse_callchain(arg, opts); | ||
782 | if (!ret) | 795 | if (!ret) |
783 | pr_debug("callchain: type %d\n", opts->call_graph); | 796 | callchain_debug(opts); |
784 | 797 | ||
785 | return ret; | 798 | return ret; |
786 | } | 799 | } |
787 | 800 | ||
801 | int record_callchain_opt(const struct option *opt, | ||
802 | const char *arg __maybe_unused, | ||
803 | int unset __maybe_unused) | ||
804 | { | ||
805 | struct perf_record_opts *opts = opt->value; | ||
806 | |||
807 | if (opts->call_graph == CALLCHAIN_NONE) | ||
808 | opts->call_graph = CALLCHAIN_FP; | ||
809 | |||
810 | callchain_debug(opts); | ||
811 | return 0; | ||
812 | } | ||
813 | |||
788 | static const char * const record_usage[] = { | 814 | static const char * const record_usage[] = { |
789 | "perf record [<options>] [<command>]", | 815 | "perf record [<options>] [<command>]", |
790 | "perf record [<options>] -- <command> [<options>]", | 816 | "perf record [<options>] -- <command> [<options>]", |
@@ -813,12 +839,12 @@ static struct perf_record record = { | |||
813 | }, | 839 | }, |
814 | }; | 840 | }; |
815 | 841 | ||
816 | #define CALLCHAIN_HELP "do call-graph (stack chain/backtrace) recording: " | 842 | #define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: " |
817 | 843 | ||
818 | #ifdef LIBUNWIND_SUPPORT | 844 | #ifdef LIBUNWIND_SUPPORT |
819 | const char record_callchain_help[] = CALLCHAIN_HELP "[fp] dwarf"; | 845 | const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf"; |
820 | #else | 846 | #else |
821 | const char record_callchain_help[] = CALLCHAIN_HELP "[fp]"; | 847 | const char record_callchain_help[] = CALLCHAIN_HELP "fp"; |
822 | #endif | 848 | #endif |
823 | 849 | ||
824 | /* | 850 | /* |
@@ -858,9 +884,12 @@ const struct option record_options[] = { | |||
858 | "number of mmap data pages"), | 884 | "number of mmap data pages"), |
859 | OPT_BOOLEAN(0, "group", &record.opts.group, | 885 | OPT_BOOLEAN(0, "group", &record.opts.group, |
860 | "put the counters into a counter group"), | 886 | "put the counters into a counter group"), |
861 | OPT_CALLBACK_DEFAULT('g', "call-graph", &record.opts, | 887 | OPT_CALLBACK_NOOPT('g', NULL, &record.opts, |
862 | "mode[,dump_size]", record_callchain_help, | 888 | NULL, "enables call-graph recording" , |
863 | &record_parse_callchain_opt, "fp"), | 889 | &record_callchain_opt), |
890 | OPT_CALLBACK(0, "call-graph", &record.opts, | ||
891 | "mode[,dump_size]", record_callchain_help, | ||
892 | &record_parse_callchain_opt), | ||
864 | OPT_INCR('v', "verbose", &verbose, | 893 | OPT_INCR('v', "verbose", &verbose, |
865 | "be more verbose (show counter open errors, etc)"), | 894 | "be more verbose (show counter open errors, etc)"), |
866 | OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), | 895 | OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 212214162bb2..5a11f13e56f9 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -810,7 +810,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
810 | ret = perf_evlist__parse_sample(top->evlist, event, &sample); | 810 | ret = perf_evlist__parse_sample(top->evlist, event, &sample); |
811 | if (ret) { | 811 | if (ret) { |
812 | pr_err("Can't parse sample, err = %d\n", ret); | 812 | pr_err("Can't parse sample, err = %d\n", ret); |
813 | continue; | 813 | goto next_event; |
814 | } | 814 | } |
815 | 815 | ||
816 | evsel = perf_evlist__id2evsel(session->evlist, sample.id); | 816 | evsel = perf_evlist__id2evsel(session->evlist, sample.id); |
@@ -825,13 +825,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
825 | case PERF_RECORD_MISC_USER: | 825 | case PERF_RECORD_MISC_USER: |
826 | ++top->us_samples; | 826 | ++top->us_samples; |
827 | if (top->hide_user_symbols) | 827 | if (top->hide_user_symbols) |
828 | continue; | 828 | goto next_event; |
829 | machine = &session->machines.host; | 829 | machine = &session->machines.host; |
830 | break; | 830 | break; |
831 | case PERF_RECORD_MISC_KERNEL: | 831 | case PERF_RECORD_MISC_KERNEL: |
832 | ++top->kernel_samples; | 832 | ++top->kernel_samples; |
833 | if (top->hide_kernel_symbols) | 833 | if (top->hide_kernel_symbols) |
834 | continue; | 834 | goto next_event; |
835 | machine = &session->machines.host; | 835 | machine = &session->machines.host; |
836 | break; | 836 | break; |
837 | case PERF_RECORD_MISC_GUEST_KERNEL: | 837 | case PERF_RECORD_MISC_GUEST_KERNEL: |
@@ -847,7 +847,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
847 | */ | 847 | */ |
848 | /* Fall thru */ | 848 | /* Fall thru */ |
849 | default: | 849 | default: |
850 | continue; | 850 | goto next_event; |
851 | } | 851 | } |
852 | 852 | ||
853 | 853 | ||
@@ -859,6 +859,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
859 | machine__process_event(machine, event); | 859 | machine__process_event(machine, event); |
860 | } else | 860 | } else |
861 | ++session->stats.nr_unknown_events; | 861 | ++session->stats.nr_unknown_events; |
862 | next_event: | ||
863 | perf_evlist__mmap_consume(top->evlist, idx); | ||
862 | } | 864 | } |
863 | } | 865 | } |
864 | 866 | ||
@@ -1016,16 +1018,16 @@ out_delete: | |||
1016 | } | 1018 | } |
1017 | 1019 | ||
1018 | static int | 1020 | static int |
1019 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) | 1021 | callchain_opt(const struct option *opt, const char *arg, int unset) |
1020 | { | 1022 | { |
1021 | /* | ||
1022 | * --no-call-graph | ||
1023 | */ | ||
1024 | if (unset) | ||
1025 | return 0; | ||
1026 | |||
1027 | symbol_conf.use_callchain = true; | 1023 | symbol_conf.use_callchain = true; |
1024 | return record_callchain_opt(opt, arg, unset); | ||
1025 | } | ||
1028 | 1026 | ||
1027 | static int | ||
1028 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) | ||
1029 | { | ||
1030 | symbol_conf.use_callchain = true; | ||
1029 | return record_parse_callchain_opt(opt, arg, unset); | 1031 | return record_parse_callchain_opt(opt, arg, unset); |
1030 | } | 1032 | } |
1031 | 1033 | ||
@@ -1106,9 +1108,12 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1106 | "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"), | 1108 | "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"), |
1107 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, | 1109 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, |
1108 | "Show a column with the number of samples"), | 1110 | "Show a column with the number of samples"), |
1109 | OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, | 1111 | OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts, |
1110 | "mode[,dump_size]", record_callchain_help, | 1112 | NULL, "enables call-graph recording", |
1111 | &parse_callchain_opt, "fp"), | 1113 | &callchain_opt), |
1114 | OPT_CALLBACK(0, "call-graph", &top.record_opts, | ||
1115 | "mode[,dump_size]", record_callchain_help, | ||
1116 | &parse_callchain_opt), | ||
1112 | OPT_CALLBACK(0, "ignore-callees", NULL, "regex", | 1117 | OPT_CALLBACK(0, "ignore-callees", NULL, "regex", |
1113 | "ignore callees of these functions in call graphs", | 1118 | "ignore callees of these functions in call graphs", |
1114 | report_parse_ignore_callees_opt), | 1119 | report_parse_ignore_callees_opt), |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 71aa3e35406b..99c8d9ad6729 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -987,7 +987,7 @@ again: | |||
987 | err = perf_evlist__parse_sample(evlist, event, &sample); | 987 | err = perf_evlist__parse_sample(evlist, event, &sample); |
988 | if (err) { | 988 | if (err) { |
989 | fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err); | 989 | fprintf(trace->output, "Can't parse sample, err = %d, skipping...\n", err); |
990 | continue; | 990 | goto next_event; |
991 | } | 991 | } |
992 | 992 | ||
993 | if (trace->base_time == 0) | 993 | if (trace->base_time == 0) |
@@ -1001,18 +1001,20 @@ again: | |||
1001 | evsel = perf_evlist__id2evsel(evlist, sample.id); | 1001 | evsel = perf_evlist__id2evsel(evlist, sample.id); |
1002 | if (evsel == NULL) { | 1002 | if (evsel == NULL) { |
1003 | fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); | 1003 | fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id); |
1004 | continue; | 1004 | goto next_event; |
1005 | } | 1005 | } |
1006 | 1006 | ||
1007 | if (sample.raw_data == NULL) { | 1007 | if (sample.raw_data == NULL) { |
1008 | fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", | 1008 | fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", |
1009 | perf_evsel__name(evsel), sample.tid, | 1009 | perf_evsel__name(evsel), sample.tid, |
1010 | sample.cpu, sample.raw_size); | 1010 | sample.cpu, sample.raw_size); |
1011 | continue; | 1011 | goto next_event; |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | handler = evsel->handler.func; | 1014 | handler = evsel->handler.func; |
1015 | handler(trace, evsel, &sample); | 1015 | handler(trace, evsel, &sample); |
1016 | next_event: | ||
1017 | perf_evlist__mmap_consume(evlist, i); | ||
1016 | 1018 | ||
1017 | if (done) | 1019 | if (done) |
1018 | goto out_unmap_evlist; | 1020 | goto out_unmap_evlist; |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6fb781d5586c..e3fedfa2906e 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -290,6 +290,7 @@ static int process_events(struct machine *machine, struct perf_evlist *evlist, | |||
290 | for (i = 0; i < evlist->nr_mmaps; i++) { | 290 | for (i = 0; i < evlist->nr_mmaps; i++) { |
291 | while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { | 291 | while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { |
292 | ret = process_event(machine, evlist, event, state); | 292 | ret = process_event(machine, evlist, event, state); |
293 | perf_evlist__mmap_consume(evlist, i); | ||
293 | if (ret < 0) | 294 | if (ret < 0) |
294 | return ret; | 295 | return ret; |
295 | } | 296 | } |
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index d444ea2c47d9..376c35608534 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c | |||
@@ -36,6 +36,7 @@ static int find_comm(struct perf_evlist *evlist, const char *comm) | |||
36 | (pid_t)event->comm.tid == getpid() && | 36 | (pid_t)event->comm.tid == getpid() && |
37 | strcmp(event->comm.comm, comm) == 0) | 37 | strcmp(event->comm.comm, comm) == 0) |
38 | found += 1; | 38 | found += 1; |
39 | perf_evlist__mmap_consume(evlist, i); | ||
39 | } | 40 | } |
40 | } | 41 | } |
41 | return found; | 42 | return found; |
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index c4185b9aeb80..a7232c204eb9 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c | |||
@@ -122,6 +122,7 @@ int test__basic_mmap(void) | |||
122 | goto out_munmap; | 122 | goto out_munmap; |
123 | } | 123 | } |
124 | nr_events[evsel->idx]++; | 124 | nr_events[evsel->idx]++; |
125 | perf_evlist__mmap_consume(evlist, 0); | ||
125 | } | 126 | } |
126 | 127 | ||
127 | err = 0; | 128 | err = 0; |
diff --git a/tools/perf/tests/open-syscall-tp-fields.c b/tools/perf/tests/open-syscall-tp-fields.c index fc5b9fca8b47..524b221b829b 100644 --- a/tools/perf/tests/open-syscall-tp-fields.c +++ b/tools/perf/tests/open-syscall-tp-fields.c | |||
@@ -77,8 +77,10 @@ int test__syscall_open_tp_fields(void) | |||
77 | 77 | ||
78 | ++nr_events; | 78 | ++nr_events; |
79 | 79 | ||
80 | if (type != PERF_RECORD_SAMPLE) | 80 | if (type != PERF_RECORD_SAMPLE) { |
81 | perf_evlist__mmap_consume(evlist, i); | ||
81 | continue; | 82 | continue; |
83 | } | ||
82 | 84 | ||
83 | err = perf_evsel__parse_sample(evsel, event, &sample); | 85 | err = perf_evsel__parse_sample(evsel, event, &sample); |
84 | if (err) { | 86 | if (err) { |
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index b8a7056519ac..7923b06ffc91 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c | |||
@@ -263,6 +263,8 @@ int test__PERF_RECORD(void) | |||
263 | type); | 263 | type); |
264 | ++errs; | 264 | ++errs; |
265 | } | 265 | } |
266 | |||
267 | perf_evlist__mmap_consume(evlist, i); | ||
266 | } | 268 | } |
267 | } | 269 | } |
268 | 270 | ||
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c index 0ab61b1f408e..4ca1b938f6a6 100644 --- a/tools/perf/tests/perf-time-to-tsc.c +++ b/tools/perf/tests/perf-time-to-tsc.c | |||
@@ -122,7 +122,7 @@ int test__perf_time_to_tsc(void) | |||
122 | if (event->header.type != PERF_RECORD_COMM || | 122 | if (event->header.type != PERF_RECORD_COMM || |
123 | (pid_t)event->comm.pid != getpid() || | 123 | (pid_t)event->comm.pid != getpid() || |
124 | (pid_t)event->comm.tid != getpid()) | 124 | (pid_t)event->comm.tid != getpid()) |
125 | continue; | 125 | goto next_event; |
126 | 126 | ||
127 | if (strcmp(event->comm.comm, comm1) == 0) { | 127 | if (strcmp(event->comm.comm, comm1) == 0) { |
128 | CHECK__(perf_evsel__parse_sample(evsel, event, | 128 | CHECK__(perf_evsel__parse_sample(evsel, event, |
@@ -134,6 +134,8 @@ int test__perf_time_to_tsc(void) | |||
134 | &sample)); | 134 | &sample)); |
135 | comm2_time = sample.time; | 135 | comm2_time = sample.time; |
136 | } | 136 | } |
137 | next_event: | ||
138 | perf_evlist__mmap_consume(evlist, i); | ||
137 | } | 139 | } |
138 | } | 140 | } |
139 | 141 | ||
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c index 2e41e2d32ccc..6e2b44ec0749 100644 --- a/tools/perf/tests/sw-clock.c +++ b/tools/perf/tests/sw-clock.c | |||
@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
78 | struct perf_sample sample; | 78 | struct perf_sample sample; |
79 | 79 | ||
80 | if (event->header.type != PERF_RECORD_SAMPLE) | 80 | if (event->header.type != PERF_RECORD_SAMPLE) |
81 | continue; | 81 | goto next_event; |
82 | 82 | ||
83 | err = perf_evlist__parse_sample(evlist, event, &sample); | 83 | err = perf_evlist__parse_sample(evlist, event, &sample); |
84 | if (err < 0) { | 84 | if (err < 0) { |
@@ -88,6 +88,8 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id) | |||
88 | 88 | ||
89 | total_periods += sample.period; | 89 | total_periods += sample.period; |
90 | nr_samples++; | 90 | nr_samples++; |
91 | next_event: | ||
92 | perf_evlist__mmap_consume(evlist, 0); | ||
91 | } | 93 | } |
92 | 94 | ||
93 | if ((u64) nr_samples == total_periods) { | 95 | if ((u64) nr_samples == total_periods) { |
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c index 28fe5894b061..a3e64876e940 100644 --- a/tools/perf/tests/task-exit.c +++ b/tools/perf/tests/task-exit.c | |||
@@ -96,10 +96,10 @@ int test__task_exit(void) | |||
96 | 96 | ||
97 | retry: | 97 | retry: |
98 | while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { | 98 | while ((event = perf_evlist__mmap_read(evlist, 0)) != NULL) { |
99 | if (event->header.type != PERF_RECORD_EXIT) | 99 | if (event->header.type == PERF_RECORD_EXIT) |
100 | continue; | 100 | nr_exit++; |
101 | 101 | ||
102 | nr_exit++; | 102 | perf_evlist__mmap_consume(evlist, 0); |
103 | } | 103 | } |
104 | 104 | ||
105 | if (!exited || !nr_exit) { | 105 | if (!exited || !nr_exit) { |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 194e2f42ff5d..6c152686e837 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -315,8 +315,7 @@ static inline void advance_hpp(struct perf_hpp *hpp, int inc) | |||
315 | } | 315 | } |
316 | 316 | ||
317 | static int hist_entry__period_snprintf(struct perf_hpp *hpp, | 317 | static int hist_entry__period_snprintf(struct perf_hpp *hpp, |
318 | struct hist_entry *he, | 318 | struct hist_entry *he) |
319 | bool color) | ||
320 | { | 319 | { |
321 | const char *sep = symbol_conf.field_sep; | 320 | const char *sep = symbol_conf.field_sep; |
322 | struct perf_hpp_fmt *fmt; | 321 | struct perf_hpp_fmt *fmt; |
@@ -338,7 +337,7 @@ static int hist_entry__period_snprintf(struct perf_hpp *hpp, | |||
338 | } else | 337 | } else |
339 | first = false; | 338 | first = false; |
340 | 339 | ||
341 | if (color && fmt->color) | 340 | if (perf_hpp__use_color() && fmt->color) |
342 | ret = fmt->color(fmt, hpp, he); | 341 | ret = fmt->color(fmt, hpp, he); |
343 | else | 342 | else |
344 | ret = fmt->entry(fmt, hpp, he); | 343 | ret = fmt->entry(fmt, hpp, he); |
@@ -358,12 +357,11 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, | |||
358 | .buf = bf, | 357 | .buf = bf, |
359 | .size = size, | 358 | .size = size, |
360 | }; | 359 | }; |
361 | bool color = !symbol_conf.field_sep; | ||
362 | 360 | ||
363 | if (size == 0 || size > bfsz) | 361 | if (size == 0 || size > bfsz) |
364 | size = hpp.size = bfsz; | 362 | size = hpp.size = bfsz; |
365 | 363 | ||
366 | ret = hist_entry__period_snprintf(&hpp, he, color); | 364 | ret = hist_entry__period_snprintf(&hpp, he); |
367 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); | 365 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); |
368 | 366 | ||
369 | ret = fprintf(fp, "%s\n", bf); | 367 | ret = fprintf(fp, "%s\n", bf); |
@@ -482,6 +480,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
482 | 480 | ||
483 | print_entries: | 481 | print_entries: |
484 | linesz = hists__sort_list_width(hists) + 3 + 1; | 482 | linesz = hists__sort_list_width(hists) + 3 + 1; |
483 | linesz += perf_hpp__color_overhead(); | ||
485 | line = malloc(linesz); | 484 | line = malloc(linesz); |
486 | if (line == NULL) { | 485 | if (line == NULL) { |
487 | ret = -1; | 486 | ret = -1; |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 2b585bc308cf..9e99060408ae 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -147,6 +147,9 @@ static inline void callchain_cursor_advance(struct callchain_cursor *cursor) | |||
147 | 147 | ||
148 | struct option; | 148 | struct option; |
149 | 149 | ||
150 | int record_parse_callchain(const char *arg, struct perf_record_opts *opts); | ||
150 | int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); | 151 | int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); |
152 | int record_callchain_opt(const struct option *opt, const char *arg, int unset); | ||
153 | |||
151 | extern const char record_callchain_help[]; | 154 | extern const char record_callchain_help[]; |
152 | #endif /* __PERF_CALLCHAIN_H */ | 155 | #endif /* __PERF_CALLCHAIN_H */ |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index f9f77bee0b1b..e584cd30b0f2 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -545,12 +545,19 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) | |||
545 | 545 | ||
546 | md->prev = old; | 546 | md->prev = old; |
547 | 547 | ||
548 | if (!evlist->overwrite) | ||
549 | perf_mmap__write_tail(md, old); | ||
550 | |||
551 | return event; | 548 | return event; |
552 | } | 549 | } |
553 | 550 | ||
551 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) | ||
552 | { | ||
553 | if (!evlist->overwrite) { | ||
554 | struct perf_mmap *md = &evlist->mmap[idx]; | ||
555 | unsigned int old = md->prev; | ||
556 | |||
557 | perf_mmap__write_tail(md, old); | ||
558 | } | ||
559 | } | ||
560 | |||
554 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) | 561 | static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) |
555 | { | 562 | { |
556 | if (evlist->mmap[idx].base != NULL) { | 563 | if (evlist->mmap[idx].base != NULL) { |
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 880d7139d2fb..206d09339306 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h | |||
@@ -89,6 +89,8 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); | |||
89 | 89 | ||
90 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); | 90 | union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); |
91 | 91 | ||
92 | void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); | ||
93 | |||
92 | int perf_evlist__open(struct perf_evlist *evlist); | 94 | int perf_evlist__open(struct perf_evlist *evlist); |
93 | void perf_evlist__close(struct perf_evlist *evlist); | 95 | void perf_evlist__close(struct perf_evlist *evlist); |
94 | 96 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1329b6b6ffe6..ce8dc61ce2c3 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <pthread.h> | 5 | #include <pthread.h> |
6 | #include "callchain.h" | 6 | #include "callchain.h" |
7 | #include "header.h" | 7 | #include "header.h" |
8 | #include "color.h" | ||
8 | 9 | ||
9 | extern struct callchain_param callchain_param; | 10 | extern struct callchain_param callchain_param; |
10 | 11 | ||
@@ -175,6 +176,18 @@ void perf_hpp__init(void); | |||
175 | void perf_hpp__column_register(struct perf_hpp_fmt *format); | 176 | void perf_hpp__column_register(struct perf_hpp_fmt *format); |
176 | void perf_hpp__column_enable(unsigned col); | 177 | void perf_hpp__column_enable(unsigned col); |
177 | 178 | ||
179 | static inline size_t perf_hpp__use_color(void) | ||
180 | { | ||
181 | return !symbol_conf.field_sep; | ||
182 | } | ||
183 | |||
184 | static inline size_t perf_hpp__color_overhead(void) | ||
185 | { | ||
186 | return perf_hpp__use_color() ? | ||
187 | (COLOR_MAXLEN + sizeof(PERF_COLOR_RESET)) * PERF_HPP__MAX_INDEX | ||
188 | : 0; | ||
189 | } | ||
190 | |||
178 | struct perf_evlist; | 191 | struct perf_evlist; |
179 | 192 | ||
180 | struct hist_browser_timer { | 193 | struct hist_browser_timer { |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 71b5412bbbb9..2ac4bc92bb1f 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -822,6 +822,8 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, | |||
822 | PyObject *pyevent = pyrf_event__new(event); | 822 | PyObject *pyevent = pyrf_event__new(event); |
823 | struct pyrf_event *pevent = (struct pyrf_event *)pyevent; | 823 | struct pyrf_event *pevent = (struct pyrf_event *)pyevent; |
824 | 824 | ||
825 | perf_evlist__mmap_consume(evlist, cpu); | ||
826 | |||
825 | if (pyevent == NULL) | 827 | if (pyevent == NULL) |
826 | return PyErr_NoMemory(); | 828 | return PyErr_NoMemory(); |
827 | 829 | ||