aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c122
1 files changed, 58 insertions, 64 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 212214162bb2..71e6402729a8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -246,10 +246,10 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
246 struct hist_entry *he; 246 struct hist_entry *he;
247 247
248 pthread_mutex_lock(&evsel->hists.lock); 248 pthread_mutex_lock(&evsel->hists.lock);
249 he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, 249 he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL,
250 sample->weight); 250 sample->period, sample->weight,
251 sample->transaction);
251 pthread_mutex_unlock(&evsel->hists.lock); 252 pthread_mutex_unlock(&evsel->hists.lock);
252
253 if (he == NULL) 253 if (he == NULL)
254 return NULL; 254 return NULL;
255 255
@@ -287,7 +287,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
287 return; 287 return;
288 } 288 }
289 289
290 hists__collapse_resort(&top->sym_evsel->hists); 290 hists__collapse_resort(&top->sym_evsel->hists, NULL);
291 hists__output_resort(&top->sym_evsel->hists); 291 hists__output_resort(&top->sym_evsel->hists);
292 hists__decay_entries(&top->sym_evsel->hists, 292 hists__decay_entries(&top->sym_evsel->hists,
293 top->hide_user_symbols, 293 top->hide_user_symbols,
@@ -553,7 +553,7 @@ static void perf_top__sort_new_samples(void *arg)
553 if (t->evlist->selected != NULL) 553 if (t->evlist->selected != NULL)
554 t->sym_evsel = t->evlist->selected; 554 t->sym_evsel = t->evlist->selected;
555 555
556 hists__collapse_resort(&t->sym_evsel->hists); 556 hists__collapse_resort(&t->sym_evsel->hists, NULL);
557 hists__output_resort(&t->sym_evsel->hists); 557 hists__output_resort(&t->sym_evsel->hists);
558 hists__decay_entries(&t->sym_evsel->hists, 558 hists__decay_entries(&t->sym_evsel->hists,
559 t->hide_user_symbols, 559 t->hide_user_symbols,
@@ -771,7 +771,8 @@ static void perf_event__process_sample(struct perf_tool *tool,
771 sample->callchain) { 771 sample->callchain) {
772 err = machine__resolve_callchain(machine, evsel, 772 err = machine__resolve_callchain(machine, evsel,
773 al.thread, sample, 773 al.thread, sample,
774 &parent, &al); 774 &parent, &al,
775 top->max_stack);
775 if (err) 776 if (err)
776 return; 777 return;
777 } 778 }
@@ -810,7 +811,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
810 ret = perf_evlist__parse_sample(top->evlist, event, &sample); 811 ret = perf_evlist__parse_sample(top->evlist, event, &sample);
811 if (ret) { 812 if (ret) {
812 pr_err("Can't parse sample, err = %d\n", ret); 813 pr_err("Can't parse sample, err = %d\n", ret);
813 continue; 814 goto next_event;
814 } 815 }
815 816
816 evsel = perf_evlist__id2evsel(session->evlist, sample.id); 817 evsel = perf_evlist__id2evsel(session->evlist, sample.id);
@@ -825,13 +826,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
825 case PERF_RECORD_MISC_USER: 826 case PERF_RECORD_MISC_USER:
826 ++top->us_samples; 827 ++top->us_samples;
827 if (top->hide_user_symbols) 828 if (top->hide_user_symbols)
828 continue; 829 goto next_event;
829 machine = &session->machines.host; 830 machine = &session->machines.host;
830 break; 831 break;
831 case PERF_RECORD_MISC_KERNEL: 832 case PERF_RECORD_MISC_KERNEL:
832 ++top->kernel_samples; 833 ++top->kernel_samples;
833 if (top->hide_kernel_symbols) 834 if (top->hide_kernel_symbols)
834 continue; 835 goto next_event;
835 machine = &session->machines.host; 836 machine = &session->machines.host;
836 break; 837 break;
837 case PERF_RECORD_MISC_GUEST_KERNEL: 838 case PERF_RECORD_MISC_GUEST_KERNEL:
@@ -847,7 +848,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
847 */ 848 */
848 /* Fall thru */ 849 /* Fall thru */
849 default: 850 default:
850 continue; 851 goto next_event;
851 } 852 }
852 853
853 854
@@ -856,9 +857,11 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
856 &sample, machine); 857 &sample, machine);
857 } else if (event->header.type < PERF_RECORD_MAX) { 858 } else if (event->header.type < PERF_RECORD_MAX) {
858 hists__inc_nr_events(&evsel->hists, event->header.type); 859 hists__inc_nr_events(&evsel->hists, event->header.type);
859 machine__process_event(machine, event); 860 machine__process_event(machine, event, &sample);
860 } else 861 } else
861 ++session->stats.nr_unknown_events; 862 ++session->stats.nr_unknown_events;
863next_event:
864 perf_evlist__mmap_consume(top->evlist, idx);
862 } 865 }
863} 866}
864 867
@@ -930,11 +933,8 @@ static int __cmd_top(struct perf_top *top)
930 struct perf_record_opts *opts = &top->record_opts; 933 struct perf_record_opts *opts = &top->record_opts;
931 pthread_t thread; 934 pthread_t thread;
932 int ret; 935 int ret;
933 /* 936
934 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 937 top->session = perf_session__new(NULL, false, NULL);
935 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
936 */
937 top->session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
938 if (top->session == NULL) 938 if (top->session == NULL)
939 return -ENOMEM; 939 return -ENOMEM;
940 940
@@ -950,14 +950,8 @@ static int __cmd_top(struct perf_top *top)
950 if (ret) 950 if (ret)
951 goto out_delete; 951 goto out_delete;
952 952
953 if (perf_target__has_task(&opts->target)) 953 machine__synthesize_threads(&top->session->machines.host, &opts->target,
954 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 954 top->evlist->threads, false);
955 perf_event__process,
956 &top->session->machines.host);
957 else
958 perf_event__synthesize_threads(&top->tool, perf_event__process,
959 &top->session->machines.host);
960
961 ret = perf_top__start_counters(top); 955 ret = perf_top__start_counters(top);
962 if (ret) 956 if (ret)
963 goto out_delete; 957 goto out_delete;
@@ -973,7 +967,7 @@ static int __cmd_top(struct perf_top *top)
973 * XXX 'top' still doesn't start workloads like record, trace, but should, 967 * XXX 'top' still doesn't start workloads like record, trace, but should,
974 * so leave the check here. 968 * so leave the check here.
975 */ 969 */
976 if (!perf_target__none(&opts->target)) 970 if (!target__none(&opts->target))
977 perf_evlist__enable(top->evlist); 971 perf_evlist__enable(top->evlist);
978 972
979 /* Wait for a minimal set of events before starting the snapshot */ 973 /* Wait for a minimal set of events before starting the snapshot */
@@ -1016,16 +1010,16 @@ out_delete:
1016} 1010}
1017 1011
1018static int 1012static int
1019parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1013callchain_opt(const struct option *opt, const char *arg, int unset)
1020{ 1014{
1021 /*
1022 * --no-call-graph
1023 */
1024 if (unset)
1025 return 0;
1026
1027 symbol_conf.use_callchain = true; 1015 symbol_conf.use_callchain = true;
1016 return record_callchain_opt(opt, arg, unset);
1017}
1028 1018
1019static int
1020parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1021{
1022 symbol_conf.use_callchain = true;
1029 return record_parse_callchain_opt(opt, arg, unset); 1023 return record_parse_callchain_opt(opt, arg, unset);
1030} 1024}
1031 1025
@@ -1041,7 +1035,7 @@ parse_percent_limit(const struct option *opt, const char *arg,
1041 1035
1042int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1036int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1043{ 1037{
1044 int status; 1038 int status = -1;
1045 char errbuf[BUFSIZ]; 1039 char errbuf[BUFSIZ];
1046 struct perf_top top = { 1040 struct perf_top top = {
1047 .count_filter = 5, 1041 .count_filter = 5,
@@ -1051,14 +1045,15 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1051 .user_freq = UINT_MAX, 1045 .user_freq = UINT_MAX,
1052 .user_interval = ULLONG_MAX, 1046 .user_interval = ULLONG_MAX,
1053 .freq = 4000, /* 4 KHz */ 1047 .freq = 4000, /* 4 KHz */
1054 .target = { 1048 .target = {
1055 .uses_mmap = true, 1049 .uses_mmap = true,
1056 }, 1050 },
1057 }, 1051 },
1052 .max_stack = PERF_MAX_STACK_DEPTH,
1058 .sym_pcnt_filter = 5, 1053 .sym_pcnt_filter = 5,
1059 }; 1054 };
1060 struct perf_record_opts *opts = &top.record_opts; 1055 struct perf_record_opts *opts = &top.record_opts;
1061 struct perf_target *target = &opts->target; 1056 struct target *target = &opts->target;
1062 const struct option options[] = { 1057 const struct option options[] = {
1063 OPT_CALLBACK('e', "event", &top.evlist, "event", 1058 OPT_CALLBACK('e', "event", &top.evlist, "event",
1064 "event selector. use 'perf list' to list available events", 1059 "event selector. use 'perf list' to list available events",
@@ -1074,10 +1069,13 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1074 "list of cpus to monitor"), 1069 "list of cpus to monitor"),
1075 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1070 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1076 "file", "vmlinux pathname"), 1071 "file", "vmlinux pathname"),
1072 OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
1073 "don't load vmlinux even if found"),
1077 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1074 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1078 "hide kernel symbols"), 1075 "hide kernel symbols"),
1079 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages, 1076 OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
1080 "number of mmap data pages"), 1077 "number of mmap data pages",
1078 perf_evlist__parse_mmap_pages),
1081 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1079 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1082 "collect data with this RT SCHED_FIFO priority"), 1080 "collect data with this RT SCHED_FIFO priority"),
1083 OPT_INTEGER('d', "delay", &top.delay_secs, 1081 OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1103,12 +1101,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1103 OPT_INCR('v', "verbose", &verbose, 1101 OPT_INCR('v', "verbose", &verbose,
1104 "be more verbose (show counter open errors, etc)"), 1102 "be more verbose (show counter open errors, etc)"),
1105 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1103 OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
1106 "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"), 1104 "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight,"
1105 " abort, in_tx, transaction"),
1107 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1106 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1108 "Show a column with the number of samples"), 1107 "Show a column with the number of samples"),
1109 OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, 1108 OPT_CALLBACK_NOOPT('G', NULL, &top.record_opts,
1110 "mode[,dump_size]", record_callchain_help, 1109 NULL, "enables call-graph recording",
1111 &parse_callchain_opt, "fp"), 1110 &callchain_opt),
1111 OPT_CALLBACK(0, "call-graph", &top.record_opts,
1112 "mode[,dump_size]", record_callchain_help,
1113 &parse_callchain_opt),
1114 OPT_INTEGER(0, "max-stack", &top.max_stack,
1115 "Set the maximum stack depth when parsing the callchain. "
1116 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),
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),
@@ -1149,8 +1154,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1149 if (sort_order == default_sort_order) 1154 if (sort_order == default_sort_order)
1150 sort_order = "dso,symbol"; 1155 sort_order = "dso,symbol";
1151 1156
1152 if (setup_sorting() < 0) 1157 if (setup_sorting() < 0) {
1153 usage_with_options(top_usage, options); 1158 parse_options_usage(top_usage, options, "s", 1);
1159 goto out_delete_evlist;
1160 }
1154 1161
1155 /* display thread wants entries to be collapsed in a different tree */ 1162 /* display thread wants entries to be collapsed in a different tree */
1156 sort__need_collapse = 1; 1163 sort__need_collapse = 1;
@@ -1162,24 +1169,24 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1162 1169
1163 setup_browser(false); 1170 setup_browser(false);
1164 1171
1165 status = perf_target__validate(target); 1172 status = target__validate(target);
1166 if (status) { 1173 if (status) {
1167 perf_target__strerror(target, status, errbuf, BUFSIZ); 1174 target__strerror(target, status, errbuf, BUFSIZ);
1168 ui__warning("%s", errbuf); 1175 ui__warning("%s\n", errbuf);
1169 } 1176 }
1170 1177
1171 status = perf_target__parse_uid(target); 1178 status = target__parse_uid(target);
1172 if (status) { 1179 if (status) {
1173 int saved_errno = errno; 1180 int saved_errno = errno;
1174 1181
1175 perf_target__strerror(target, status, errbuf, BUFSIZ); 1182 target__strerror(target, status, errbuf, BUFSIZ);
1176 ui__error("%s", errbuf); 1183 ui__error("%s\n", errbuf);
1177 1184
1178 status = -saved_errno; 1185 status = -saved_errno;
1179 goto out_delete_evlist; 1186 goto out_delete_evlist;
1180 } 1187 }
1181 1188
1182 if (perf_target__none(target)) 1189 if (target__none(target))
1183 target->system_wide = true; 1190 target->system_wide = true;
1184 1191
1185 if (perf_evlist__create_maps(top.evlist, target) < 0) 1192 if (perf_evlist__create_maps(top.evlist, target) < 0)
@@ -1196,20 +1203,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1196 if (top.delay_secs < 1) 1203 if (top.delay_secs < 1)
1197 top.delay_secs = 1; 1204 top.delay_secs = 1;
1198 1205
1199 if (opts->user_interval != ULLONG_MAX) 1206 if (perf_record_opts__config(opts)) {
1200 opts->default_interval = opts->user_interval;
1201 if (opts->user_freq != UINT_MAX)
1202 opts->freq = opts->user_freq;
1203
1204 /*
1205 * User specified count overrides default frequency.
1206 */
1207 if (opts->default_interval)
1208 opts->freq = 0;
1209 else if (opts->freq) {
1210 opts->default_interval = opts->freq;
1211 } else {
1212 ui__error("frequency and count are zero, aborting\n");
1213 status = -EINVAL; 1207 status = -EINVAL;
1214 goto out_delete_maps; 1208 goto out_delete_maps;
1215 } 1209 }