aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-12-11 14:48:41 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-12-11 15:22:39 -0500
commit2376c67a7bbc7849b806688ba2efb8520c21c458 (patch)
tree03d6f5612b7822d6a85e9251aa3eab931237d6ba /tools/perf/builtin-top.c
parent75d9a10854db6aab2400cd6a844c392107be4c64 (diff)
perf top: Use perf_evlist__config()
Using struct perf_record_opts to specify how to configure the evsel perf_event_attrs. This gets top closer to record in the way it sets up evsels, with the aim of sharing more and more to the point that both will be a single utility. In this direction top now uses the same callchain option parsing as record and that brings DWARF callchains to top, something that was already available for record. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-u03o0bsrqcjgskciso3pvsjr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c204
1 files changed, 65 insertions, 139 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index a30647487ba3..b7d2ea62dbc6 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -596,7 +596,7 @@ static void *display_thread_tui(void *arg)
596 * via --uid. 596 * via --uid.
597 */ 597 */
598 list_for_each_entry(pos, &top->evlist->entries, node) 598 list_for_each_entry(pos, &top->evlist->entries, node)
599 pos->hists.uid_filter_str = top->target.uid_str; 599 pos->hists.uid_filter_str = top->record_opts.target.uid_str;
600 600
601 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, 601 perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
602 &top->session->header.env); 602 &top->session->header.env);
@@ -894,34 +894,13 @@ static void perf_top__start_counters(struct perf_top *top)
894{ 894{
895 struct perf_evsel *counter; 895 struct perf_evsel *counter;
896 struct perf_evlist *evlist = top->evlist; 896 struct perf_evlist *evlist = top->evlist;
897 struct perf_record_opts *opts = &top->record_opts;
897 898
898 if (top->group) 899 perf_evlist__config(evlist, opts);
899 perf_evlist__set_leader(evlist);
900 900
901 list_for_each_entry(counter, &evlist->entries, node) { 901 list_for_each_entry(counter, &evlist->entries, node) {
902 struct perf_event_attr *attr = &counter->attr; 902 struct perf_event_attr *attr = &counter->attr;
903 903
904 perf_evsel__set_sample_bit(counter, IP);
905 perf_evsel__set_sample_bit(counter, TID);
906
907 if (top->freq) {
908 perf_evsel__set_sample_bit(counter, PERIOD);
909 attr->freq = 1;
910 attr->sample_freq = top->freq;
911 }
912
913 if (evlist->nr_entries > 1)
914 perf_evsel__set_sample_id(counter);
915
916 if (perf_target__has_cpu(&top->target))
917 perf_evsel__set_sample_bit(counter, CPU);
918
919 if (symbol_conf.use_callchain)
920 perf_evsel__set_sample_bit(counter, CALLCHAIN);
921
922 attr->mmap = 1;
923 attr->comm = 1;
924 attr->inherit = top->inherit;
925fallback_missing_features: 904fallback_missing_features:
926 if (top->exclude_guest_missing) 905 if (top->exclude_guest_missing)
927 attr->exclude_guest = attr->exclude_host = 0; 906 attr->exclude_guest = attr->exclude_host = 0;
@@ -995,7 +974,7 @@ try_again:
995 } 974 }
996 } 975 }
997 976
998 if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) { 977 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
999 ui__error("Failed to mmap with %d (%s)\n", 978 ui__error("Failed to mmap with %d (%s)\n",
1000 errno, strerror(errno)); 979 errno, strerror(errno));
1001 goto out_err; 980 goto out_err;
@@ -1015,7 +994,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
1015 ui__error("Selected -g but \"sym\" not present in --sort/-s."); 994 ui__error("Selected -g but \"sym\" not present in --sort/-s.");
1016 return -EINVAL; 995 return -EINVAL;
1017 } 996 }
1018 } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) { 997 } else if (callchain_param.mode != CHAIN_NONE) {
1019 if (callchain_register_param(&callchain_param) < 0) { 998 if (callchain_register_param(&callchain_param) < 0) {
1020 ui__error("Can't register callchain params.\n"); 999 ui__error("Can't register callchain params.\n");
1021 return -EINVAL; 1000 return -EINVAL;
@@ -1027,6 +1006,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
1027 1006
1028static int __cmd_top(struct perf_top *top) 1007static int __cmd_top(struct perf_top *top)
1029{ 1008{
1009 struct perf_record_opts *opts = &top->record_opts;
1030 pthread_t thread; 1010 pthread_t thread;
1031 int ret; 1011 int ret;
1032 /* 1012 /*
@@ -1041,7 +1021,7 @@ static int __cmd_top(struct perf_top *top)
1041 if (ret) 1021 if (ret)
1042 goto out_delete; 1022 goto out_delete;
1043 1023
1044 if (perf_target__has_task(&top->target)) 1024 if (perf_target__has_task(&opts->target))
1045 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 1025 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
1046 perf_event__process, 1026 perf_event__process,
1047 &top->session->host_machine); 1027 &top->session->host_machine);
@@ -1052,6 +1032,17 @@ static int __cmd_top(struct perf_top *top)
1052 top->session->evlist = top->evlist; 1032 top->session->evlist = top->evlist;
1053 perf_session__set_id_hdr_size(top->session); 1033 perf_session__set_id_hdr_size(top->session);
1054 1034
1035 /*
1036 * When perf is starting the traced process, all the events (apart from
1037 * group members) have enable_on_exec=1 set, so don't spoil it by
1038 * prematurely enabling them.
1039 *
1040 * XXX 'top' still doesn't start workloads like record, trace, but should,
1041 * so leave the check here.
1042 */
1043 if (!perf_target__none(&opts->target))
1044 perf_evlist__enable(top->evlist);
1045
1055 /* Wait for a minimal set of events before starting the snapshot */ 1046 /* Wait for a minimal set of events before starting the snapshot */
1056 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 1047 poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
1057 1048
@@ -1092,116 +1083,56 @@ out_delete:
1092static int 1083static int
1093parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1084parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1094{ 1085{
1095 struct perf_top *top = (struct perf_top *)opt->value;
1096 char *tok, *tok2;
1097 char *endptr;
1098
1099 /* 1086 /*
1100 * --no-call-graph 1087 * --no-call-graph
1101 */ 1088 */
1102 if (unset) { 1089 if (unset)
1103 top->dont_use_callchains = true;
1104 return 0; 1090 return 0;
1105 }
1106 1091
1107 symbol_conf.use_callchain = true; 1092 symbol_conf.use_callchain = true;
1108 1093
1109 if (!arg) 1094 return record_parse_callchain_opt(opt, arg, unset);
1110 return 0;
1111
1112 tok = strtok((char *)arg, ",");
1113 if (!tok)
1114 return -1;
1115
1116 /* get the output mode */
1117 if (!strncmp(tok, "graph", strlen(arg)))
1118 callchain_param.mode = CHAIN_GRAPH_ABS;
1119
1120 else if (!strncmp(tok, "flat", strlen(arg)))
1121 callchain_param.mode = CHAIN_FLAT;
1122
1123 else if (!strncmp(tok, "fractal", strlen(arg)))
1124 callchain_param.mode = CHAIN_GRAPH_REL;
1125
1126 else if (!strncmp(tok, "none", strlen(arg))) {
1127 callchain_param.mode = CHAIN_NONE;
1128 symbol_conf.use_callchain = false;
1129
1130 return 0;
1131 } else
1132 return -1;
1133
1134 /* get the min percentage */
1135 tok = strtok(NULL, ",");
1136 if (!tok)
1137 goto setup;
1138
1139 callchain_param.min_percent = strtod(tok, &endptr);
1140 if (tok == endptr)
1141 return -1;
1142
1143 /* get the print limit */
1144 tok2 = strtok(NULL, ",");
1145 if (!tok2)
1146 goto setup;
1147
1148 if (tok2[0] != 'c') {
1149 callchain_param.print_limit = strtod(tok2, &endptr);
1150 tok2 = strtok(NULL, ",");
1151 if (!tok2)
1152 goto setup;
1153 }
1154
1155 /* get the call chain order */
1156 if (!strcmp(tok2, "caller"))
1157 callchain_param.order = ORDER_CALLER;
1158 else if (!strcmp(tok2, "callee"))
1159 callchain_param.order = ORDER_CALLEE;
1160 else
1161 return -1;
1162setup:
1163 if (callchain_register_param(&callchain_param) < 0) {
1164 fprintf(stderr, "Can't register callchain params\n");
1165 return -1;
1166 }
1167 return 0;
1168} 1095}
1169 1096
1170int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1097int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1171{ 1098{
1172 struct perf_evsel *pos;
1173 int status; 1099 int status;
1174 char errbuf[BUFSIZ]; 1100 char errbuf[BUFSIZ];
1175 struct perf_top top = { 1101 struct perf_top top = {
1176 .count_filter = 5, 1102 .count_filter = 5,
1177 .delay_secs = 2, 1103 .delay_secs = 2,
1178 .freq = 4000, /* 4 KHz */ 1104 .record_opts = {
1179 .mmap_pages = 128, 1105 .mmap_pages = UINT_MAX,
1180 .sym_pcnt_filter = 5, 1106 .user_freq = UINT_MAX,
1181 .target = { 1107 .user_interval = ULLONG_MAX,
1182 .uses_mmap = true, 1108 .freq = 4000, /* 4 KHz */
1109 .target = {
1110 .uses_mmap = true,
1111 },
1183 }, 1112 },
1113 .sym_pcnt_filter = 5,
1184 }; 1114 };
1185 char callchain_default_opt[] = "fractal,0.5,callee"; 1115 struct perf_record_opts *opts = &top.record_opts;
1116 struct perf_target *target = &opts->target;
1186 const struct option options[] = { 1117 const struct option options[] = {
1187 OPT_CALLBACK('e', "event", &top.evlist, "event", 1118 OPT_CALLBACK('e', "event", &top.evlist, "event",
1188 "event selector. use 'perf list' to list available events", 1119 "event selector. use 'perf list' to list available events",
1189 parse_events_option), 1120 parse_events_option),
1190 OPT_INTEGER('c', "count", &top.default_interval, 1121 OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
1191 "event period to sample"), 1122 OPT_STRING('p', "pid", &target->pid, "pid",
1192 OPT_STRING('p', "pid", &top.target.pid, "pid",
1193 "profile events on existing process id"), 1123 "profile events on existing process id"),
1194 OPT_STRING('t', "tid", &top.target.tid, "tid", 1124 OPT_STRING('t', "tid", &target->tid, "tid",
1195 "profile events on existing thread id"), 1125 "profile events on existing thread id"),
1196 OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide, 1126 OPT_BOOLEAN('a', "all-cpus", &target->system_wide,
1197 "system-wide collection from all CPUs"), 1127 "system-wide collection from all CPUs"),
1198 OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu", 1128 OPT_STRING('C', "cpu", &target->cpu_list, "cpu",
1199 "list of cpus to monitor"), 1129 "list of cpus to monitor"),
1200 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1130 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1201 "file", "vmlinux pathname"), 1131 "file", "vmlinux pathname"),
1202 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1132 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1203 "hide kernel symbols"), 1133 "hide kernel symbols"),
1204 OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"), 1134 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages,
1135 "number of mmap data pages"),
1205 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1136 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1206 "collect data with this RT SCHED_FIFO priority"), 1137 "collect data with this RT SCHED_FIFO priority"),
1207 OPT_INTEGER('d', "delay", &top.delay_secs, 1138 OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1210,16 +1141,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1210 "dump the symbol table used for profiling"), 1141 "dump the symbol table used for profiling"),
1211 OPT_INTEGER('f', "count-filter", &top.count_filter, 1142 OPT_INTEGER('f', "count-filter", &top.count_filter,
1212 "only display functions with more events than this"), 1143 "only display functions with more events than this"),
1213 OPT_BOOLEAN('g', "group", &top.group, 1144 OPT_BOOLEAN('g', "group", &opts->group,
1214 "put the counters into a counter group"), 1145 "put the counters into a counter group"),
1215 OPT_BOOLEAN('i', "inherit", &top.inherit, 1146 OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
1216 "child tasks inherit counters"), 1147 "child tasks do not inherit counters"),
1217 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", 1148 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1218 "symbol to annotate"), 1149 "symbol to annotate"),
1219 OPT_BOOLEAN('z', "zero", &top.zero, 1150 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
1220 "zero history across updates"), 1151 OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"),
1221 OPT_INTEGER('F', "freq", &top.freq,
1222 "profile at this frequency"),
1223 OPT_INTEGER('E', "entries", &top.print_entries, 1152 OPT_INTEGER('E', "entries", &top.print_entries,
1224 "display this many functions"), 1153 "display this many functions"),
1225 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1154 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1232,10 +1161,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1232 "sort by key(s): pid, comm, dso, symbol, parent"), 1161 "sort by key(s): pid, comm, dso, symbol, parent"),
1233 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1162 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1234 "Show a column with the number of samples"), 1163 "Show a column with the number of samples"),
1235 OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order", 1164 OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
1236 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. " 1165 "mode[,dump_size]", record_callchain_help,
1237 "Default: fractal,0.5,callee", &parse_callchain_opt, 1166 &parse_callchain_opt, "fp"),
1238 callchain_default_opt),
1239 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1167 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1240 "Show a column with the sum of periods"), 1168 "Show a column with the sum of periods"),
1241 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 1169 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -1250,7 +1178,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1250 "Display raw encoding of assembly instructions (default)"), 1178 "Display raw encoding of assembly instructions (default)"),
1251 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1179 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1252 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1180 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1253 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"), 1181 OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
1254 OPT_END() 1182 OPT_END()
1255 }; 1183 };
1256 const char * const top_usage[] = { 1184 const char * const top_usage[] = {
@@ -1280,27 +1208,27 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1280 1208
1281 setup_browser(false); 1209 setup_browser(false);
1282 1210
1283 status = perf_target__validate(&top.target); 1211 status = perf_target__validate(target);
1284 if (status) { 1212 if (status) {
1285 perf_target__strerror(&top.target, status, errbuf, BUFSIZ); 1213 perf_target__strerror(target, status, errbuf, BUFSIZ);
1286 ui__warning("%s", errbuf); 1214 ui__warning("%s", errbuf);
1287 } 1215 }
1288 1216
1289 status = perf_target__parse_uid(&top.target); 1217 status = perf_target__parse_uid(target);
1290 if (status) { 1218 if (status) {
1291 int saved_errno = errno; 1219 int saved_errno = errno;
1292 1220
1293 perf_target__strerror(&top.target, status, errbuf, BUFSIZ); 1221 perf_target__strerror(target, status, errbuf, BUFSIZ);
1294 ui__error("%s", errbuf); 1222 ui__error("%s", errbuf);
1295 1223
1296 status = -saved_errno; 1224 status = -saved_errno;
1297 goto out_delete_evlist; 1225 goto out_delete_evlist;
1298 } 1226 }
1299 1227
1300 if (perf_target__none(&top.target)) 1228 if (perf_target__none(target))
1301 top.target.system_wide = true; 1229 target->system_wide = true;
1302 1230
1303 if (perf_evlist__create_maps(top.evlist, &top.target) < 0) 1231 if (perf_evlist__create_maps(top.evlist, target) < 0)
1304 usage_with_options(top_usage, options); 1232 usage_with_options(top_usage, options);
1305 1233
1306 if (!top.evlist->nr_entries && 1234 if (!top.evlist->nr_entries &&
@@ -1314,24 +1242,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1314 if (top.delay_secs < 1) 1242 if (top.delay_secs < 1)
1315 top.delay_secs = 1; 1243 top.delay_secs = 1;
1316 1244
1245 if (opts->user_interval != ULLONG_MAX)
1246 opts->default_interval = opts->user_interval;
1247 if (opts->user_freq != UINT_MAX)
1248 opts->freq = opts->user_freq;
1249
1317 /* 1250 /*
1318 * User specified count overrides default frequency. 1251 * User specified count overrides default frequency.
1319 */ 1252 */
1320 if (top.default_interval) 1253 if (opts->default_interval)
1321 top.freq = 0; 1254 opts->freq = 0;
1322 else if (top.freq) { 1255 else if (opts->freq) {
1323 top.default_interval = top.freq; 1256 opts->default_interval = opts->freq;
1324 } else { 1257 } else {
1325 ui__error("frequency and count are zero, aborting\n"); 1258 ui__error("frequency and count are zero, aborting\n");
1326 exit(EXIT_FAILURE); 1259 status = -EINVAL;
1327 } 1260 goto out_delete_evlist;
1328
1329 list_for_each_entry(pos, &top.evlist->entries, node) {
1330 /*
1331 * Fill in the ones not specifically initialized via -c:
1332 */
1333 if (!pos->attr.sample_period)
1334 pos->attr.sample_period = top.default_interval;
1335 } 1261 }
1336 1262
1337 top.sym_evsel = perf_evlist__first(top.evlist); 1263 top.sym_evsel = perf_evlist__first(top.evlist);