diff options
-rw-r--r-- | tools/perf/Documentation/perf-top.txt | 5 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 26 | ||||
-rw-r--r-- | tools/perf/util/callchain.c | 40 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 1 |
4 files changed, 62 insertions, 10 deletions
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index f6a23eb294e7..556cec09bf50 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -160,9 +160,10 @@ Default is to monitor all CPUS. | |||
160 | -g:: | 160 | -g:: |
161 | Enables call-graph (stack chain/backtrace) recording. | 161 | Enables call-graph (stack chain/backtrace) recording. |
162 | 162 | ||
163 | --call-graph:: | 163 | --call-graph [mode,type,min[,limit],order[,key][,branch]]:: |
164 | Setup and enable call-graph (stack chain/backtrace) recording, | 164 | Setup and enable call-graph (stack chain/backtrace) recording, |
165 | implies -g. | 165 | implies -g. See `--call-graph` section in perf-record and |
166 | perf-report man pages for details. | ||
166 | 167 | ||
167 | --children:: | 168 | --children:: |
168 | Accumulate callchain of children to parent entry so that then can | 169 | Accumulate callchain of children to parent entry so that then can |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 6f641fd68296..1de381d3f29f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -1053,8 +1053,22 @@ callchain_opt(const struct option *opt, const char *arg, int unset) | |||
1053 | static int | 1053 | static int |
1054 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) | 1054 | parse_callchain_opt(const struct option *opt, const char *arg, int unset) |
1055 | { | 1055 | { |
1056 | symbol_conf.use_callchain = true; | 1056 | struct record_opts *record = (struct record_opts *)opt->value; |
1057 | return record_parse_callchain_opt(opt, arg, unset); | 1057 | |
1058 | record->callgraph_set = true; | ||
1059 | callchain_param.enabled = !unset; | ||
1060 | callchain_param.record_mode = CALLCHAIN_FP; | ||
1061 | |||
1062 | /* | ||
1063 | * --no-call-graph | ||
1064 | */ | ||
1065 | if (unset) { | ||
1066 | symbol_conf.use_callchain = false; | ||
1067 | callchain_param.record_mode = CALLCHAIN_NONE; | ||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | return parse_callchain_top_opt(arg); | ||
1058 | } | 1072 | } |
1059 | 1073 | ||
1060 | static int perf_top_config(const char *var, const char *value, void *cb) | 1074 | static int perf_top_config(const char *var, const char *value, void *cb) |
@@ -1079,6 +1093,8 @@ parse_percent_limit(const struct option *opt, const char *arg, | |||
1079 | return 0; | 1093 | return 0; |
1080 | } | 1094 | } |
1081 | 1095 | ||
1096 | const char top_callchain_help[] = CALLCHAIN_RECORD_HELP ", " CALLCHAIN_REPORT_HELP; | ||
1097 | |||
1082 | int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | 1098 | int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) |
1083 | { | 1099 | { |
1084 | char errbuf[BUFSIZ]; | 1100 | char errbuf[BUFSIZ]; |
@@ -1154,11 +1170,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1154 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, | 1170 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, |
1155 | "Show a column with the number of samples"), | 1171 | "Show a column with the number of samples"), |
1156 | OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, | 1172 | OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, |
1157 | NULL, "enables call-graph recording", | 1173 | NULL, "enables call-graph recording and display", |
1158 | &callchain_opt), | 1174 | &callchain_opt), |
1159 | OPT_CALLBACK(0, "call-graph", &top.record_opts, | 1175 | OPT_CALLBACK(0, "call-graph", &top.record_opts, |
1160 | "mode[,dump_size]", record_callchain_help, | 1176 | "mode[,dump_size],output_type,min_percent[,print_limit],call_order[,branch]", |
1161 | &parse_callchain_opt), | 1177 | top_callchain_help, &parse_callchain_opt), |
1162 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, | 1178 | OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, |
1163 | "Accumulate callchains of children and show total overhead as well"), | 1179 | "Accumulate callchains of children and show total overhead as well"), |
1164 | OPT_INTEGER(0, "max-stack", &top.max_stack, | 1180 | OPT_INTEGER(0, "max-stack", &top.max_stack, |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 773fe13ce627..842be32899ee 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -77,12 +77,14 @@ static int parse_callchain_sort_key(const char *value) | |||
77 | return -1; | 77 | return -1; |
78 | } | 78 | } |
79 | 79 | ||
80 | int | 80 | static int |
81 | parse_callchain_report_opt(const char *arg) | 81 | __parse_callchain_report_opt(const char *arg, bool allow_record_opt) |
82 | { | 82 | { |
83 | char *tok; | 83 | char *tok; |
84 | char *endptr; | 84 | char *endptr; |
85 | bool minpcnt_set = false; | 85 | bool minpcnt_set = false; |
86 | bool record_opt_set = false; | ||
87 | bool try_stack_size = false; | ||
86 | 88 | ||
87 | symbol_conf.use_callchain = true; | 89 | symbol_conf.use_callchain = true; |
88 | 90 | ||
@@ -100,6 +102,28 @@ parse_callchain_report_opt(const char *arg) | |||
100 | !parse_callchain_order(tok) || | 102 | !parse_callchain_order(tok) || |
101 | !parse_callchain_sort_key(tok)) { | 103 | !parse_callchain_sort_key(tok)) { |
102 | /* parsing ok - move on to the next */ | 104 | /* parsing ok - move on to the next */ |
105 | try_stack_size = false; | ||
106 | goto next; | ||
107 | } else if (allow_record_opt && !record_opt_set) { | ||
108 | if (parse_callchain_record(tok, &callchain_param)) | ||
109 | goto try_numbers; | ||
110 | |||
111 | /* assume that number followed by 'dwarf' is stack size */ | ||
112 | if (callchain_param.record_mode == CALLCHAIN_DWARF) | ||
113 | try_stack_size = true; | ||
114 | |||
115 | record_opt_set = true; | ||
116 | goto next; | ||
117 | } | ||
118 | |||
119 | try_numbers: | ||
120 | if (try_stack_size) { | ||
121 | unsigned long size = 0; | ||
122 | |||
123 | if (get_stack_size(tok, &size) < 0) | ||
124 | return -1; | ||
125 | callchain_param.dump_size = size; | ||
126 | try_stack_size = false; | ||
103 | } else if (!minpcnt_set) { | 127 | } else if (!minpcnt_set) { |
104 | /* try to get the min percent */ | 128 | /* try to get the min percent */ |
105 | callchain_param.min_percent = strtod(tok, &endptr); | 129 | callchain_param.min_percent = strtod(tok, &endptr); |
@@ -112,7 +136,7 @@ parse_callchain_report_opt(const char *arg) | |||
112 | if (tok == endptr) | 136 | if (tok == endptr) |
113 | return -1; | 137 | return -1; |
114 | } | 138 | } |
115 | 139 | next: | |
116 | arg = NULL; | 140 | arg = NULL; |
117 | } | 141 | } |
118 | 142 | ||
@@ -123,6 +147,16 @@ parse_callchain_report_opt(const char *arg) | |||
123 | return 0; | 147 | return 0; |
124 | } | 148 | } |
125 | 149 | ||
150 | int parse_callchain_report_opt(const char *arg) | ||
151 | { | ||
152 | return __parse_callchain_report_opt(arg, false); | ||
153 | } | ||
154 | |||
155 | int parse_callchain_top_opt(const char *arg) | ||
156 | { | ||
157 | return __parse_callchain_report_opt(arg, true); | ||
158 | } | ||
159 | |||
126 | int perf_callchain_config(const char *var, const char *value) | 160 | int perf_callchain_config(const char *var, const char *value) |
127 | { | 161 | { |
128 | char *endptr; | 162 | char *endptr; |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index c9e3a2e85a72..836d59a001bc 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -192,6 +192,7 @@ extern const char record_callchain_help[]; | |||
192 | extern int parse_callchain_record(const char *arg, struct callchain_param *param); | 192 | extern int parse_callchain_record(const char *arg, struct callchain_param *param); |
193 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); | 193 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); |
194 | int parse_callchain_report_opt(const char *arg); | 194 | int parse_callchain_report_opt(const char *arg); |
195 | int parse_callchain_top_opt(const char *arg); | ||
195 | int perf_callchain_config(const char *var, const char *value); | 196 | int perf_callchain_config(const char *var, const char *value); |
196 | 197 | ||
197 | static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, | 198 | static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, |