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.c372
1 files changed, 115 insertions, 257 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c9ff3950cd4b..72f6eb7b4173 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -68,27 +68,7 @@
68#include <linux/unistd.h> 68#include <linux/unistd.h>
69#include <linux/types.h> 69#include <linux/types.h>
70 70
71void get_term_dimensions(struct winsize *ws) 71static volatile int done;
72{
73 char *s = getenv("LINES");
74
75 if (s != NULL) {
76 ws->ws_row = atoi(s);
77 s = getenv("COLUMNS");
78 if (s != NULL) {
79 ws->ws_col = atoi(s);
80 if (ws->ws_row && ws->ws_col)
81 return;
82 }
83 }
84#ifdef TIOCGWINSZ
85 if (ioctl(1, TIOCGWINSZ, ws) == 0 &&
86 ws->ws_row && ws->ws_col)
87 return;
88#endif
89 ws->ws_row = 25;
90 ws->ws_col = 80;
91}
92 72
93static void perf_top__update_print_entries(struct perf_top *top) 73static void perf_top__update_print_entries(struct perf_top *top)
94{ 74{
@@ -453,8 +433,10 @@ static int perf_top__key_mapped(struct perf_top *top, int c)
453 return 0; 433 return 0;
454} 434}
455 435
456static void perf_top__handle_keypress(struct perf_top *top, int c) 436static bool perf_top__handle_keypress(struct perf_top *top, int c)
457{ 437{
438 bool ret = true;
439
458 if (!perf_top__key_mapped(top, c)) { 440 if (!perf_top__key_mapped(top, c)) {
459 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 441 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
460 struct termios tc, save; 442 struct termios tc, save;
@@ -475,7 +457,7 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
475 457
476 tcsetattr(0, TCSAFLUSH, &save); 458 tcsetattr(0, TCSAFLUSH, &save);
477 if (!perf_top__key_mapped(top, c)) 459 if (!perf_top__key_mapped(top, c))
478 return; 460 return ret;
479 } 461 }
480 462
481 switch (c) { 463 switch (c) {
@@ -537,7 +519,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
537 printf("exiting.\n"); 519 printf("exiting.\n");
538 if (top->dump_symtab) 520 if (top->dump_symtab)
539 perf_session__fprintf_dsos(top->session, stderr); 521 perf_session__fprintf_dsos(top->session, stderr);
540 exit(0); 522 ret = false;
523 break;
541 case 's': 524 case 's':
542 perf_top__prompt_symbol(top, "Enter details symbol"); 525 perf_top__prompt_symbol(top, "Enter details symbol");
543 break; 526 break;
@@ -560,6 +543,8 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
560 default: 543 default:
561 break; 544 break;
562 } 545 }
546
547 return ret;
563} 548}
564 549
565static void perf_top__sort_new_samples(void *arg) 550static void perf_top__sort_new_samples(void *arg)
@@ -596,13 +581,12 @@ static void *display_thread_tui(void *arg)
596 * via --uid. 581 * via --uid.
597 */ 582 */
598 list_for_each_entry(pos, &top->evlist->entries, node) 583 list_for_each_entry(pos, &top->evlist->entries, node)
599 pos->hists.uid_filter_str = top->target.uid_str; 584 pos->hists.uid_filter_str = top->record_opts.target.uid_str;
600 585
601 perf_evlist__tui_browse_hists(top->evlist, help, &hbt, 586 perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
602 &top->session->header.env); 587 &top->session->header.env);
603 588
604 exit_browser(0); 589 done = 1;
605 exit(0);
606 return NULL; 590 return NULL;
607} 591}
608 592
@@ -626,7 +610,7 @@ repeat:
626 /* trash return*/ 610 /* trash return*/
627 getc(stdin); 611 getc(stdin);
628 612
629 while (1) { 613 while (!done) {
630 perf_top__print_sym_table(top); 614 perf_top__print_sym_table(top);
631 /* 615 /*
632 * Either timeout expired or we got an EINTR due to SIGWINCH, 616 * Either timeout expired or we got an EINTR due to SIGWINCH,
@@ -640,15 +624,14 @@ repeat:
640 continue; 624 continue;
641 /* Fall trhu */ 625 /* Fall trhu */
642 default: 626 default:
643 goto process_hotkey; 627 c = getc(stdin);
628 tcsetattr(0, TCSAFLUSH, &save);
629
630 if (perf_top__handle_keypress(top, c))
631 goto repeat;
632 done = 1;
644 } 633 }
645 } 634 }
646process_hotkey:
647 c = getc(stdin);
648 tcsetattr(0, TCSAFLUSH, &save);
649
650 perf_top__handle_keypress(top, c);
651 goto repeat;
652 635
653 return NULL; 636 return NULL;
654} 637}
@@ -716,7 +699,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
716 static struct intlist *seen; 699 static struct intlist *seen;
717 700
718 if (!seen) 701 if (!seen)
719 seen = intlist__new(); 702 seen = intlist__new(NULL);
720 703
721 if (!intlist__has_entry(seen, event->ip.pid)) { 704 if (!intlist__has_entry(seen, event->ip.pid)) {
722 pr_err("Can't find guest [%d]'s kernel information\n", 705 pr_err("Can't find guest [%d]'s kernel information\n",
@@ -727,8 +710,8 @@ static void perf_event__process_sample(struct perf_tool *tool,
727 } 710 }
728 711
729 if (!machine) { 712 if (!machine) {
730 pr_err("%u unprocessable samples recorded.", 713 pr_err("%u unprocessable samples recorded.\r",
731 top->session->hists.stats.nr_unprocessable_samples++); 714 top->session->stats.nr_unprocessable_samples++);
732 return; 715 return;
733 } 716 }
734 717
@@ -847,13 +830,13 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
847 ++top->us_samples; 830 ++top->us_samples;
848 if (top->hide_user_symbols) 831 if (top->hide_user_symbols)
849 continue; 832 continue;
850 machine = perf_session__find_host_machine(session); 833 machine = &session->machines.host;
851 break; 834 break;
852 case PERF_RECORD_MISC_KERNEL: 835 case PERF_RECORD_MISC_KERNEL:
853 ++top->kernel_samples; 836 ++top->kernel_samples;
854 if (top->hide_kernel_symbols) 837 if (top->hide_kernel_symbols)
855 continue; 838 continue;
856 machine = perf_session__find_host_machine(session); 839 machine = &session->machines.host;
857 break; 840 break;
858 case PERF_RECORD_MISC_GUEST_KERNEL: 841 case PERF_RECORD_MISC_GUEST_KERNEL:
859 ++top->guest_kernel_samples; 842 ++top->guest_kernel_samples;
@@ -878,7 +861,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
878 hists__inc_nr_events(&evsel->hists, event->header.type); 861 hists__inc_nr_events(&evsel->hists, event->header.type);
879 machine__process_event(machine, event); 862 machine__process_event(machine, event);
880 } else 863 } else
881 ++session->hists.stats.nr_unknown_events; 864 ++session->stats.nr_unknown_events;
882 } 865 }
883} 866}
884 867
@@ -890,123 +873,42 @@ static void perf_top__mmap_read(struct perf_top *top)
890 perf_top__mmap_read_idx(top, i); 873 perf_top__mmap_read_idx(top, i);
891} 874}
892 875
893static void perf_top__start_counters(struct perf_top *top) 876static int perf_top__start_counters(struct perf_top *top)
894{ 877{
878 char msg[512];
895 struct perf_evsel *counter; 879 struct perf_evsel *counter;
896 struct perf_evlist *evlist = top->evlist; 880 struct perf_evlist *evlist = top->evlist;
881 struct perf_record_opts *opts = &top->record_opts;
897 882
898 if (top->group) 883 perf_evlist__config(evlist, opts);
899 perf_evlist__set_leader(evlist);
900 884
901 list_for_each_entry(counter, &evlist->entries, node) { 885 list_for_each_entry(counter, &evlist->entries, node) {
902 struct perf_event_attr *attr = &counter->attr;
903
904 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
905
906 if (top->freq) {
907 attr->sample_type |= PERF_SAMPLE_PERIOD;
908 attr->freq = 1;
909 attr->sample_freq = top->freq;
910 }
911
912 if (evlist->nr_entries > 1) {
913 attr->sample_type |= PERF_SAMPLE_ID;
914 attr->read_format |= PERF_FORMAT_ID;
915 }
916
917 if (perf_target__has_cpu(&top->target))
918 attr->sample_type |= PERF_SAMPLE_CPU;
919
920 if (symbol_conf.use_callchain)
921 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
922
923 attr->mmap = 1;
924 attr->comm = 1;
925 attr->inherit = top->inherit;
926fallback_missing_features:
927 if (top->exclude_guest_missing)
928 attr->exclude_guest = attr->exclude_host = 0;
929retry_sample_id:
930 attr->sample_id_all = top->sample_id_all_missing ? 0 : 1;
931try_again: 886try_again:
932 if (perf_evsel__open(counter, top->evlist->cpus, 887 if (perf_evsel__open(counter, top->evlist->cpus,
933 top->evlist->threads) < 0) { 888 top->evlist->threads) < 0) {
934 int err = errno; 889 if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
935
936 if (err == EPERM || err == EACCES) {
937 ui__error_paranoid();
938 goto out_err;
939 } else if (err == EINVAL) {
940 if (!top->exclude_guest_missing &&
941 (attr->exclude_guest || attr->exclude_host)) {
942 pr_debug("Old kernel, cannot exclude "
943 "guest or host samples.\n");
944 top->exclude_guest_missing = true;
945 goto fallback_missing_features;
946 } else if (!top->sample_id_all_missing) {
947 /*
948 * Old kernel, no attr->sample_id_type_all field
949 */
950 top->sample_id_all_missing = true;
951 goto retry_sample_id;
952 }
953 }
954 /*
955 * If it's cycles then fall back to hrtimer
956 * based cpu-clock-tick sw counter, which
957 * is always available even if no PMU support:
958 */
959 if ((err == ENOENT || err == ENXIO) &&
960 (attr->type == PERF_TYPE_HARDWARE) &&
961 (attr->config == PERF_COUNT_HW_CPU_CYCLES)) {
962
963 if (verbose) 890 if (verbose)
964 ui__warning("Cycles event not supported,\n" 891 ui__warning("%s\n", msg);
965 "trying to fall back to cpu-clock-ticks\n");
966
967 attr->type = PERF_TYPE_SOFTWARE;
968 attr->config = PERF_COUNT_SW_CPU_CLOCK;
969 if (counter->name) {
970 free(counter->name);
971 counter->name = NULL;
972 }
973 goto try_again; 892 goto try_again;
974 } 893 }
975 894
976 if (err == ENOENT) { 895 perf_evsel__open_strerror(counter, &opts->target,
977 ui__error("The %s event is not supported.\n", 896 errno, msg, sizeof(msg));
978 perf_evsel__name(counter)); 897 ui__error("%s\n", msg);
979 goto out_err;
980 } else if (err == EMFILE) {
981 ui__error("Too many events are opened.\n"
982 "Try again after reducing the number of events\n");
983 goto out_err;
984 } else if ((err == EOPNOTSUPP) && (attr->precise_ip)) {
985 ui__error("\'precise\' request may not be supported. "
986 "Try removing 'p' modifier\n");
987 goto out_err;
988 }
989
990 ui__error("The sys_perf_event_open() syscall "
991 "returned with %d (%s). /bin/dmesg "
992 "may provide additional information.\n"
993 "No CONFIG_PERF_EVENTS=y kernel support "
994 "configured?\n", err, strerror(err));
995 goto out_err; 898 goto out_err;
996 } 899 }
997 } 900 }
998 901
999 if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) { 902 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
1000 ui__error("Failed to mmap with %d (%s)\n", 903 ui__error("Failed to mmap with %d (%s)\n",
1001 errno, strerror(errno)); 904 errno, strerror(errno));
1002 goto out_err; 905 goto out_err;
1003 } 906 }
1004 907
1005 return; 908 return 0;
1006 909
1007out_err: 910out_err:
1008 exit_browser(0); 911 return -1;
1009 exit(0);
1010} 912}
1011 913
1012static int perf_top__setup_sample_type(struct perf_top *top) 914static int perf_top__setup_sample_type(struct perf_top *top)
@@ -1016,7 +918,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
1016 ui__error("Selected -g but \"sym\" not present in --sort/-s."); 918 ui__error("Selected -g but \"sym\" not present in --sort/-s.");
1017 return -EINVAL; 919 return -EINVAL;
1018 } 920 }
1019 } else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) { 921 } else if (callchain_param.mode != CHAIN_NONE) {
1020 if (callchain_register_param(&callchain_param) < 0) { 922 if (callchain_register_param(&callchain_param) < 0) {
1021 ui__error("Can't register callchain params.\n"); 923 ui__error("Can't register callchain params.\n");
1022 return -EINVAL; 924 return -EINVAL;
@@ -1028,6 +930,7 @@ static int perf_top__setup_sample_type(struct perf_top *top)
1028 930
1029static int __cmd_top(struct perf_top *top) 931static int __cmd_top(struct perf_top *top)
1030{ 932{
933 struct perf_record_opts *opts = &top->record_opts;
1031 pthread_t thread; 934 pthread_t thread;
1032 int ret; 935 int ret;
1033 /* 936 /*
@@ -1042,26 +945,42 @@ static int __cmd_top(struct perf_top *top)
1042 if (ret) 945 if (ret)
1043 goto out_delete; 946 goto out_delete;
1044 947
1045 if (perf_target__has_task(&top->target)) 948 if (perf_target__has_task(&opts->target))
1046 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 949 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
1047 perf_event__process, 950 perf_event__process,
1048 &top->session->host_machine); 951 &top->session->machines.host);
1049 else 952 else
1050 perf_event__synthesize_threads(&top->tool, perf_event__process, 953 perf_event__synthesize_threads(&top->tool, perf_event__process,
1051 &top->session->host_machine); 954 &top->session->machines.host);
1052 perf_top__start_counters(top); 955
956 ret = perf_top__start_counters(top);
957 if (ret)
958 goto out_delete;
959
1053 top->session->evlist = top->evlist; 960 top->session->evlist = top->evlist;
1054 perf_session__set_id_hdr_size(top->session); 961 perf_session__set_id_hdr_size(top->session);
1055 962
963 /*
964 * When perf is starting the traced process, all the events (apart from
965 * group members) have enable_on_exec=1 set, so don't spoil it by
966 * prematurely enabling them.
967 *
968 * XXX 'top' still doesn't start workloads like record, trace, but should,
969 * so leave the check here.
970 */
971 if (!perf_target__none(&opts->target))
972 perf_evlist__enable(top->evlist);
973
1056 /* Wait for a minimal set of events before starting the snapshot */ 974 /* Wait for a minimal set of events before starting the snapshot */
1057 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 975 poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
1058 976
1059 perf_top__mmap_read(top); 977 perf_top__mmap_read(top);
1060 978
979 ret = -1;
1061 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui : 980 if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
1062 display_thread), top)) { 981 display_thread), top)) {
1063 ui__error("Could not create display thread.\n"); 982 ui__error("Could not create display thread.\n");
1064 exit(-1); 983 goto out_delete;
1065 } 984 }
1066 985
1067 if (top->realtime_prio) { 986 if (top->realtime_prio) {
@@ -1070,11 +989,11 @@ static int __cmd_top(struct perf_top *top)
1070 param.sched_priority = top->realtime_prio; 989 param.sched_priority = top->realtime_prio;
1071 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 990 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
1072 ui__error("Could not set realtime priority.\n"); 991 ui__error("Could not set realtime priority.\n");
1073 exit(-1); 992 goto out_delete;
1074 } 993 }
1075 } 994 }
1076 995
1077 while (1) { 996 while (!done) {
1078 u64 hits = top->samples; 997 u64 hits = top->samples;
1079 998
1080 perf_top__mmap_read(top); 999 perf_top__mmap_read(top);
@@ -1083,126 +1002,67 @@ static int __cmd_top(struct perf_top *top)
1083 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 1002 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
1084 } 1003 }
1085 1004
1005 ret = 0;
1086out_delete: 1006out_delete:
1087 perf_session__delete(top->session); 1007 perf_session__delete(top->session);
1088 top->session = NULL; 1008 top->session = NULL;
1089 1009
1090 return 0; 1010 return ret;
1091} 1011}
1092 1012
1093static int 1013static int
1094parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1014parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1095{ 1015{
1096 struct perf_top *top = (struct perf_top *)opt->value;
1097 char *tok, *tok2;
1098 char *endptr;
1099
1100 /* 1016 /*
1101 * --no-call-graph 1017 * --no-call-graph
1102 */ 1018 */
1103 if (unset) { 1019 if (unset)
1104 top->dont_use_callchains = true;
1105 return 0; 1020 return 0;
1106 }
1107 1021
1108 symbol_conf.use_callchain = true; 1022 symbol_conf.use_callchain = true;
1109 1023
1110 if (!arg) 1024 return record_parse_callchain_opt(opt, arg, unset);
1111 return 0;
1112
1113 tok = strtok((char *)arg, ",");
1114 if (!tok)
1115 return -1;
1116
1117 /* get the output mode */
1118 if (!strncmp(tok, "graph", strlen(arg)))
1119 callchain_param.mode = CHAIN_GRAPH_ABS;
1120
1121 else if (!strncmp(tok, "flat", strlen(arg)))
1122 callchain_param.mode = CHAIN_FLAT;
1123
1124 else if (!strncmp(tok, "fractal", strlen(arg)))
1125 callchain_param.mode = CHAIN_GRAPH_REL;
1126
1127 else if (!strncmp(tok, "none", strlen(arg))) {
1128 callchain_param.mode = CHAIN_NONE;
1129 symbol_conf.use_callchain = false;
1130
1131 return 0;
1132 } else
1133 return -1;
1134
1135 /* get the min percentage */
1136 tok = strtok(NULL, ",");
1137 if (!tok)
1138 goto setup;
1139
1140 callchain_param.min_percent = strtod(tok, &endptr);
1141 if (tok == endptr)
1142 return -1;
1143
1144 /* get the print limit */
1145 tok2 = strtok(NULL, ",");
1146 if (!tok2)
1147 goto setup;
1148
1149 if (tok2[0] != 'c') {
1150 callchain_param.print_limit = strtod(tok2, &endptr);
1151 tok2 = strtok(NULL, ",");
1152 if (!tok2)
1153 goto setup;
1154 }
1155
1156 /* get the call chain order */
1157 if (!strcmp(tok2, "caller"))
1158 callchain_param.order = ORDER_CALLER;
1159 else if (!strcmp(tok2, "callee"))
1160 callchain_param.order = ORDER_CALLEE;
1161 else
1162 return -1;
1163setup:
1164 if (callchain_register_param(&callchain_param) < 0) {
1165 fprintf(stderr, "Can't register callchain params\n");
1166 return -1;
1167 }
1168 return 0;
1169} 1025}
1170 1026
1171int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) 1027int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1172{ 1028{
1173 struct perf_evsel *pos;
1174 int status; 1029 int status;
1175 char errbuf[BUFSIZ]; 1030 char errbuf[BUFSIZ];
1176 struct perf_top top = { 1031 struct perf_top top = {
1177 .count_filter = 5, 1032 .count_filter = 5,
1178 .delay_secs = 2, 1033 .delay_secs = 2,
1179 .freq = 4000, /* 4 KHz */ 1034 .record_opts = {
1180 .mmap_pages = 128, 1035 .mmap_pages = UINT_MAX,
1181 .sym_pcnt_filter = 5, 1036 .user_freq = UINT_MAX,
1182 .target = { 1037 .user_interval = ULLONG_MAX,
1183 .uses_mmap = true, 1038 .freq = 4000, /* 4 KHz */
1039 .target = {
1040 .uses_mmap = true,
1041 },
1184 }, 1042 },
1043 .sym_pcnt_filter = 5,
1185 }; 1044 };
1186 char callchain_default_opt[] = "fractal,0.5,callee"; 1045 struct perf_record_opts *opts = &top.record_opts;
1046 struct perf_target *target = &opts->target;
1187 const struct option options[] = { 1047 const struct option options[] = {
1188 OPT_CALLBACK('e', "event", &top.evlist, "event", 1048 OPT_CALLBACK('e', "event", &top.evlist, "event",
1189 "event selector. use 'perf list' to list available events", 1049 "event selector. use 'perf list' to list available events",
1190 parse_events_option), 1050 parse_events_option),
1191 OPT_INTEGER('c', "count", &top.default_interval, 1051 OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
1192 "event period to sample"), 1052 OPT_STRING('p', "pid", &target->pid, "pid",
1193 OPT_STRING('p', "pid", &top.target.pid, "pid",
1194 "profile events on existing process id"), 1053 "profile events on existing process id"),
1195 OPT_STRING('t', "tid", &top.target.tid, "tid", 1054 OPT_STRING('t', "tid", &target->tid, "tid",
1196 "profile events on existing thread id"), 1055 "profile events on existing thread id"),
1197 OPT_BOOLEAN('a', "all-cpus", &top.target.system_wide, 1056 OPT_BOOLEAN('a', "all-cpus", &target->system_wide,
1198 "system-wide collection from all CPUs"), 1057 "system-wide collection from all CPUs"),
1199 OPT_STRING('C', "cpu", &top.target.cpu_list, "cpu", 1058 OPT_STRING('C', "cpu", &target->cpu_list, "cpu",
1200 "list of cpus to monitor"), 1059 "list of cpus to monitor"),
1201 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 1060 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
1202 "file", "vmlinux pathname"), 1061 "file", "vmlinux pathname"),
1203 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols, 1062 OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
1204 "hide kernel symbols"), 1063 "hide kernel symbols"),
1205 OPT_UINTEGER('m', "mmap-pages", &top.mmap_pages, "number of mmap data pages"), 1064 OPT_UINTEGER('m', "mmap-pages", &opts->mmap_pages,
1065 "number of mmap data pages"),
1206 OPT_INTEGER('r', "realtime", &top.realtime_prio, 1066 OPT_INTEGER('r', "realtime", &top.realtime_prio,
1207 "collect data with this RT SCHED_FIFO priority"), 1067 "collect data with this RT SCHED_FIFO priority"),
1208 OPT_INTEGER('d', "delay", &top.delay_secs, 1068 OPT_INTEGER('d', "delay", &top.delay_secs,
@@ -1211,16 +1071,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1211 "dump the symbol table used for profiling"), 1071 "dump the symbol table used for profiling"),
1212 OPT_INTEGER('f', "count-filter", &top.count_filter, 1072 OPT_INTEGER('f', "count-filter", &top.count_filter,
1213 "only display functions with more events than this"), 1073 "only display functions with more events than this"),
1214 OPT_BOOLEAN('g', "group", &top.group, 1074 OPT_BOOLEAN('g', "group", &opts->group,
1215 "put the counters into a counter group"), 1075 "put the counters into a counter group"),
1216 OPT_BOOLEAN('i', "inherit", &top.inherit, 1076 OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
1217 "child tasks inherit counters"), 1077 "child tasks do not inherit counters"),
1218 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name", 1078 OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
1219 "symbol to annotate"), 1079 "symbol to annotate"),
1220 OPT_BOOLEAN('z', "zero", &top.zero, 1080 OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
1221 "zero history across updates"), 1081 OPT_UINTEGER('F', "freq", &opts->user_freq, "profile at this frequency"),
1222 OPT_INTEGER('F', "freq", &top.freq,
1223 "profile at this frequency"),
1224 OPT_INTEGER('E', "entries", &top.print_entries, 1082 OPT_INTEGER('E', "entries", &top.print_entries,
1225 "display this many functions"), 1083 "display this many functions"),
1226 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols, 1084 OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
@@ -1233,10 +1091,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1233 "sort by key(s): pid, comm, dso, symbol, parent"), 1091 "sort by key(s): pid, comm, dso, symbol, parent"),
1234 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1092 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1235 "Show a column with the number of samples"), 1093 "Show a column with the number of samples"),
1236 OPT_CALLBACK_DEFAULT('G', "call-graph", &top, "output_type,min_percent, call_order", 1094 OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts,
1237 "Display callchains using output_type (graph, flat, fractal, or none), min percent threshold and callchain order. " 1095 "mode[,dump_size]", record_callchain_help,
1238 "Default: fractal,0.5,callee", &parse_callchain_opt, 1096 &parse_callchain_opt, "fp"),
1239 callchain_default_opt),
1240 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 1097 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
1241 "Show a column with the sum of periods"), 1098 "Show a column with the sum of periods"),
1242 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 1099 OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
@@ -1251,7 +1108,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1251 "Display raw encoding of assembly instructions (default)"), 1108 "Display raw encoding of assembly instructions (default)"),
1252 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1109 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1253 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1110 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1254 OPT_STRING('u', "uid", &top.target.uid_str, "user", "user to profile"), 1111 OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
1255 OPT_END() 1112 OPT_END()
1256 }; 1113 };
1257 const char * const top_usage[] = { 1114 const char * const top_usage[] = {
@@ -1272,7 +1129,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1272 if (sort_order == default_sort_order) 1129 if (sort_order == default_sort_order)
1273 sort_order = "dso,symbol"; 1130 sort_order = "dso,symbol";
1274 1131
1275 setup_sorting(top_usage, options); 1132 if (setup_sorting() < 0)
1133 usage_with_options(top_usage, options);
1276 1134
1277 if (top.use_stdio) 1135 if (top.use_stdio)
1278 use_browser = 0; 1136 use_browser = 0;
@@ -1281,33 +1139,33 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1281 1139
1282 setup_browser(false); 1140 setup_browser(false);
1283 1141
1284 status = perf_target__validate(&top.target); 1142 status = perf_target__validate(target);
1285 if (status) { 1143 if (status) {
1286 perf_target__strerror(&top.target, status, errbuf, BUFSIZ); 1144 perf_target__strerror(target, status, errbuf, BUFSIZ);
1287 ui__warning("%s", errbuf); 1145 ui__warning("%s", errbuf);
1288 } 1146 }
1289 1147
1290 status = perf_target__parse_uid(&top.target); 1148 status = perf_target__parse_uid(target);
1291 if (status) { 1149 if (status) {
1292 int saved_errno = errno; 1150 int saved_errno = errno;
1293 1151
1294 perf_target__strerror(&top.target, status, errbuf, BUFSIZ); 1152 perf_target__strerror(target, status, errbuf, BUFSIZ);
1295 ui__error("%s", errbuf); 1153 ui__error("%s", errbuf);
1296 1154
1297 status = -saved_errno; 1155 status = -saved_errno;
1298 goto out_delete_evlist; 1156 goto out_delete_evlist;
1299 } 1157 }
1300 1158
1301 if (perf_target__none(&top.target)) 1159 if (perf_target__none(target))
1302 top.target.system_wide = true; 1160 target->system_wide = true;
1303 1161
1304 if (perf_evlist__create_maps(top.evlist, &top.target) < 0) 1162 if (perf_evlist__create_maps(top.evlist, target) < 0)
1305 usage_with_options(top_usage, options); 1163 usage_with_options(top_usage, options);
1306 1164
1307 if (!top.evlist->nr_entries && 1165 if (!top.evlist->nr_entries &&
1308 perf_evlist__add_default(top.evlist) < 0) { 1166 perf_evlist__add_default(top.evlist) < 0) {
1309 ui__error("Not enough memory for event selector list\n"); 1167 ui__error("Not enough memory for event selector list\n");
1310 return -ENOMEM; 1168 goto out_delete_maps;
1311 } 1169 }
1312 1170
1313 symbol_conf.nr_events = top.evlist->nr_entries; 1171 symbol_conf.nr_events = top.evlist->nr_entries;
@@ -1315,24 +1173,22 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1315 if (top.delay_secs < 1) 1173 if (top.delay_secs < 1)
1316 top.delay_secs = 1; 1174 top.delay_secs = 1;
1317 1175
1176 if (opts->user_interval != ULLONG_MAX)
1177 opts->default_interval = opts->user_interval;
1178 if (opts->user_freq != UINT_MAX)
1179 opts->freq = opts->user_freq;
1180
1318 /* 1181 /*
1319 * User specified count overrides default frequency. 1182 * User specified count overrides default frequency.
1320 */ 1183 */
1321 if (top.default_interval) 1184 if (opts->default_interval)
1322 top.freq = 0; 1185 opts->freq = 0;
1323 else if (top.freq) { 1186 else if (opts->freq) {
1324 top.default_interval = top.freq; 1187 opts->default_interval = opts->freq;
1325 } else { 1188 } else {
1326 ui__error("frequency and count are zero, aborting\n"); 1189 ui__error("frequency and count are zero, aborting\n");
1327 exit(EXIT_FAILURE); 1190 status = -EINVAL;
1328 } 1191 goto out_delete_maps;
1329
1330 list_for_each_entry(pos, &top.evlist->entries, node) {
1331 /*
1332 * Fill in the ones not specifically initialized via -c:
1333 */
1334 if (!pos->attr.sample_period)
1335 pos->attr.sample_period = top.default_interval;
1336 } 1192 }
1337 1193
1338 top.sym_evsel = perf_evlist__first(top.evlist); 1194 top.sym_evsel = perf_evlist__first(top.evlist);
@@ -1365,6 +1221,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1365 1221
1366 status = __cmd_top(&top); 1222 status = __cmd_top(&top);
1367 1223
1224out_delete_maps:
1225 perf_evlist__delete_maps(top.evlist);
1368out_delete_evlist: 1226out_delete_evlist:
1369 perf_evlist__delete(top.evlist); 1227 perf_evlist__delete(top.evlist);
1370 1228