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.c87
1 files changed, 55 insertions, 32 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 377971dc89a3..fc3d55f832ac 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -59,7 +59,7 @@
59 59
60#include <sys/syscall.h> 60#include <sys/syscall.h>
61#include <sys/ioctl.h> 61#include <sys/ioctl.h>
62#include <sys/poll.h> 62#include <poll.h>
63#include <sys/prctl.h> 63#include <sys/prctl.h>
64#include <sys/wait.h> 64#include <sys/wait.h>
65#include <sys/uio.h> 65#include <sys/uio.h>
@@ -276,11 +276,17 @@ static void perf_top__print_sym_table(struct perf_top *top)
276 return; 276 return;
277 } 277 }
278 278
279 if (top->zero) {
280 hists__delete_entries(&top->sym_evsel->hists);
281 } else {
282 hists__decay_entries(&top->sym_evsel->hists,
283 top->hide_user_symbols,
284 top->hide_kernel_symbols);
285 }
286
279 hists__collapse_resort(&top->sym_evsel->hists, NULL); 287 hists__collapse_resort(&top->sym_evsel->hists, NULL);
280 hists__output_resort(&top->sym_evsel->hists); 288 hists__output_resort(&top->sym_evsel->hists);
281 hists__decay_entries(&top->sym_evsel->hists, 289
282 top->hide_user_symbols,
283 top->hide_kernel_symbols);
284 hists__output_recalc_col_len(&top->sym_evsel->hists, 290 hists__output_recalc_col_len(&top->sym_evsel->hists,
285 top->print_entries - printed); 291 top->print_entries - printed);
286 putchar('\n'); 292 putchar('\n');
@@ -427,18 +433,13 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
427 433
428 if (!perf_top__key_mapped(top, c)) { 434 if (!perf_top__key_mapped(top, c)) {
429 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 435 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
430 struct termios tc, save; 436 struct termios save;
431 437
432 perf_top__print_mapped_keys(top); 438 perf_top__print_mapped_keys(top);
433 fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 439 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
434 fflush(stdout); 440 fflush(stdout);
435 441
436 tcgetattr(0, &save); 442 set_term_quiet_input(&save);
437 tc = save;
438 tc.c_lflag &= ~(ICANON | ECHO);
439 tc.c_cc[VMIN] = 0;
440 tc.c_cc[VTIME] = 0;
441 tcsetattr(0, TCSANOW, &tc);
442 443
443 poll(&stdin_poll, 1, -1); 444 poll(&stdin_poll, 1, -1);
444 c = getc(stdin); 445 c = getc(stdin);
@@ -542,11 +543,16 @@ static void perf_top__sort_new_samples(void *arg)
542 if (t->evlist->selected != NULL) 543 if (t->evlist->selected != NULL)
543 t->sym_evsel = t->evlist->selected; 544 t->sym_evsel = t->evlist->selected;
544 545
546 if (t->zero) {
547 hists__delete_entries(&t->sym_evsel->hists);
548 } else {
549 hists__decay_entries(&t->sym_evsel->hists,
550 t->hide_user_symbols,
551 t->hide_kernel_symbols);
552 }
553
545 hists__collapse_resort(&t->sym_evsel->hists, NULL); 554 hists__collapse_resort(&t->sym_evsel->hists, NULL);
546 hists__output_resort(&t->sym_evsel->hists); 555 hists__output_resort(&t->sym_evsel->hists);
547 hists__decay_entries(&t->sym_evsel->hists,
548 t->hide_user_symbols,
549 t->hide_kernel_symbols);
550} 556}
551 557
552static void *display_thread_tui(void *arg) 558static void *display_thread_tui(void *arg)
@@ -577,23 +583,32 @@ static void *display_thread_tui(void *arg)
577 return NULL; 583 return NULL;
578} 584}
579 585
586static void display_sig(int sig __maybe_unused)
587{
588 done = 1;
589}
590
591static void display_setup_sig(void)
592{
593 signal(SIGSEGV, display_sig);
594 signal(SIGFPE, display_sig);
595 signal(SIGINT, display_sig);
596 signal(SIGQUIT, display_sig);
597 signal(SIGTERM, display_sig);
598}
599
580static void *display_thread(void *arg) 600static void *display_thread(void *arg)
581{ 601{
582 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 602 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
583 struct termios tc, save; 603 struct termios save;
584 struct perf_top *top = arg; 604 struct perf_top *top = arg;
585 int delay_msecs, c; 605 int delay_msecs, c;
586 606
587 tcgetattr(0, &save); 607 display_setup_sig();
588 tc = save;
589 tc.c_lflag &= ~(ICANON | ECHO);
590 tc.c_cc[VMIN] = 0;
591 tc.c_cc[VTIME] = 0;
592
593 pthread__unblock_sigwinch(); 608 pthread__unblock_sigwinch();
594repeat: 609repeat:
595 delay_msecs = top->delay_secs * 1000; 610 delay_msecs = top->delay_secs * 1000;
596 tcsetattr(0, TCSANOW, &tc); 611 set_term_quiet_input(&save);
597 /* trash return*/ 612 /* trash return*/
598 getc(stdin); 613 getc(stdin);
599 614
@@ -620,13 +635,16 @@ repeat:
620 } 635 }
621 } 636 }
622 637
638 tcsetattr(0, TCSAFLUSH, &save);
623 return NULL; 639 return NULL;
624} 640}
625 641
626static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym) 642static int symbol_filter(struct map *map, struct symbol *sym)
627{ 643{
628 const char *name = sym->name; 644 const char *name = sym->name;
629 645
646 if (!map->dso->kernel)
647 return 0;
630 /* 648 /*
631 * ppc64 uses function descriptors and appends a '.' to the 649 * ppc64 uses function descriptors and appends a '.' to the
632 * start of every instruction address. Remove it. 650 * start of every instruction address. Remove it.
@@ -876,7 +894,7 @@ try_again:
876 894
877 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 895 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
878 ui__error("Failed to mmap with %d (%s)\n", 896 ui__error("Failed to mmap with %d (%s)\n",
879 errno, strerror(errno)); 897 errno, strerror_r(errno, msg, sizeof(msg)));
880 goto out_err; 898 goto out_err;
881 } 899 }
882 900
@@ -911,7 +929,7 @@ static int __cmd_top(struct perf_top *top)
911 929
912 top->session = perf_session__new(NULL, false, NULL); 930 top->session = perf_session__new(NULL, false, NULL);
913 if (top->session == NULL) 931 if (top->session == NULL)
914 return -ENOMEM; 932 return -1;
915 933
916 machines__set_symbol_filter(&top->session->machines, symbol_filter); 934 machines__set_symbol_filter(&top->session->machines, symbol_filter);
917 935
@@ -946,7 +964,7 @@ static int __cmd_top(struct perf_top *top)
946 perf_evlist__enable(top->evlist); 964 perf_evlist__enable(top->evlist);
947 965
948 /* Wait for a minimal set of events before starting the snapshot */ 966 /* Wait for a minimal set of events before starting the snapshot */
949 poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 967 perf_evlist__poll(top->evlist, 100);
950 968
951 perf_top__mmap_read(top); 969 perf_top__mmap_read(top);
952 970
@@ -963,7 +981,7 @@ static int __cmd_top(struct perf_top *top)
963 param.sched_priority = top->realtime_prio; 981 param.sched_priority = top->realtime_prio;
964 if (sched_setscheduler(0, SCHED_FIFO, &param)) { 982 if (sched_setscheduler(0, SCHED_FIFO, &param)) {
965 ui__error("Could not set realtime priority.\n"); 983 ui__error("Could not set realtime priority.\n");
966 goto out_delete; 984 goto out_join;
967 } 985 }
968 } 986 }
969 987
@@ -973,10 +991,12 @@ static int __cmd_top(struct perf_top *top)
973 perf_top__mmap_read(top); 991 perf_top__mmap_read(top);
974 992
975 if (hits == top->samples) 993 if (hits == top->samples)
976 ret = poll(top->evlist->pollfd, top->evlist->nr_fds, 100); 994 ret = perf_evlist__poll(top->evlist, 100);
977 } 995 }
978 996
979 ret = 0; 997 ret = 0;
998out_join:
999 pthread_join(thread, NULL);
980out_delete: 1000out_delete:
981 perf_session__delete(top->session); 1001 perf_session__delete(top->session);
982 top->session = NULL; 1002 top->session = NULL;
@@ -1000,10 +1020,8 @@ parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1000 1020
1001static int perf_top_config(const char *var, const char *value, void *cb) 1021static int perf_top_config(const char *var, const char *value, void *cb)
1002{ 1022{
1003 struct perf_top *top = cb;
1004
1005 if (!strcmp(var, "top.call-graph")) 1023 if (!strcmp(var, "top.call-graph"))
1006 return record_parse_callchain(value, &top->record_opts); 1024 var = "call-graph.record-mode"; /* fall-through */
1007 if (!strcmp(var, "top.children")) { 1025 if (!strcmp(var, "top.children")) {
1008 symbol_conf.cumulate_callchain = perf_config_bool(var, value); 1026 symbol_conf.cumulate_callchain = perf_config_bool(var, value);
1009 return 0; 1027 return 0;
@@ -1122,6 +1140,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1122 "Interleave source code with assembly code (default)"), 1140 "Interleave source code with assembly code (default)"),
1123 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 1141 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
1124 "Display raw encoding of assembly instructions (default)"), 1142 "Display raw encoding of assembly instructions (default)"),
1143 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
1144 "Enable kernel symbol demangling"),
1125 OPT_STRING(0, "objdump", &objdump_path, "path", 1145 OPT_STRING(0, "objdump", &objdump_path, "path",
1126 "objdump binary to use for disassembly and annotations"), 1146 "objdump binary to use for disassembly and annotations"),
1127 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1147 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
@@ -1131,6 +1151,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1131 "Don't show entries under that percent", parse_percent_limit), 1151 "Don't show entries under that percent", parse_percent_limit),
1132 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 1152 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
1133 "How to display percentage of filtered entries", parse_filter_percentage), 1153 "How to display percentage of filtered entries", parse_filter_percentage),
1154 OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
1155 "width[,width...]",
1156 "don't try to adjust column width, use these fixed values"),
1134 OPT_END() 1157 OPT_END()
1135 }; 1158 };
1136 const char * const top_usage[] = { 1159 const char * const top_usage[] = {
@@ -1217,7 +1240,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1217 symbol_conf.priv_size = sizeof(struct annotation); 1240 symbol_conf.priv_size = sizeof(struct annotation);
1218 1241
1219 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1242 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1220 if (symbol__init() < 0) 1243 if (symbol__init(NULL) < 0)
1221 return -1; 1244 return -1;
1222 1245
1223 sort__setup_elide(stdout); 1246 sort__setup_elide(stdout);