aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/newt.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/newt.c')
-rw-r--r--tools/perf/util/newt.c150
1 files changed, 116 insertions, 34 deletions
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c
index ccb7c5bb269e..d54c540f49db 100644
--- a/tools/perf/util/newt.c
+++ b/tools/perf/util/newt.c
@@ -1,7 +1,15 @@
1#define _GNU_SOURCE 1#define _GNU_SOURCE
2#include <stdio.h> 2#include <stdio.h>
3#undef _GNU_SOURCE 3#undef _GNU_SOURCE
4 4/*
5 * slang versions <= 2.0.6 have a "#if HAVE_LONG_LONG" that breaks
6 * the build if it isn't defined. Use the equivalent one that glibc
7 * has on features.h.
8 */
9#include <features.h>
10#ifndef HAVE_LONG_LONG
11#define HAVE_LONG_LONG __GLIBC_HAVE_LONG_LONG
12#endif
5#include <slang.h> 13#include <slang.h>
6#include <stdlib.h> 14#include <stdlib.h>
7#include <newt.h> 15#include <newt.h>
@@ -227,6 +235,15 @@ static bool dialog_yesno(const char *msg)
227 return newtWinChoice(NULL, yes, no, (char *)msg) == 1; 235 return newtWinChoice(NULL, yes, no, (char *)msg) == 1;
228} 236}
229 237
238static void ui__error_window(const char *fmt, ...)
239{
240 va_list ap;
241
242 va_start(ap, fmt);
243 newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap);
244 va_end(ap);
245}
246
230#define HE_COLORSET_TOP 50 247#define HE_COLORSET_TOP 50
231#define HE_COLORSET_MEDIUM 51 248#define HE_COLORSET_MEDIUM 51
232#define HE_COLORSET_NORMAL 52 249#define HE_COLORSET_NORMAL 52
@@ -375,8 +392,11 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
375 newtFormAddHotKey(self->form, NEWT_KEY_DOWN); 392 newtFormAddHotKey(self->form, NEWT_KEY_DOWN);
376 newtFormAddHotKey(self->form, NEWT_KEY_PGUP); 393 newtFormAddHotKey(self->form, NEWT_KEY_PGUP);
377 newtFormAddHotKey(self->form, NEWT_KEY_PGDN); 394 newtFormAddHotKey(self->form, NEWT_KEY_PGDN);
395 newtFormAddHotKey(self->form, ' ');
378 newtFormAddHotKey(self->form, NEWT_KEY_HOME); 396 newtFormAddHotKey(self->form, NEWT_KEY_HOME);
379 newtFormAddHotKey(self->form, NEWT_KEY_END); 397 newtFormAddHotKey(self->form, NEWT_KEY_END);
398 newtFormAddHotKey(self->form, NEWT_KEY_TAB);
399 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
380 400
381 if (ui_browser__refresh_entries(self) < 0) 401 if (ui_browser__refresh_entries(self) < 0)
382 return -1; 402 return -1;
@@ -389,6 +409,8 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
389 409
390 if (es->reason != NEWT_EXIT_HOTKEY) 410 if (es->reason != NEWT_EXIT_HOTKEY)
391 break; 411 break;
412 if (is_exit_key(es->u.key))
413 return es->u.key;
392 switch (es->u.key) { 414 switch (es->u.key) {
393 case NEWT_KEY_DOWN: 415 case NEWT_KEY_DOWN:
394 if (self->index == self->nr_entries - 1) 416 if (self->index == self->nr_entries - 1)
@@ -411,6 +433,7 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
411 } 433 }
412 break; 434 break;
413 case NEWT_KEY_PGDN: 435 case NEWT_KEY_PGDN:
436 case ' ':
414 if (self->first_visible_entry_idx + self->height > self->nr_entries - 1) 437 if (self->first_visible_entry_idx + self->height > self->nr_entries - 1)
415 break; 438 break;
416 439
@@ -461,12 +484,10 @@ static int ui_browser__run(struct ui_browser *self, const char *title,
461 } 484 }
462 } 485 }
463 break; 486 break;
464 case NEWT_KEY_ESCAPE: 487 case NEWT_KEY_RIGHT:
465 case NEWT_KEY_LEFT: 488 case NEWT_KEY_LEFT:
466 case CTRL('c'): 489 case NEWT_KEY_TAB:
467 case 'Q': 490 return es->u.key;
468 case 'q':
469 return 0;
470 default: 491 default:
471 continue; 492 continue;
472 } 493 }
@@ -658,18 +679,24 @@ static size_t hist_entry__append_browser(struct hist_entry *self,
658 return ret; 679 return ret;
659} 680}
660 681
661static void hist_entry__annotate_browser(struct hist_entry *self) 682int hist_entry__tui_annotate(struct hist_entry *self)
662{ 683{
663 struct ui_browser browser; 684 struct ui_browser browser;
664 struct newtExitStruct es; 685 struct newtExitStruct es;
665 struct objdump_line *pos, *n; 686 struct objdump_line *pos, *n;
666 LIST_HEAD(head); 687 LIST_HEAD(head);
688 int ret;
667 689
668 if (self->ms.sym == NULL) 690 if (self->ms.sym == NULL)
669 return; 691 return -1;
670 692
671 if (hist_entry__annotate(self, &head) < 0) 693 if (self->ms.map->dso->annotate_warned)
672 return; 694 return -1;
695
696 if (hist_entry__annotate(self, &head) < 0) {
697 ui__error_window(browser__last_msg);
698 return -1;
699 }
673 700
674 ui_helpline__push("Press <- or ESC to exit"); 701 ui_helpline__push("Press <- or ESC to exit");
675 702
@@ -684,7 +711,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self)
684 } 711 }
685 712
686 browser.width += 18; /* Percentage */ 713 browser.width += 18; /* Percentage */
687 ui_browser__run(&browser, self->ms.sym->name, &es); 714 ret = ui_browser__run(&browser, self->ms.sym->name, &es);
688 newtFormDestroy(browser.form); 715 newtFormDestroy(browser.form);
689 newtPopWindow(); 716 newtPopWindow();
690 list_for_each_entry_safe(pos, n, &head, node) { 717 list_for_each_entry_safe(pos, n, &head, node) {
@@ -692,6 +719,7 @@ static void hist_entry__annotate_browser(struct hist_entry *self)
692 objdump_line__free(pos); 719 objdump_line__free(pos);
693 } 720 }
694 ui_helpline__pop(); 721 ui_helpline__pop();
722 return ret;
695} 723}
696 724
697static const void *newt__symbol_tree_get_current(newtComponent self) 725static const void *newt__symbol_tree_get_current(newtComponent self)
@@ -814,6 +842,8 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists
814 newtFormAddHotKey(self->form, 'h'); 842 newtFormAddHotKey(self->form, 'h');
815 newtFormAddHotKey(self->form, NEWT_KEY_F1); 843 newtFormAddHotKey(self->form, NEWT_KEY_F1);
816 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT); 844 newtFormAddHotKey(self->form, NEWT_KEY_RIGHT);
845 newtFormAddHotKey(self->form, NEWT_KEY_TAB);
846 newtFormAddHotKey(self->form, NEWT_KEY_UNTAB);
817 newtFormAddComponents(self->form, self->tree, NULL); 847 newtFormAddComponents(self->form, self->tree, NULL);
818 self->selection = newt__symbol_tree_get_current(self->tree); 848 self->selection = newt__symbol_tree_get_current(self->tree);
819 849
@@ -845,7 +875,7 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self)
845 return he ? he->thread : NULL; 875 return he ? he->thread : NULL;
846} 876}
847 877
848static int hist_browser__title(char *bf, size_t size, const char *input_name, 878static int hist_browser__title(char *bf, size_t size, const char *ev_name,
849 const struct dso *dso, const struct thread *thread) 879 const struct dso *dso, const struct thread *thread)
850{ 880{
851 int printed = 0; 881 int printed = 0;
@@ -859,18 +889,18 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name,
859 printed += snprintf(bf + printed, size - printed, 889 printed += snprintf(bf + printed, size - printed,
860 "%sDSO: %s", thread ? " " : "", 890 "%sDSO: %s", thread ? " " : "",
861 dso->short_name); 891 dso->short_name);
862 return printed ?: snprintf(bf, size, "Report: %s", input_name); 892 return printed ?: snprintf(bf, size, "Event: %s", ev_name);
863} 893}
864 894
865int hists__browse(struct hists *self, const char *helpline, const char *input_name) 895int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
866{ 896{
867 struct hist_browser *browser = hist_browser__new(); 897 struct hist_browser *browser = hist_browser__new();
868 struct pstack *fstack = pstack__new(2); 898 struct pstack *fstack;
869 const struct thread *thread_filter = NULL; 899 const struct thread *thread_filter = NULL;
870 const struct dso *dso_filter = NULL; 900 const struct dso *dso_filter = NULL;
871 struct newtExitStruct es; 901 struct newtExitStruct es;
872 char msg[160]; 902 char msg[160];
873 int err = -1; 903 int key = -1;
874 904
875 if (browser == NULL) 905 if (browser == NULL)
876 return -1; 906 return -1;
@@ -881,7 +911,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
881 911
882 ui_helpline__push(helpline); 912 ui_helpline__push(helpline);
883 913
884 hist_browser__title(msg, sizeof(msg), input_name, 914 hist_browser__title(msg, sizeof(msg), ev_name,
885 dso_filter, thread_filter); 915 dso_filter, thread_filter);
886 if (hist_browser__populate(browser, self, msg) < 0) 916 if (hist_browser__populate(browser, self, msg) < 0)
887 goto out_free_stack; 917 goto out_free_stack;
@@ -899,11 +929,27 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na
899 dso = browser->selection->map ? browser->selection->map->dso : NULL; 929 dso = browser->selection->map ? browser->selection->map->dso : NULL;
900 930
901 if (es.reason == NEWT_EXIT_HOTKEY) { 931 if (es.reason == NEWT_EXIT_HOTKEY) {
902 if (es.u.key == NEWT_KEY_F1) 932 key = es.u.key;
933
934 switch (key) {
935 case NEWT_KEY_F1:
903 goto do_help; 936 goto do_help;
937 case NEWT_KEY_TAB:
938 case NEWT_KEY_UNTAB:
939 /*
940 * Exit the browser, let hists__browser_tree
941 * go to the next or previous
942 */
943 goto out_free_stack;
944 default:;
945 }
904 946
905 switch (toupper(es.u.key)) { 947 key = toupper(key);
948 switch (key) {
906 case 'A': 949 case 'A':
950 if (browser->selection->map == NULL &&
951 browser->selection->map->dso->annotate_warned)
952 continue;
907 goto do_annotate; 953 goto do_annotate;
908 case 'D': 954 case 'D':
909 goto zoom_dso; 955 goto zoom_dso;
@@ -922,14 +968,14 @@ do_help:
922 continue; 968 continue;
923 default:; 969 default:;
924 } 970 }
925 if (toupper(es.u.key) == 'Q' || 971 if (is_exit_key(key)) {
926 es.u.key == CTRL('c')) 972 if (key == NEWT_KEY_ESCAPE) {
927 break; 973 if (dialog_yesno("Do you really want to exit?"))
928 if (es.u.key == NEWT_KEY_ESCAPE) { 974 break;
929 if (dialog_yesno("Do you really want to exit?")) 975 else
976 continue;
977 } else
930 break; 978 break;
931 else
932 continue;
933 } 979 }
934 980
935 if (es.u.key == NEWT_KEY_LEFT) { 981 if (es.u.key == NEWT_KEY_LEFT) {
@@ -947,6 +993,7 @@ do_help:
947 } 993 }
948 994
949 if (browser->selection->sym != NULL && 995 if (browser->selection->sym != NULL &&
996 !browser->selection->map->dso->annotate_warned &&
950 asprintf(&options[nr_options], "Annotate %s", 997 asprintf(&options[nr_options], "Annotate %s",
951 browser->selection->sym->name) > 0) 998 browser->selection->sym->name) > 0)
952 annotate = nr_options++; 999 annotate = nr_options++;
@@ -981,6 +1028,7 @@ do_help:
981 struct hist_entry *he; 1028 struct hist_entry *he;
982do_annotate: 1029do_annotate:
983 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) { 1030 if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
1031 browser->selection->map->dso->annotate_warned = 1;
984 ui_helpline__puts("No vmlinux file found, can't " 1032 ui_helpline__puts("No vmlinux file found, can't "
985 "annotate with just a " 1033 "annotate with just a "
986 "kallsyms file"); 1034 "kallsyms file");
@@ -991,7 +1039,7 @@ do_annotate:
991 if (he == NULL) 1039 if (he == NULL)
992 continue; 1040 continue;
993 1041
994 hist_entry__annotate_browser(he); 1042 hist_entry__tui_annotate(he);
995 } else if (choice == zoom_dso) { 1043 } else if (choice == zoom_dso) {
996zoom_dso: 1044zoom_dso:
997 if (dso_filter) { 1045 if (dso_filter) {
@@ -1008,7 +1056,7 @@ zoom_out_dso:
1008 pstack__push(fstack, &dso_filter); 1056 pstack__push(fstack, &dso_filter);
1009 } 1057 }
1010 hists__filter_by_dso(self, dso_filter); 1058 hists__filter_by_dso(self, dso_filter);
1011 hist_browser__title(msg, sizeof(msg), input_name, 1059 hist_browser__title(msg, sizeof(msg), ev_name,
1012 dso_filter, thread_filter); 1060 dso_filter, thread_filter);
1013 if (hist_browser__populate(browser, self, msg) < 0) 1061 if (hist_browser__populate(browser, self, msg) < 0)
1014 goto out; 1062 goto out;
@@ -1027,18 +1075,49 @@ zoom_out_thread:
1027 pstack__push(fstack, &thread_filter); 1075 pstack__push(fstack, &thread_filter);
1028 } 1076 }
1029 hists__filter_by_thread(self, thread_filter); 1077 hists__filter_by_thread(self, thread_filter);
1030 hist_browser__title(msg, sizeof(msg), input_name, 1078 hist_browser__title(msg, sizeof(msg), ev_name,
1031 dso_filter, thread_filter); 1079 dso_filter, thread_filter);
1032 if (hist_browser__populate(browser, self, msg) < 0) 1080 if (hist_browser__populate(browser, self, msg) < 0)
1033 goto out; 1081 goto out;
1034 } 1082 }
1035 } 1083 }
1036 err = 0;
1037out_free_stack: 1084out_free_stack:
1038 pstack__delete(fstack); 1085 pstack__delete(fstack);
1039out: 1086out:
1040 hist_browser__delete(browser); 1087 hist_browser__delete(browser);
1041 return err; 1088 return key;
1089}
1090
1091int hists__tui_browse_tree(struct rb_root *self, const char *help)
1092{
1093 struct rb_node *first = rb_first(self), *nd = first, *next;
1094 int key = 0;
1095
1096 while (nd) {
1097 struct hists *hists = rb_entry(nd, struct hists, rb_node);
1098 const char *ev_name = __event_name(hists->type, hists->config);
1099
1100 key = hists__browse(hists, help, ev_name);
1101
1102 if (is_exit_key(key))
1103 break;
1104
1105 switch (key) {
1106 case NEWT_KEY_TAB:
1107 next = rb_next(nd);
1108 if (next)
1109 nd = next;
1110 break;
1111 case NEWT_KEY_UNTAB:
1112 if (nd == first)
1113 continue;
1114 nd = rb_prev(nd);
1115 default:
1116 break;
1117 }
1118 }
1119
1120 return key;
1042} 1121}
1043 1122
1044static struct newtPercentTreeColors { 1123static struct newtPercentTreeColors {
@@ -1058,10 +1137,13 @@ static struct newtPercentTreeColors {
1058void setup_browser(void) 1137void setup_browser(void)
1059{ 1138{
1060 struct newtPercentTreeColors *c = &defaultPercentTreeColors; 1139 struct newtPercentTreeColors *c = &defaultPercentTreeColors;
1061 if (!isatty(1)) 1140
1141 if (!isatty(1) || !use_browser || dump_trace) {
1142 setup_pager();
1062 return; 1143 return;
1144 }
1063 1145
1064 use_browser = true; 1146 use_browser = 1;
1065 newtInit(); 1147 newtInit();
1066 newtCls(); 1148 newtCls();
1067 ui_helpline__puts(" "); 1149 ui_helpline__puts(" ");
@@ -1074,7 +1156,7 @@ void setup_browser(void)
1074 1156
1075void exit_browser(bool wait_for_ok) 1157void exit_browser(bool wait_for_ok)
1076{ 1158{
1077 if (use_browser) { 1159 if (use_browser > 0) {
1078 if (wait_for_ok) { 1160 if (wait_for_ok) {
1079 char title[] = "Fatal Error", ok[] = "Ok"; 1161 char title[] = "Fatal Error", ok[] = "Ok";
1080 newtWinMessage(title, ok, browser__last_msg); 1162 newtWinMessage(title, ok, browser__last_msg);