diff options
| -rw-r--r-- | tools/perf/builtin-report.c | 60 | ||||
| -rw-r--r-- | tools/perf/util/hist.h | 14 | ||||
| -rw-r--r-- | tools/perf/util/newt.c | 74 |
3 files changed, 108 insertions, 40 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index a7b8760e401c..359205782964 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -288,6 +288,38 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self, | |||
| 288 | return ret + fprintf(fp, "\n#\n"); | 288 | return ret + fprintf(fp, "\n#\n"); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | static int hists__tty_browse_tree(struct rb_root *tree, const char *help) | ||
| 292 | { | ||
| 293 | struct rb_node *next = rb_first(tree); | ||
| 294 | |||
| 295 | while (next) { | ||
| 296 | struct hists *hists = rb_entry(next, struct hists, rb_node); | ||
| 297 | const char *evname = NULL; | ||
| 298 | |||
| 299 | if (rb_first(&hists->entries) != rb_last(&hists->entries)) | ||
| 300 | evname = __event_name(hists->type, hists->config); | ||
| 301 | |||
| 302 | hists__fprintf_nr_sample_events(hists, evname, stdout); | ||
| 303 | hists__fprintf(hists, NULL, false, stdout); | ||
| 304 | fprintf(stdout, "\n\n"); | ||
| 305 | next = rb_next(&hists->rb_node); | ||
| 306 | } | ||
| 307 | |||
| 308 | if (sort_order == default_sort_order && | ||
| 309 | parent_pattern == default_parent_pattern) { | ||
| 310 | fprintf(stdout, "#\n# (%s)\n#\n", help); | ||
| 311 | |||
| 312 | if (show_threads) { | ||
| 313 | bool style = !strcmp(pretty_printing_style, "raw"); | ||
| 314 | perf_read_values_display(stdout, &show_threads_values, | ||
| 315 | style); | ||
| 316 | perf_read_values_destroy(&show_threads_values); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 291 | static int __cmd_report(void) | 323 | static int __cmd_report(void) |
| 292 | { | 324 | { |
| 293 | int ret = -EINVAL; | 325 | int ret = -EINVAL; |
| @@ -330,34 +362,14 @@ static int __cmd_report(void) | |||
| 330 | hists = rb_entry(next, struct hists, rb_node); | 362 | hists = rb_entry(next, struct hists, rb_node); |
| 331 | hists__collapse_resort(hists); | 363 | hists__collapse_resort(hists); |
| 332 | hists__output_resort(hists); | 364 | hists__output_resort(hists); |
| 333 | if (use_browser > 0) | ||
| 334 | hists__browse(hists, help, input_name); | ||
| 335 | else { | ||
| 336 | const char *evname = NULL; | ||
| 337 | if (rb_first(&session->hists.entries) != | ||
| 338 | rb_last(&session->hists.entries)) | ||
| 339 | evname = __event_name(hists->type, hists->config); | ||
| 340 | |||
| 341 | hists__fprintf_nr_sample_events(hists, evname, stdout); | ||
| 342 | |||
| 343 | hists__fprintf(hists, NULL, false, stdout); | ||
| 344 | fprintf(stdout, "\n\n"); | ||
| 345 | } | ||
| 346 | |||
| 347 | next = rb_next(&hists->rb_node); | 365 | next = rb_next(&hists->rb_node); |
| 348 | } | 366 | } |
| 349 | 367 | ||
| 350 | if (use_browser <= 0 && sort_order == default_sort_order && | 368 | if (use_browser > 0) |
| 351 | parent_pattern == default_parent_pattern) { | 369 | hists__tui_browse_tree(&session->hists_tree, help); |
| 352 | fprintf(stdout, "#\n# (%s)\n#\n", help); | 370 | else |
| 371 | hists__tty_browse_tree(&session->hists_tree, help); | ||
| 353 | 372 | ||
| 354 | if (show_threads) { | ||
| 355 | bool style = !strcmp(pretty_printing_style, "raw"); | ||
| 356 | perf_read_values_display(stdout, &show_threads_values, | ||
| 357 | style); | ||
| 358 | perf_read_values_destroy(&show_threads_values); | ||
| 359 | } | ||
| 360 | } | ||
| 361 | out_delete: | 373 | out_delete: |
| 362 | perf_session__delete(session); | 374 | perf_session__delete(session); |
| 363 | return ret; | 375 | return ret; |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 2d5203fedb20..83fa33a7b38b 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -98,10 +98,17 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread); | |||
| 98 | #ifdef NO_NEWT_SUPPORT | 98 | #ifdef NO_NEWT_SUPPORT |
| 99 | static inline int hists__browse(struct hists *self __used, | 99 | static inline int hists__browse(struct hists *self __used, |
| 100 | const char *helpline __used, | 100 | const char *helpline __used, |
| 101 | const char *input_name __used) | 101 | const char *ev_name __used) |
| 102 | { | 102 | { |
| 103 | return 0; | 103 | return 0; |
| 104 | } | 104 | } |
| 105 | |||
| 106 | static inline int hists__tui_browse_tree(struct rb_root *self __used, | ||
| 107 | const char *help __used) | ||
| 108 | { | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 105 | static inline int hist_entry__tui_annotate(struct hist_entry *self __used) | 112 | static inline int hist_entry__tui_annotate(struct hist_entry *self __used) |
| 106 | { | 113 | { |
| 107 | return 0; | 114 | return 0; |
| @@ -111,9 +118,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used) | |||
| 111 | #else | 118 | #else |
| 112 | #include <newt.h> | 119 | #include <newt.h> |
| 113 | int hists__browse(struct hists *self, const char *helpline, | 120 | int hists__browse(struct hists *self, const char *helpline, |
| 114 | const char *input_name); | 121 | const char *ev_name); |
| 115 | int hist_entry__tui_annotate(struct hist_entry *self); | 122 | int hist_entry__tui_annotate(struct hist_entry *self); |
| 123 | |||
| 116 | #define KEY_LEFT NEWT_KEY_LEFT | 124 | #define KEY_LEFT NEWT_KEY_LEFT |
| 117 | #define KEY_RIGHT NEWT_KEY_RIGHT | 125 | #define KEY_RIGHT NEWT_KEY_RIGHT |
| 126 | |||
| 127 | int hists__tui_browse_tree(struct rb_root *self, const char *help); | ||
| 118 | #endif | 128 | #endif |
| 119 | #endif /* __PERF_HIST_H */ | 129 | #endif /* __PERF_HIST_H */ |
diff --git a/tools/perf/util/newt.c b/tools/perf/util/newt.c index ffd04720b754..d54c540f49db 100644 --- a/tools/perf/util/newt.c +++ b/tools/perf/util/newt.c | |||
| @@ -842,6 +842,8 @@ static int hist_browser__populate(struct hist_browser *self, struct hists *hists | |||
| 842 | newtFormAddHotKey(self->form, 'h'); | 842 | newtFormAddHotKey(self->form, 'h'); |
| 843 | newtFormAddHotKey(self->form, NEWT_KEY_F1); | 843 | newtFormAddHotKey(self->form, NEWT_KEY_F1); |
| 844 | 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); | ||
| 845 | newtFormAddComponents(self->form, self->tree, NULL); | 847 | newtFormAddComponents(self->form, self->tree, NULL); |
| 846 | self->selection = newt__symbol_tree_get_current(self->tree); | 848 | self->selection = newt__symbol_tree_get_current(self->tree); |
| 847 | 849 | ||
| @@ -873,7 +875,7 @@ static struct thread *hist_browser__selected_thread(struct hist_browser *self) | |||
| 873 | return he ? he->thread : NULL; | 875 | return he ? he->thread : NULL; |
| 874 | } | 876 | } |
| 875 | 877 | ||
| 876 | static int hist_browser__title(char *bf, size_t size, const char *input_name, | 878 | static int hist_browser__title(char *bf, size_t size, const char *ev_name, |
| 877 | const struct dso *dso, const struct thread *thread) | 879 | const struct dso *dso, const struct thread *thread) |
| 878 | { | 880 | { |
| 879 | int printed = 0; | 881 | int printed = 0; |
| @@ -887,18 +889,18 @@ static int hist_browser__title(char *bf, size_t size, const char *input_name, | |||
| 887 | printed += snprintf(bf + printed, size - printed, | 889 | printed += snprintf(bf + printed, size - printed, |
| 888 | "%sDSO: %s", thread ? " " : "", | 890 | "%sDSO: %s", thread ? " " : "", |
| 889 | dso->short_name); | 891 | dso->short_name); |
| 890 | return printed ?: snprintf(bf, size, "Report: %s", input_name); | 892 | return printed ?: snprintf(bf, size, "Event: %s", ev_name); |
| 891 | } | 893 | } |
| 892 | 894 | ||
| 893 | int hists__browse(struct hists *self, const char *helpline, const char *input_name) | 895 | int hists__browse(struct hists *self, const char *helpline, const char *ev_name) |
| 894 | { | 896 | { |
| 895 | struct hist_browser *browser = hist_browser__new(); | 897 | struct hist_browser *browser = hist_browser__new(); |
| 896 | struct pstack *fstack = pstack__new(2); | 898 | struct pstack *fstack; |
| 897 | const struct thread *thread_filter = NULL; | 899 | const struct thread *thread_filter = NULL; |
| 898 | const struct dso *dso_filter = NULL; | 900 | const struct dso *dso_filter = NULL; |
| 899 | struct newtExitStruct es; | 901 | struct newtExitStruct es; |
| 900 | char msg[160]; | 902 | char msg[160]; |
| 901 | int err = -1; | 903 | int key = -1; |
| 902 | 904 | ||
| 903 | if (browser == NULL) | 905 | if (browser == NULL) |
| 904 | return -1; | 906 | return -1; |
| @@ -909,7 +911,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na | |||
| 909 | 911 | ||
| 910 | ui_helpline__push(helpline); | 912 | ui_helpline__push(helpline); |
| 911 | 913 | ||
| 912 | hist_browser__title(msg, sizeof(msg), input_name, | 914 | hist_browser__title(msg, sizeof(msg), ev_name, |
| 913 | dso_filter, thread_filter); | 915 | dso_filter, thread_filter); |
| 914 | if (hist_browser__populate(browser, self, msg) < 0) | 916 | if (hist_browser__populate(browser, self, msg) < 0) |
| 915 | goto out_free_stack; | 917 | goto out_free_stack; |
| @@ -927,10 +929,23 @@ int hists__browse(struct hists *self, const char *helpline, const char *input_na | |||
| 927 | dso = browser->selection->map ? browser->selection->map->dso : NULL; | 929 | dso = browser->selection->map ? browser->selection->map->dso : NULL; |
| 928 | 930 | ||
| 929 | if (es.reason == NEWT_EXIT_HOTKEY) { | 931 | if (es.reason == NEWT_EXIT_HOTKEY) { |
| 930 | if (es.u.key == NEWT_KEY_F1) | 932 | key = es.u.key; |
| 933 | |||
| 934 | switch (key) { | ||
| 935 | case NEWT_KEY_F1: | ||
| 931 | 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 | } | ||
| 932 | 946 | ||
| 933 | switch (toupper(es.u.key)) { | 947 | key = toupper(key); |
| 948 | switch (key) { | ||
| 934 | case 'A': | 949 | case 'A': |
| 935 | if (browser->selection->map == NULL && | 950 | if (browser->selection->map == NULL && |
| 936 | browser->selection->map->dso->annotate_warned) | 951 | browser->selection->map->dso->annotate_warned) |
| @@ -953,8 +968,8 @@ do_help: | |||
| 953 | continue; | 968 | continue; |
| 954 | default:; | 969 | default:; |
| 955 | } | 970 | } |
| 956 | if (is_exit_key(es.u.key)) { | 971 | if (is_exit_key(key)) { |
| 957 | if (es.u.key == NEWT_KEY_ESCAPE) { | 972 | if (key == NEWT_KEY_ESCAPE) { |
| 958 | if (dialog_yesno("Do you really want to exit?")) | 973 | if (dialog_yesno("Do you really want to exit?")) |
| 959 | break; | 974 | break; |
| 960 | else | 975 | else |
| @@ -1041,7 +1056,7 @@ zoom_out_dso: | |||
| 1041 | pstack__push(fstack, &dso_filter); | 1056 | pstack__push(fstack, &dso_filter); |
| 1042 | } | 1057 | } |
| 1043 | hists__filter_by_dso(self, dso_filter); | 1058 | hists__filter_by_dso(self, dso_filter); |
| 1044 | hist_browser__title(msg, sizeof(msg), input_name, | 1059 | hist_browser__title(msg, sizeof(msg), ev_name, |
| 1045 | dso_filter, thread_filter); | 1060 | dso_filter, thread_filter); |
| 1046 | if (hist_browser__populate(browser, self, msg) < 0) | 1061 | if (hist_browser__populate(browser, self, msg) < 0) |
| 1047 | goto out; | 1062 | goto out; |
| @@ -1060,18 +1075,49 @@ zoom_out_thread: | |||
| 1060 | pstack__push(fstack, &thread_filter); | 1075 | pstack__push(fstack, &thread_filter); |
| 1061 | } | 1076 | } |
| 1062 | hists__filter_by_thread(self, thread_filter); | 1077 | hists__filter_by_thread(self, thread_filter); |
| 1063 | hist_browser__title(msg, sizeof(msg), input_name, | 1078 | hist_browser__title(msg, sizeof(msg), ev_name, |
| 1064 | dso_filter, thread_filter); | 1079 | dso_filter, thread_filter); |
| 1065 | if (hist_browser__populate(browser, self, msg) < 0) | 1080 | if (hist_browser__populate(browser, self, msg) < 0) |
| 1066 | goto out; | 1081 | goto out; |
| 1067 | } | 1082 | } |
| 1068 | } | 1083 | } |
| 1069 | err = 0; | ||
| 1070 | out_free_stack: | 1084 | out_free_stack: |
| 1071 | pstack__delete(fstack); | 1085 | pstack__delete(fstack); |
| 1072 | out: | 1086 | out: |
| 1073 | hist_browser__delete(browser); | 1087 | hist_browser__delete(browser); |
| 1074 | return err; | 1088 | return key; |
| 1089 | } | ||
| 1090 | |||
| 1091 | int 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; | ||
| 1075 | } | 1121 | } |
| 1076 | 1122 | ||
| 1077 | static struct newtPercentTreeColors { | 1123 | static struct newtPercentTreeColors { |
