From 81cce8de9437be9234f651be1f03e596c1b1a79a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 Oct 2011 19:11:32 -0300 Subject: perf browsers: Add live mode to the hists, annotate browsers This allows passing a timer to be run periodically, which will update the hists tree that then gers refreshed on the screen, just like the Live mode (symbol entries, annotation) we already have in 'perf top --tui'. Will be used by the new hist_entry/hists based 'top' tool. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-2r44qd8oe4sagzcgoikl8qzc@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browsers/annotate.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 0229723aceb..76c1d083aa9 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -164,7 +164,8 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, } static int annotate_browser__run(struct annotate_browser *self, int evidx, - int refresh) + void(*timer)(void *arg) __used, void *arg __used, + int delay_secs) { struct rb_node *nd = NULL; struct symbol *sym = self->b.priv; @@ -189,13 +190,13 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, nd = self->curr_hot; - if (refresh != 0) - newtFormSetTimer(self->b.form, refresh); + if (delay_secs != 0) + newtFormSetTimer(self->b.form, delay_secs * 1000); while (1) { key = ui_browser__run(&self->b); - if (refresh != 0) { + if (delay_secs != 0) { annotate_browser__calc_percent(self, evidx); /* * Current line focus got out of the list of most active @@ -212,7 +213,10 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, * FIXME we need to check if it was * es.reason == NEWT_EXIT_TIMER */ - if (refresh != 0) + if (timer != NULL) + timer(arg); + + if (delay_secs != 0) symbol__annotate_decay_histogram(sym, evidx); continue; case NEWT_KEY_TAB: @@ -246,13 +250,16 @@ out: return key; } -int hist_entry__tui_annotate(struct hist_entry *he, int evidx) +int hist_entry__tui_annotate(struct hist_entry *he, int evidx, + void(*timer)(void *arg), void *arg, int delay_secs) { - return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0); + return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, + timer, arg, delay_secs); } int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, - int refresh) + void(*timer)(void *arg), void *arg, + int delay_secs) { struct objdump_line *pos, *n; struct annotation *notes; @@ -293,7 +300,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, browser.b.entries = ¬es->src->source, browser.b.width += 18; /* Percentage */ - ret = annotate_browser__run(&browser, evidx, refresh); + ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs); list_for_each_entry_safe(pos, n, ¬es->src->source, node) { list_del(&pos->node); objdump_line__free(pos); -- cgit v1.2.3-70-g09d2 From 34958544b3da17e98d98d7b872c6516995ad66bb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 5 Oct 2011 19:35:54 -0300 Subject: perf annotate browser: Allow navigation to called functions I.e. when in the annotate TUI window, if Enter is pressed over an assembly line with a 'callq' it will try to open another TUI window with that symbol. This is just a proof of concept and works only on x86_64, more work is needed to support kernel modules, userland, other arches, etc, but should already be useful as-is. Suggested-by: Ingo Molnar Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-opyvskw5na3qdmkv8vxi3zbr@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 9 +++-- tools/perf/util/annotate.h | 2 +- tools/perf/util/hist.h | 4 +- tools/perf/util/ui/browsers/annotate.c | 69 ++++++++++++++++++++++++++++------ tools/perf/util/ui/browsers/hists.c | 20 ++++++---- 5 files changed, 79 insertions(+), 25 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 39e3d382b2d..24db9d2db7b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -114,7 +114,8 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx) print_line, full_paths, 0, 0); } -static void hists__find_annotations(struct hists *self, int evidx) +static void hists__find_annotations(struct hists *self, int evidx, + int nr_events) { struct rb_node *nd = rb_first(&self->entries), *next; int key = KEY_RIGHT; @@ -137,7 +138,8 @@ find_next: } if (use_browser > 0) { - key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0); + key = hist_entry__tui_annotate(he, evidx, nr_events, + NULL, NULL, 0); switch (key) { case KEY_RIGHT: next = rb_next(nd); @@ -215,7 +217,8 @@ static int __cmd_annotate(void) total_nr_samples += nr_samples; hists__collapse_resort(hists); hists__output_resort(hists); - hists__find_annotations(hists, pos->idx); + hists__find_annotations(hists, pos->idx, + session->evlist->nr_entries); } } diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index aafbc7e9a9b..d9072523d34 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -99,7 +99,7 @@ static inline int symbol__tui_annotate(struct symbol *sym __used, } #else int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, - void(*timer)(void *arg), void *arg, + int nr_events, void(*timer)(void *arg), void *arg, int delay_secs); #endif diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f87677bfaff..7ea1e560e00 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -110,7 +110,7 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, } static inline int hist_entry__tui_annotate(struct hist_entry *self __used, - int evidx __used, + int evidx __used, int nr_events __used, void(*timer)(void *arg) __used, void *arg __used, int delay_secs __used); { @@ -120,7 +120,7 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used, #define KEY_RIGHT -2 #else #include -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, +int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, void(*timer)(void *arg), void *arg, int delay_secs); #define KEY_LEFT NEWT_KEY_LEFT diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 76c1d083aa9..77421bab8fd 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -20,6 +20,7 @@ struct annotate_browser { struct ui_browser b; struct rb_root entries; struct rb_node *curr_hot; + struct objdump_line *selection; }; struct objdump_line_rb_node { @@ -36,6 +37,7 @@ struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self) static void annotate_browser__write(struct ui_browser *self, void *entry, int row) { + struct annotate_browser *ab = container_of(self, struct annotate_browser, b); struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); bool current_entry = ui_browser__is_current_entry(self, row); int width = self->width; @@ -58,6 +60,8 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro if (!current_entry) ui_browser__set_color(self, HE_COLORSET_CODE); + else + ab->selection = ol; } static double objdump_line__calc_percent(struct objdump_line *self, @@ -141,7 +145,8 @@ static void annotate_browser__set_top(struct annotate_browser *self, static void annotate_browser__calc_percent(struct annotate_browser *browser, int evidx) { - struct symbol *sym = browser->b.priv; + struct map_symbol *ms = browser->b.priv; + struct symbol *sym = ms->sym; struct annotation *notes = symbol__annotation(sym); struct objdump_line *pos; @@ -164,17 +169,18 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, } static int annotate_browser__run(struct annotate_browser *self, int evidx, - void(*timer)(void *arg) __used, void *arg __used, - int delay_secs) + int nr_events, void(*timer)(void *arg), + void *arg, int delay_secs) { struct rb_node *nd = NULL; - struct symbol *sym = self->b.priv; + struct map_symbol *ms = self->b.priv; + struct symbol *sym = ms->sym; /* * RIGHT To allow builtin-annotate to cycle thru multiple symbols by * examining the exit key for this function. */ int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB, - NEWT_KEY_RIGHT, 0 }; + NEWT_KEY_RIGHT, NEWT_KEY_ENTER, 0 }; int key; if (ui_browser__show(&self->b, sym->name, @@ -238,6 +244,42 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, case 'H': nd = self->curr_hot; break; + case NEWT_KEY_ENTER: + if (self->selection != NULL) { + char *s = strstr(self->selection->line, "callq "); + struct annotation *notes; + struct symbol *target; + u64 ip; + + if (s == NULL) + continue; + + s = strchr(s, ' '); + if (s++ == NULL) + continue; + + ip = strtoull(s, NULL, 16); + ip = ms->map->map_ip(ms->map, ip); + target = map__find_symbol(ms->map, ip, NULL); + if (target == NULL) + continue; + + notes = symbol__annotation(target); + pthread_mutex_lock(¬es->lock); + + if (notes->src == NULL && + symbol__alloc_hist(target, nr_events) < 0) { + pthread_mutex_unlock(¬es->lock); + ui__warning("Not enough memory for annotating '%s' symbol!\n", + target->name); + continue; + } + + pthread_mutex_unlock(¬es->lock); + symbol__tui_annotate(target, ms->map, evidx, nr_events, + timer, arg, delay_secs); + } + break; default: goto out; } @@ -250,25 +292,29 @@ out: return key; } -int hist_entry__tui_annotate(struct hist_entry *he, int evidx, +int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, void(*timer)(void *arg), void *arg, int delay_secs) { - return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, + return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, nr_events, timer, arg, delay_secs); } int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, - void(*timer)(void *arg), void *arg, - int delay_secs) + int nr_events, void(*timer)(void *arg), void *arg, + int delay_secs) { struct objdump_line *pos, *n; struct annotation *notes; + struct map_symbol ms = { + .map = map, + .sym = sym, + }; struct annotate_browser browser = { .b = { .refresh = ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = annotate_browser__write, - .priv = sym, + .priv = &ms, }, }; int ret; @@ -300,7 +346,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, browser.b.entries = ¬es->src->source, browser.b.width += 18; /* Percentage */ - ret = annotate_browser__run(&browser, evidx, timer, arg, delay_secs); + ret = annotate_browser__run(&browser, evidx, nr_events, + timer, arg, delay_secs); list_for_each_entry_safe(pos, n, ¬es->src->source, node) { list_del(&pos->node); objdump_line__free(pos); diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 6244d19bd1f..f0515cbabda 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -825,7 +825,7 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size, return printed; } -static int perf_evsel__hists_browse(struct perf_evsel *evsel, +static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, const char *helpline, const char *ev_name, bool left_exits, void(*timer)(void *arg), void *arg, @@ -968,7 +968,7 @@ do_annotate: if (he == NULL) continue; - hist_entry__tui_annotate(he, evsel->idx, + hist_entry__tui_annotate(he, evsel->idx, nr_events, timer, arg, delay_secs); } else if (choice == browse_map) map__browse(browser->selection->map); @@ -1042,7 +1042,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser, menu->selection = evsel; } -static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help, +static int perf_evsel_menu__run(struct perf_evsel_menu *menu, + int nr_events, const char *help, void(*timer)(void *arg), void *arg, int delay_secs) { int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, }; @@ -1077,8 +1078,9 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help, perf_evlist__set_selected(evlist, pos); browse_hists: ev_name = event_name(pos); - key = perf_evsel__hists_browse(pos, help, ev_name, true, - timer, arg, delay_secs); + key = perf_evsel__hists_browse(pos, nr_events, help, + ev_name, true, timer, + arg, delay_secs); ui_browser__show_title(&menu->b, title); break; case NEWT_KEY_LEFT: @@ -1150,7 +1152,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, pos->name = strdup(ev_name); } - return perf_evsel_menu__run(&menu, help, timer, arg, delay_secs); + return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer, + arg, delay_secs); } int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, @@ -1162,8 +1165,9 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, struct perf_evsel *first = list_entry(evlist->entries.next, struct perf_evsel, node); const char *ev_name = event_name(first); - return perf_evsel__hists_browse(first, help, ev_name, false, - timer, arg, delay_secs); + return perf_evsel__hists_browse(first, evlist->nr_entries, help, + ev_name, false, timer, arg, + delay_secs); } return __perf_evlist__tui_browse_hists(evlist, help, -- cgit v1.2.3-70-g09d2 From 234a5375f6e7dee1f8bd5a7a2f5107c1c265ad8e Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 6 Oct 2011 09:45:29 -0300 Subject: perf annotate browser: Use -> to navigate on assembly lines And add better explanations when the line isn't actionable, like non assembly lines and on other instructions. Suggested-by: Ingo Molnar Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-375n844b5wra7lgq08ou153j@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browsers/annotate.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 77421bab8fd..674b55e686f 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -184,8 +184,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, int key; if (ui_browser__show(&self->b, sym->name, - "<-, -> or ESC: exit, TAB/shift+TAB: " - "cycle hottest lines, H: Hottest") < 0) + "<- or ESC: exit, TAB/shift+TAB: " + "cycle hottest lines, H: Hottest, -> Line action") < 0) return -1; ui_browser__add_exit_keys(&self->b, exit_keys); @@ -245,24 +245,39 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, nd = self->curr_hot; break; case NEWT_KEY_ENTER: - if (self->selection != NULL) { + case NEWT_KEY_RIGHT: + if (self->selection == NULL) { + ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); + continue; + } + + if (self->selection->offset == -1) { + ui_helpline__puts("Actions are only available for assembly lines."); + continue; + } else { char *s = strstr(self->selection->line, "callq "); struct annotation *notes; struct symbol *target; u64 ip; - if (s == NULL) + if (s == NULL) { + ui_helpline__puts("Actions are only available for the 'callq' instruction."); continue; + } s = strchr(s, ' '); - if (s++ == NULL) + if (s++ == NULL) { + ui_helpline__puts("Invallid callq instruction."); continue; + } ip = strtoull(s, NULL, 16); ip = ms->map->map_ip(ms->map, ip); target = map__find_symbol(ms->map, ip, NULL); - if (target == NULL) + if (target == NULL) { + ui_helpline__puts("The called function was not found."); continue; + } notes = symbol__annotation(target); pthread_mutex_lock(¬es->lock); -- cgit v1.2.3-70-g09d2 From 3af6e33867b3814a73c3f3ba991a13d7304ad23a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 13 Oct 2011 08:52:46 -0300 Subject: perf ui browser: Handle SIGWINCH To do that we needed to stop using newtForm, as we don't want libnewt to catch the xterm resize signal. Remove some more newt calls and instead use the underlying libslang directly. In time tools/perf will use just libslang. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-h1824yjiru5n2ivz4bseizwj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 21 ++++- tools/perf/perf.c | 24 ++++++ tools/perf/perf.h | 2 + tools/perf/util/ui/browser.c | 137 ++++++++++++++++++++++----------- tools/perf/util/ui/browser.h | 6 +- tools/perf/util/ui/browsers/annotate.c | 5 +- tools/perf/util/ui/browsers/hists.c | 12 +-- tools/perf/util/ui/browsers/map.c | 3 +- tools/perf/util/ui/helpline.h | 2 + 9 files changed, 144 insertions(+), 68 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c5aebf6eb74..de3cb1e00f9 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -585,16 +585,31 @@ static void *display_thread(void *arg __used) tc.c_cc[VMIN] = 0; tc.c_cc[VTIME] = 0; + pthread__unblock_sigwinch(); repeat: delay_msecs = top.delay_secs * 1000; tcsetattr(0, TCSANOW, &tc); /* trash return*/ getc(stdin); - do { + while (1) { print_sym_table(); - } while (!poll(&stdin_poll, 1, delay_msecs) == 1); - + /* + * Either timeout expired or we got an EINTR due to SIGWINCH, + * refresh screen in both cases. + */ + switch (poll(&stdin_poll, 1, delay_msecs)) { + case 0: + continue; + case -1: + if (errno == EINTR) + continue; + /* Fall trhu */ + default: + goto process_hotkey; + } + } +process_hotkey: c = getc(stdin); tcsetattr(0, TCSAFLUSH, &save); diff --git a/tools/perf/perf.c b/tools/perf/perf.c index ec635b7cc8e..73d0cac8b67 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -427,6 +427,24 @@ static void get_debugfs_mntpt(void) debugfs_mntpt[0] = '\0'; } +static void pthread__block_sigwinch(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGWINCH); + pthread_sigmask(SIG_BLOCK, &set, NULL); +} + +void pthread__unblock_sigwinch(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGWINCH); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); +} + int main(int argc, const char **argv) { const char *cmd; @@ -480,6 +498,12 @@ int main(int argc, const char **argv) * time. */ setup_path(); + /* + * Block SIGWINCH notifications so that the thread that wants it can + * unblock and get syscalls like select interrupted instead of waiting + * forever while the signal goes to some other non interested thread. + */ + pthread__block_sigwinch(); while (1) { static int done_help; diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 08b0b5e82a4..914c895510f 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h @@ -183,4 +183,6 @@ struct ip_callchain { extern bool perf_host, perf_guest; extern const char perf_version_string[]; +void pthread__unblock_sigwinch(void); + #endif diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c index 5911bba6385..05a0f61312d 100644 --- a/tools/perf/util/ui/browser.c +++ b/tools/perf/util/ui/browser.c @@ -1,4 +1,7 @@ +#include "../util.h" +#include "../../perf.h" #include "libslang.h" +#include #include "ui.h" #include #include @@ -8,8 +11,8 @@ #include "browser.h" #include "helpline.h" #include "../color.h" -#include "../util.h" -#include + +int newtGetKey(void); static int ui_browser__percent_color(double percent, bool current) { @@ -127,11 +130,8 @@ bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row) void ui_browser__refresh_dimensions(struct ui_browser *self) { - int cols, rows; - newtGetScreenSize(&cols, &rows); - - self->width = cols - 1; - self->height = rows - 2; + self->width = SLtt_Screen_Cols - 1; + self->height = SLtt_Screen_Rows - 2; self->y = 1; self->x = 0; } @@ -142,9 +142,8 @@ void ui_browser__reset_index(struct ui_browser *self) self->seek(self, 0, SEEK_SET); } -void ui_browser__add_exit_key(struct ui_browser *self, int key) +void ui_browser__add_exit_key(struct ui_browser *browser __used, int key __used) { - newtFormAddHotKey(self->form, key); } void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]) @@ -161,7 +160,7 @@ void __ui_browser__show_title(struct ui_browser *browser, const char *title) { SLsmg_gotorc(0, 0); ui_browser__set_color(browser, NEWT_COLORSET_ROOT); - slsmg_write_nstring(title, browser->width); + slsmg_write_nstring(title, browser->width + 1); } void ui_browser__show_title(struct ui_browser *browser, const char *title) @@ -174,57 +173,75 @@ void ui_browser__show_title(struct ui_browser *browser, const char *title) int ui_browser__show(struct ui_browser *self, const char *title, const char *helpline, ...) { + int err; va_list ap; int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP, NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ', NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 }; - if (self->form != NULL) - newtFormDestroy(self->form); - ui_browser__refresh_dimensions(self); - self->form = newtForm(NULL, NULL, 0); - if (self->form == NULL) - return -1; - - self->sb = newtVerticalScrollbar(self->width, 1, self->height, - HE_COLORSET_NORMAL, - HE_COLORSET_SELECTED); - if (self->sb == NULL) - return -1; pthread_mutex_lock(&ui__lock); __ui_browser__show_title(self, title); ui_browser__add_exit_keys(self, keys); - newtFormAddComponent(self->form, self->sb); + self->title = title; + free(self->helpline); + self->helpline = NULL; va_start(ap, helpline); - ui_helpline__vpush(helpline, ap); + err = vasprintf(&self->helpline, helpline, ap); va_end(ap); + if (err > 0) + ui_helpline__push(self->helpline); pthread_mutex_unlock(&ui__lock); - return 0; + return err ? 0 : -1; } -void ui_browser__hide(struct ui_browser *self) +void ui_browser__hide(struct ui_browser *browser __used) { pthread_mutex_lock(&ui__lock); - newtFormDestroy(self->form); - self->form = NULL; ui_helpline__pop(); pthread_mutex_unlock(&ui__lock); } -int ui_browser__refresh(struct ui_browser *self) +static void ui_browser__scrollbar_set(struct ui_browser *browser) +{ + int height = browser->height, h = 0, pct = 0, + col = browser->width, + row = browser->y - 1; + + if (browser->nr_entries > 1) { + pct = ((browser->index * (browser->height - 1)) / + (browser->nr_entries - 1)); + } + + while (h < height) { + ui_browser__gotorc(browser, row++, col); + SLsmg_set_char_set(1); + SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_BOARD_CHAR); + SLsmg_set_char_set(0); + ++h; + } +} + +static int __ui_browser__refresh(struct ui_browser *browser) { int row; + row = browser->refresh(browser); + ui_browser__set_color(browser, HE_COLORSET_NORMAL); + SLsmg_fill_region(browser->y + row, browser->x, + browser->height - row, browser->width, ' '); + ui_browser__scrollbar_set(browser); + + return 0; +} + +int ui_browser__refresh(struct ui_browser *browser) +{ pthread_mutex_lock(&ui__lock); - newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); - row = self->refresh(self); - ui_browser__set_color(self, HE_COLORSET_NORMAL); - SLsmg_fill_region(self->y + row, self->x, - self->height - row, self->width, ' '); + __ui_browser__refresh(browser); pthread_mutex_unlock(&ui__lock); return 0; @@ -253,21 +270,49 @@ void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries) browser->seek(browser, browser->top_idx, SEEK_SET); } -int ui_browser__run(struct ui_browser *self) +int ui_browser__run(struct ui_browser *self, int delay_secs) { - struct newtExitStruct es; + int err, key; + struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; - if (ui_browser__refresh(self) < 0) - return -1; + pthread__unblock_sigwinch(); while (1) { off_t offset; + fd_set read_set; - newtFormRun(self->form, &es); + pthread_mutex_lock(&ui__lock); + err = __ui_browser__refresh(self); + SLsmg_refresh(); + pthread_mutex_unlock(&ui__lock); + if (err < 0) + break; + + FD_ZERO(&read_set); + FD_SET(0, &read_set); + + if (delay_secs) { + timeout.tv_sec = delay_secs; + timeout.tv_usec = 0; + } - if (es.reason != NEWT_EXIT_HOTKEY) + err = select(1, &read_set, NULL, NULL, ptimeout); + if (err > 0 && FD_ISSET(0, &read_set)) + key = newtGetKey(); + else if (err == 0) break; - switch (es.u.key) { + else { + pthread_mutex_lock(&ui__lock); + SLtt_get_screen_size(); + SLsmg_reinit_smg(); + pthread_mutex_unlock(&ui__lock); + ui_browser__refresh_dimensions(self); + __ui_browser__show_title(self, self->title); + ui_helpline__puts(self->helpline); + continue; + } + + switch (key) { case NEWT_KEY_DOWN: if (self->index == self->nr_entries - 1) break; @@ -324,10 +369,8 @@ int ui_browser__run(struct ui_browser *self) self->seek(self, -offset, SEEK_END); break; default: - return es.u.key; + return key; } - if (ui_browser__refresh(self) < 0) - return -1; } return -1; } @@ -353,13 +396,13 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *self) return row; } -static struct newtPercentTreeColors { +static struct ui_browser__colors { const char *topColorFg, *topColorBg; const char *mediumColorFg, *mediumColorBg; const char *normalColorFg, *normalColorBg; const char *selColorFg, *selColorBg; const char *codeColorFg, *codeColorBg; -} defaultPercentTreeColors = { +} ui_browser__default_colors = { "red", "lightgray", "green", "lightgray", "black", "lightgray", @@ -369,7 +412,7 @@ static struct newtPercentTreeColors { void ui_browser__init(void) { - struct newtPercentTreeColors *c = &defaultPercentTreeColors; + struct ui_browser__colors *c = &ui_browser__default_colors; sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h index d42be43ac0e..37d56bfe8fe 100644 --- a/tools/perf/util/ui/browser.h +++ b/tools/perf/util/ui/browser.h @@ -2,7 +2,6 @@ #define _PERF_UI_BROWSER_H_ 1 #include -#include #include #include "../types.h" @@ -13,11 +12,12 @@ #define HE_COLORSET_CODE 54 struct ui_browser { - newtComponent form, sb; u64 index, top_idx; void *top, *entries; u16 y, x, width, height; void *priv; + const char *title; + char *helpline; unsigned int (*refresh)(struct ui_browser *self); void (*write)(struct ui_browser *self, void *entry, int row); void (*seek)(struct ui_browser *self, off_t offset, int whence); @@ -40,7 +40,7 @@ int ui_browser__show(struct ui_browser *self, const char *title, const char *helpline, ...); void ui_browser__hide(struct ui_browser *self); int ui_browser__refresh(struct ui_browser *self); -int ui_browser__run(struct ui_browser *self); +int ui_browser__run(struct ui_browser *browser, int delay_secs); void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries); void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence); diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 674b55e686f..1967fbf7399 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -196,11 +196,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, nd = self->curr_hot; - if (delay_secs != 0) - newtFormSetTimer(self->b.form, delay_secs * 1000); - while (1) { - key = ui_browser__run(&self->b); + key = ui_browser__run(&self->b, delay_secs); if (delay_secs != 0) { annotate_browser__calc_percent(self, evidx); diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index fdc3c90696d..603d6ee5a0d 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -301,7 +301,6 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name, void(*timer)(void *arg), void *arg, int delay_secs) { int key; - int delay_msecs = delay_secs * 1000; char title[160]; int sym_exit_keys[] = { 'a', 'h', 'C', 'd', 'E', 't', 0, }; int exit_keys[] = { '?', 'h', 'D', NEWT_KEY_LEFT, NEWT_KEY_RIGHT, @@ -318,15 +317,12 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name, "Press '?' for help on key bindings") < 0) return -1; - if (timer != NULL) - newtFormSetTimer(self->b.form, delay_msecs); - ui_browser__add_exit_keys(&self->b, exit_keys); if (self->has_symbols) ui_browser__add_exit_keys(&self->b, sym_exit_keys); while (1) { - key = ui_browser__run(&self->b); + key = ui_browser__run(&self->b, delay_secs); switch (key) { case -1: @@ -1061,7 +1057,6 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, void(*timer)(void *arg), void *arg, int delay_secs) { int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, }; - int delay_msecs = delay_secs * 1000; struct perf_evlist *evlist = menu->b.priv; struct perf_evsel *pos; const char *ev_name, *title = "Available samples"; @@ -1071,13 +1066,10 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, "ESC: exit, ENTER|->: Browse histograms") < 0) return -1; - if (timer != NULL) - newtFormSetTimer(menu->b.form, delay_msecs); - ui_browser__add_exit_keys(&menu->b, exit_keys); while (1) { - key = ui_browser__run(&menu->b); + key = ui_browser__run(&menu->b, delay_secs); switch (key) { case -1: diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c index 8462bffe20b..499db76bac2 100644 --- a/tools/perf/util/ui/browsers/map.c +++ b/tools/perf/util/ui/browsers/map.c @@ -1,5 +1,6 @@ #include "../libslang.h" #include +#include #include #include #include @@ -112,7 +113,7 @@ static int map_browser__run(struct map_browser *self) ui_browser__add_exit_key(&self->b, '/'); while (1) { - key = ui_browser__run(&self->b); + key = ui_browser__run(&self->b, 0); if (verbose && key == '/') map_browser__search(self); diff --git a/tools/perf/util/ui/helpline.h b/tools/perf/util/ui/helpline.h index ab6028d0c40..80997575908 100644 --- a/tools/perf/util/ui/helpline.h +++ b/tools/perf/util/ui/helpline.h @@ -1,6 +1,8 @@ #ifndef _PERF_UI_HELPLINE_H_ #define _PERF_UI_HELPLINE_H_ 1 +#include + void ui_helpline__init(void); void ui_helpline__pop(void); void ui_helpline__push(const char *msg); -- cgit v1.2.3-70-g09d2 From ed7e5662ddff6a60bdae830ff65547c2eeed6f9a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 13 Oct 2011 08:31:22 -0300 Subject: perf ui browser: Remove ui_browser__add_exit_keys Users (hist_browser, etc) should just handle all keys, discarding the ones they don't handle. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-fjouann12v2k58t6vdd2wawb@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browser.c | 18 ------------------ tools/perf/util/ui/browser.h | 2 -- tools/perf/util/ui/browsers/annotate.c | 12 ++++-------- tools/perf/util/ui/browsers/hists.c | 28 ++++++++-------------------- tools/perf/util/ui/browsers/map.c | 3 --- 5 files changed, 12 insertions(+), 51 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c index 05a0f61312d..2923c493fb6 100644 --- a/tools/perf/util/ui/browser.c +++ b/tools/perf/util/ui/browser.c @@ -142,20 +142,6 @@ void ui_browser__reset_index(struct ui_browser *self) self->seek(self, 0, SEEK_SET); } -void ui_browser__add_exit_key(struct ui_browser *browser __used, int key __used) -{ -} - -void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]) -{ - int i = 0; - - while (keys[i] && i < 64) { - ui_browser__add_exit_key(self, keys[i]); - ++i; - } -} - void __ui_browser__show_title(struct ui_browser *browser, const char *title) { SLsmg_gotorc(0, 0); @@ -175,16 +161,12 @@ int ui_browser__show(struct ui_browser *self, const char *title, { int err; va_list ap; - int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP, - NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ', - NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 }; ui_browser__refresh_dimensions(self); pthread_mutex_lock(&ui__lock); __ui_browser__show_title(self, title); - ui_browser__add_exit_keys(self, keys); self->title = title; free(self->helpline); self->helpline = NULL; diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h index 37d56bfe8fe..7dd9d6107d1 100644 --- a/tools/perf/util/ui/browser.h +++ b/tools/perf/util/ui/browser.h @@ -32,8 +32,6 @@ void ui_browser__refresh_dimensions(struct ui_browser *self); void ui_browser__reset_index(struct ui_browser *self); void ui_browser__gotorc(struct ui_browser *self, int y, int x); -void ui_browser__add_exit_key(struct ui_browser *self, int key); -void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]); void __ui_browser__show_title(struct ui_browser *browser, const char *title); void ui_browser__show_title(struct ui_browser *browser, const char *title); int ui_browser__show(struct ui_browser *self, const char *title, diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 1967fbf7399..cbefb4fc99c 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -175,12 +175,6 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, struct rb_node *nd = NULL; struct map_symbol *ms = self->b.priv; struct symbol *sym = ms->sym; - /* - * RIGHT To allow builtin-annotate to cycle thru multiple symbols by - * examining the exit key for this function. - */ - int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB, - NEWT_KEY_RIGHT, NEWT_KEY_ENTER, 0 }; int key; if (ui_browser__show(&self->b, sym->name, @@ -188,7 +182,6 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, "cycle hottest lines, H: Hottest, -> Line action") < 0) return -1; - ui_browser__add_exit_keys(&self->b, exit_keys); annotate_browser__calc_percent(self, evidx); if (self->curr_hot) @@ -292,8 +285,11 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, timer, arg, delay_secs); } break; - default: + case 'q': + case CTRL('c'): goto out; + default: + continue; } if (nd != NULL) diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 603d6ee5a0d..662b7217a03 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -302,9 +302,6 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name, { int key; char title[160]; - int sym_exit_keys[] = { 'a', 'h', 'C', 'd', 'E', 't', 0, }; - int exit_keys[] = { '?', 'h', 'D', NEWT_KEY_LEFT, NEWT_KEY_RIGHT, - NEWT_KEY_TAB, NEWT_KEY_UNTAB, NEWT_KEY_ENTER, 0, }; self->b.entries = &self->hists->entries; self->b.nr_entries = self->hists->nr_entries; @@ -317,10 +314,6 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name, "Press '?' for help on key bindings") < 0) return -1; - ui_browser__add_exit_keys(&self->b, exit_keys); - if (self->has_symbols) - ui_browser__add_exit_keys(&self->b, sym_exit_keys); - while (1) { key = ui_browser__run(&self->b, delay_secs); @@ -921,8 +914,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, !ui__dialog_yesno("Do you really want to exit?")) continue; /* Fall thru */ - default: + case 'q': + case CTRL('c'): goto out_free_stack; + default: + continue; } if (!browser->has_symbols) @@ -1056,7 +1052,6 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, int nr_events, const char *help, void(*timer)(void *arg), void *arg, int delay_secs) { - int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, }; struct perf_evlist *evlist = menu->b.priv; struct perf_evsel *pos; const char *ev_name, *title = "Available samples"; @@ -1066,8 +1061,6 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, "ESC: exit, ENTER|->: Browse histograms") < 0) return -1; - ui_browser__add_exit_keys(&menu->b, exit_keys); - while (1) { key = ui_browser__run(&menu->b, delay_secs); @@ -1091,15 +1084,6 @@ browse_hists: break; case NEWT_KEY_LEFT: continue; - case NEWT_KEY_ESCAPE: - if (!ui__dialog_yesno("Do you really want to exit?")) - continue; - /* Fall thru */ - default: - goto out; - } - - switch (key) { case NEWT_KEY_TAB: if (pos->node.next == &evlist->entries) pos = list_entry(evlist->entries.next, struct perf_evsel, node); @@ -1114,6 +1098,10 @@ browse_hists: pos = list_entry(pos->node.prev, struct perf_evsel, node); perf_evlist__set_selected(evlist, pos); goto browse_hists; + case NEWT_KEY_ESCAPE: + if (!ui__dialog_yesno("Do you really want to exit?")) + continue; + /* Fall thru */ case 'q': case CTRL('c'): goto out; diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c index 499db76bac2..6905bcc8be2 100644 --- a/tools/perf/util/ui/browsers/map.c +++ b/tools/perf/util/ui/browsers/map.c @@ -109,9 +109,6 @@ static int map_browser__run(struct map_browser *self) verbose ? "" : "restart with -v to use") < 0) return -1; - if (verbose) - ui_browser__add_exit_key(&self->b, '/'); - while (1) { key = ui_browser__run(&self->b, 0); -- cgit v1.2.3-70-g09d2 From 7296d66aca60a71076a5f0ffab39730e7788590f Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 14 Oct 2011 09:37:38 -0300 Subject: perf annotate browser: Exit when pressing ESC or the left arrow We lost that functionality on ed7e566, restore it. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-z8eb8af2x46x42lgpn1ustid@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browsers/annotate.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index cbefb4fc99c..84315c99928 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -285,6 +285,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, timer, arg, delay_secs); } break; + case NEWT_KEY_LEFT: + case NEWT_KEY_ESCAPE: case 'q': case CTRL('c'): goto out; -- cgit v1.2.3-70-g09d2 From 0361fc25d509be09464dd23c274bd175cc933cc8 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 14 Oct 2011 12:31:21 -0300 Subject: perf annotate browser: Allow toggling the visualization of source code lines Just press 'S' on any assembly line and the source code will be hidden while the current line remains selected. Press 'S' again to show them back. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-efmxm5etouebb7es0kkyqqwa@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browsers/annotate.c | 76 +++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 5 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 84315c99928..eb2712ecb60 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -21,12 +21,16 @@ struct annotate_browser { struct rb_root entries; struct rb_node *curr_hot; struct objdump_line *selection; + int nr_asm_entries; + int nr_entries; + bool hide_src_code; }; struct objdump_line_rb_node { struct rb_node rb_node; double percent; u32 idx; + int idx_asm; }; static inline @@ -35,10 +39,22 @@ struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self) return (struct objdump_line_rb_node *)(self + 1); } +static bool objdump_line__filter(struct ui_browser *browser, void *entry) +{ + struct annotate_browser *ab = container_of(browser, struct annotate_browser, b); + + if (ab->hide_src_code) { + struct objdump_line *ol = list_entry(entry, struct objdump_line, node); + return ol->offset == -1; + } + + return false; +} + static void annotate_browser__write(struct ui_browser *self, void *entry, int row) { struct annotate_browser *ab = container_of(self, struct annotate_browser, b); - struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); + struct objdump_line *ol = list_entry(entry, struct objdump_line, node); bool current_entry = ui_browser__is_current_entry(self, row); int width = self->width; @@ -168,6 +184,45 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser, browser->curr_hot = rb_last(&browser->entries); } +static bool annotate_browser__toggle_source(struct annotate_browser *browser) +{ + struct objdump_line *ol; + struct objdump_line_rb_node *olrb; + off_t offset = browser->b.index - browser->b.top_idx; + + browser->b.seek(&browser->b, offset, SEEK_CUR); + ol = list_entry(browser->b.top, struct objdump_line, node); + olrb = objdump_line__rb(ol); + + if (browser->hide_src_code) { + if (olrb->idx_asm < offset) + offset = olrb->idx; + + browser->b.nr_entries = browser->nr_entries; + browser->hide_src_code = false; + browser->b.seek(&browser->b, -offset, SEEK_CUR); + browser->b.top_idx = olrb->idx - offset; + browser->b.index = olrb->idx; + } else { + if (olrb->idx_asm < 0) { + ui_helpline__puts("Only available for assembly lines."); + browser->b.seek(&browser->b, -offset, SEEK_CUR); + return false; + } + + if (olrb->idx_asm < offset) + offset = olrb->idx_asm; + + browser->b.nr_entries = browser->nr_asm_entries; + browser->hide_src_code = true; + browser->b.seek(&browser->b, -offset, SEEK_CUR); + browser->b.top_idx = olrb->idx_asm - offset; + browser->b.index = olrb->idx_asm; + } + + return true; +} + static int annotate_browser__run(struct annotate_browser *self, int evidx, int nr_events, void(*timer)(void *arg), void *arg, int delay_secs) @@ -175,11 +230,12 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, struct rb_node *nd = NULL; struct map_symbol *ms = self->b.priv; struct symbol *sym = ms->sym; + const char *help = "<-, ESC: exit, TAB/shift+TAB: cycle hottest lines, " + "H: Hottest, -> Line action, S -> Toggle source " + "code view"; int key; - if (ui_browser__show(&self->b, sym->name, - "<- or ESC: exit, TAB/shift+TAB: " - "cycle hottest lines, H: Hottest, -> Line action") < 0) + if (ui_browser__show(&self->b, sym->name, help) < 0) return -1; annotate_browser__calc_percent(self, evidx); @@ -234,6 +290,10 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, case 'H': nd = self->curr_hot; break; + case 'S': + if (annotate_browser__toggle_source(self)) + ui_helpline__puts(help); + continue; case NEWT_KEY_ENTER: case NEWT_KEY_RIGHT: if (self->selection == NULL) { @@ -324,6 +384,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, .refresh = ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = annotate_browser__write, + .filter = objdump_line__filter, .priv = &ms, }, }; @@ -351,9 +412,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, if (browser.b.width < line_len) browser.b.width = line_len; rbpos = objdump_line__rb(pos); - rbpos->idx = browser.b.nr_entries++; + rbpos->idx = browser.nr_entries++; + if (pos->offset != -1) + rbpos->idx_asm = browser.nr_asm_entries++; + else + rbpos->idx_asm = -1; } + browser.b.nr_entries = browser.nr_entries; browser.b.entries = ¬es->src->source, browser.b.width += 18; /* Percentage */ ret = annotate_browser__run(&browser, evidx, nr_events, -- cgit v1.2.3-70-g09d2 From c172f7422c03463a7177e268ffe625c41c42c179 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 18 Oct 2011 14:31:35 -0200 Subject: perf ui browser: Allow initial use without navigation UI elements The selection and scroll bar are really needed only when the user starts navigating, before that it just provide distractions. This also brings the initial screen to look more like the stdio UI, which more people are used to. The new code is flexible enough that menu like browsers can opt out and start with those UI elements. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-jfgok30kkerpfw8wtcltgy6z@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browser.c | 28 +++++++++++++++++++++++----- tools/perf/util/ui/browser.h | 2 ++ tools/perf/util/ui/browsers/annotate.c | 6 ++++++ tools/perf/util/ui/browsers/hists.c | 20 ++++++++------------ 4 files changed, 39 insertions(+), 17 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c index a54b926efe2..dce16ee4364 100644 --- a/tools/perf/util/ui/browser.c +++ b/tools/perf/util/ui/browser.c @@ -14,9 +14,10 @@ int newtGetKey(void); -static int ui_browser__percent_color(double percent, bool current) +static int ui_browser__percent_color(struct ui_browser *browser, + double percent, bool current) { - if (current) + if (current && (!browser->use_navkeypressed || browser->navkeypressed)) return HE_COLORSET_SELECTED; if (percent >= MIN_RED) return HE_COLORSET_TOP; @@ -33,7 +34,7 @@ void ui_browser__set_color(struct ui_browser *self __used, int color) void ui_browser__set_percent_color(struct ui_browser *self, double percent, bool current) { - int color = ui_browser__percent_color(percent, current); + int color = ui_browser__percent_color(self, percent, current); ui_browser__set_color(self, color); } @@ -241,12 +242,18 @@ static void ui_browser__scrollbar_set(struct ui_browser *browser) static int __ui_browser__refresh(struct ui_browser *browser) { int row; + int width = browser->width; row = browser->refresh(browser); ui_browser__set_color(browser, HE_COLORSET_NORMAL); + + if (!browser->use_navkeypressed || browser->navkeypressed) + ui_browser__scrollbar_set(browser); + else + width += 1; + SLsmg_fill_region(browser->y + row, browser->x, - browser->height - row, browser->width, ' '); - ui_browser__scrollbar_set(browser); + browser->height - row, width, ' '); return 0; } @@ -326,6 +333,17 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) continue; } + if (self->use_navkeypressed && !self->navkeypressed) { + if (key == NEWT_KEY_DOWN || key == NEWT_KEY_UP || + key == NEWT_KEY_PGDN || key == NEWT_KEY_PGUP || + key == NEWT_KEY_HOME || key == NEWT_KEY_END || + key == ' ') { + self->navkeypressed = true; + continue; + } else + return key; + } + switch (key) { case NEWT_KEY_DOWN: if (self->index == self->nr_entries - 1) diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h index 351c006dd4b..a2c707d33c5 100644 --- a/tools/perf/util/ui/browser.h +++ b/tools/perf/util/ui/browser.h @@ -23,6 +23,8 @@ struct ui_browser { void (*seek)(struct ui_browser *self, off_t offset, int whence); bool (*filter)(struct ui_browser *self, void *entry); u32 nr_entries; + bool navkeypressed; + bool use_navkeypressed; }; void ui_browser__set_color(struct ui_browser *self, int color); diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index eb2712ecb60..a2c351cf23e 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -69,6 +69,11 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro SLsmg_write_char(':'); slsmg_write_nstring(" ", 8); + + /* The scroll bar isn't being used */ + if (!self->navkeypressed) + width += 1; + if (!*ol->line) slsmg_write_nstring(" ", width - 18); else @@ -386,6 +391,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, .write = annotate_browser__write, .filter = objdump_line__filter, .priv = &ms, + .use_navkeypressed = true, }, }; int ret; diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 873b852e914..2d390b9cb63 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -547,7 +547,7 @@ static int hist_browser__show_entry(struct hist_browser *self, char s[256]; double percent; int printed = 0; - int color, width = self->b.width; + int width = self->b.width; char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(&self->b, row); off_t row_offset = entry->row_offset; @@ -567,22 +567,17 @@ static int hist_browser__show_entry(struct hist_browser *self, 0, false, self->hists->stats.total_period); percent = (entry->period * 100.0) / self->hists->stats.total_period; - color = HE_COLORSET_SELECTED; - if (!current_entry) { - if (percent >= MIN_RED) - color = HE_COLORSET_TOP; - else if (percent >= MIN_GREEN) - color = HE_COLORSET_MEDIUM; - else - color = HE_COLORSET_NORMAL; - } - - ui_browser__set_color(&self->b, color); + ui_browser__set_percent_color(&self->b, percent, current_entry); ui_browser__gotorc(&self->b, row, 0); if (symbol_conf.use_callchain) { slsmg_printf("%c ", folded_sign); width -= 2; } + + /* The scroll bar isn't being used */ + if (!self->b.navkeypressed) + width += 1; + slsmg_write_nstring(s, width); ++row; ++printed; @@ -787,6 +782,7 @@ static struct hist_browser *hist_browser__new(struct hists *hists) self->hists = hists; self->b.refresh = hist_browser__refresh; self->b.seek = ui_browser__hists_seek; + self->b.use_navkeypressed = true, self->has_symbols = sort_sym.list.next != NULL; } -- cgit v1.2.3-70-g09d2 From fe46e64c432d355ab1b5245498d9b75f37d71ac3 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 19 Oct 2011 13:18:13 -0200 Subject: perf annotate browser: Don't change selection line when returning from callq When the user navigates to another annotation browser pressing -> on a 'callq' line, on exit (<-) return to the originating 'callq' line. Reported-by: Ingo Molnar Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-z5vgver0jgevbiicfndqni5g@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/ui/browsers/annotate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index a2c351cf23e..1a12d8fa8e9 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -349,7 +349,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, symbol__tui_annotate(target, ms->map, evidx, nr_events, timer, arg, delay_secs); } - break; + continue; case NEWT_KEY_LEFT: case NEWT_KEY_ESCAPE: case 'q': -- cgit v1.2.3-70-g09d2 From cf9580036a830f9e95f32dbcedfc57ea1697f120 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 20 Oct 2011 16:59:15 -0200 Subject: perf ui browser: Use libslang to read keys Just another step in stopping the use of libnewt in perf. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-uy6s534uqxq8tenh6s3k8ocj@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Makefile | 1 + tools/perf/builtin-annotate.c | 8 ++-- tools/perf/util/hist.h | 9 ++-- tools/perf/util/ui/browser.c | 79 +++++++++++++++++++++++----------- tools/perf/util/ui/browsers/annotate.c | 19 ++++---- tools/perf/util/ui/browsers/hists.c | 33 +++++++------- tools/perf/util/ui/keysyms.h | 25 +++++++++++ tools/perf/util/ui/libslang.h | 2 + tools/perf/util/ui/setup.c | 13 ++++++ 9 files changed, 125 insertions(+), 64 deletions(-) create mode 100644 tools/perf/util/ui/keysyms.h (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 37fe93019bc..b98e3075646 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -472,6 +472,7 @@ else LIB_H += util/ui/browser.h LIB_H += util/ui/browsers/map.h LIB_H += util/ui/helpline.h + LIB_H += util/ui/keysyms.h LIB_H += util/ui/libslang.h LIB_H += util/ui/progress.h LIB_H += util/ui/util.h diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 3ea764a7805..46b4c24f338 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -118,7 +118,7 @@ static void hists__find_annotations(struct hists *self, int evidx, int nr_events) { struct rb_node *nd = rb_first(&self->entries), *next; - int key = KEY_RIGHT; + int key = K_RIGHT; while (nd) { struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); @@ -130,7 +130,7 @@ static void hists__find_annotations(struct hists *self, int evidx, notes = symbol__annotation(he->ms.sym); if (notes->src == NULL) { find_next: - if (key == KEY_LEFT) + if (key == K_LEFT) nd = rb_prev(nd); else nd = rb_next(nd); @@ -141,10 +141,10 @@ find_next: key = hist_entry__tui_annotate(he, evidx, nr_events, NULL, NULL, 0); switch (key) { - case KEY_RIGHT: + case K_RIGHT: next = rb_next(nd); break; - case KEY_LEFT: + case K_LEFT: next = rb_prev(nd); break; default: diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 575bcbc4135..ff93ddc91c5 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -125,16 +125,13 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used, { return 0; } -#define KEY_LEFT -1 -#define KEY_RIGHT -2 +#define K_LEFT -1 +#define K_RIGHT -2 #else -#include +#include "ui/keysyms.h" int hist_entry__tui_annotate(struct hist_entry *he, int evidx, int nr_events, void(*timer)(void *arg), void *arg, int delay_secs); -#define KEY_LEFT NEWT_KEY_LEFT -#define KEY_RIGHT NEWT_KEY_RIGHT - int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, void(*timer)(void *arg), void *arg, int refresh); diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c index 06fc9ebd8d3..5359f371d30 100644 --- a/tools/perf/util/ui/browser.c +++ b/tools/perf/util/ui/browser.c @@ -11,10 +11,9 @@ #include #include "browser.h" #include "helpline.h" +#include "keysyms.h" #include "../color.h" -int newtGetKey(void); - static int ui_browser__percent_color(struct ui_browser *browser, double percent, bool current) { @@ -292,16 +291,55 @@ void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries) browser->seek(browser, browser->top_idx, SEEK_SET); } +static int ui__getch(int delay_secs) +{ + struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; + fd_set read_set; + int err, key; + + FD_ZERO(&read_set); + FD_SET(0, &read_set); + + if (delay_secs) { + timeout.tv_sec = delay_secs; + timeout.tv_usec = 0; + } + + err = select(1, &read_set, NULL, NULL, ptimeout); + + if (err == 0) + return K_TIMER; + + if (err == -1) { + if (errno == EINTR) + return K_RESIZE; + return K_ERROR; + } + + key = SLang_getkey(); + if (key != K_ESC) + return key; + + FD_ZERO(&read_set); + FD_SET(0, &read_set); + timeout.tv_sec = 0; + timeout.tv_usec = 20; + err = select(1, &read_set, NULL, NULL, &timeout); + if (err == 0) + return K_ESC; + + SLang_ungetkey(key); + return SLkp_getkey(); +} + int ui_browser__run(struct ui_browser *self, int delay_secs) { int err, key; - struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL; pthread__unblock_sigwinch(); while (1) { off_t offset; - fd_set read_set; pthread_mutex_lock(&ui__lock); err = __ui_browser__refresh(self); @@ -310,20 +348,9 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) if (err < 0) break; - FD_ZERO(&read_set); - FD_SET(0, &read_set); + key = ui__getch(delay_secs); - if (delay_secs) { - timeout.tv_sec = delay_secs; - timeout.tv_usec = 0; - } - - err = select(1, &read_set, NULL, NULL, ptimeout); - if (err > 0 && FD_ISSET(0, &read_set)) - key = newtGetKey(); - else if (err == 0) - break; - else { + if (key == K_RESIZE) { pthread_mutex_lock(&ui__lock); SLtt_get_screen_size(); SLsmg_reinit_smg(); @@ -335,9 +362,9 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) } if (self->use_navkeypressed && !self->navkeypressed) { - if (key == NEWT_KEY_DOWN || key == NEWT_KEY_UP || - key == NEWT_KEY_PGDN || key == NEWT_KEY_PGUP || - key == NEWT_KEY_HOME || key == NEWT_KEY_END || + if (key == K_DOWN || key == K_UP || + key == K_PGDN || key == K_PGUP || + key == K_HOME || key == K_END || key == ' ') { self->navkeypressed = true; continue; @@ -346,7 +373,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) } switch (key) { - case NEWT_KEY_DOWN: + case K_DOWN: if (self->index == self->nr_entries - 1) break; ++self->index; @@ -355,7 +382,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) self->seek(self, +1, SEEK_CUR); } break; - case NEWT_KEY_UP: + case K_UP: if (self->index == 0) break; --self->index; @@ -364,7 +391,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) self->seek(self, -1, SEEK_CUR); } break; - case NEWT_KEY_PGDN: + case K_PGDN: case ' ': if (self->top_idx + self->height > self->nr_entries - 1) break; @@ -376,7 +403,7 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) self->top_idx += offset; self->seek(self, +offset, SEEK_CUR); break; - case NEWT_KEY_PGUP: + case K_PGUP: if (self->top_idx == 0) break; @@ -389,10 +416,10 @@ int ui_browser__run(struct ui_browser *self, int delay_secs) self->top_idx -= offset; self->seek(self, -offset, SEEK_CUR); break; - case NEWT_KEY_HOME: + case K_HOME: ui_browser__reset_index(self); break; - case NEWT_KEY_END: + case K_END: offset = self->height - 1; if (offset >= self->nr_entries) offset = self->nr_entries - 1; diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 1a12d8fa8e9..4e0cb7fea7d 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -6,6 +6,7 @@ #include "../../sort.h" #include "../../symbol.h" #include +#include static void ui__error_window(const char *fmt, ...) { @@ -265,18 +266,14 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, } switch (key) { - case -1: - /* - * FIXME we need to check if it was - * es.reason == NEWT_EXIT_TIMER - */ + case K_TIMER: if (timer != NULL) timer(arg); if (delay_secs != 0) symbol__annotate_decay_histogram(sym, evidx); continue; - case NEWT_KEY_TAB: + case K_TAB: if (nd != NULL) { nd = rb_prev(nd); if (nd == NULL) @@ -284,7 +281,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, } else nd = self->curr_hot; break; - case NEWT_KEY_UNTAB: + case K_UNTAB: if (nd != NULL) nd = rb_next(nd); if (nd == NULL) @@ -299,8 +296,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, if (annotate_browser__toggle_source(self)) ui_helpline__puts(help); continue; - case NEWT_KEY_ENTER: - case NEWT_KEY_RIGHT: + case K_ENTER: + case K_RIGHT: if (self->selection == NULL) { ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); continue; @@ -350,8 +347,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, timer, arg, delay_secs); } continue; - case NEWT_KEY_LEFT: - case NEWT_KEY_ESCAPE: + case K_LEFT: + case K_ESC: case 'q': case CTRL('c'): goto out; diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index a06e7d936ec..af12e6f1079 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -344,7 +344,7 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name, /* Expand the whole world. */ hist_browser__set_folding(self, true); break; - case NEWT_KEY_ENTER: + case K_ENTER: if (hist_browser__toggle_fold(self)) break; /* fall thru */ @@ -872,8 +872,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, } switch (key) { - case NEWT_KEY_TAB: - case NEWT_KEY_UNTAB: + case K_TAB: + case K_UNTAB: if (nr_events == 1) continue; /* @@ -891,7 +891,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, goto zoom_dso; case 't': goto zoom_thread; - case NEWT_KEY_F1: + case K_F1: case 'h': case '?': ui__help_window("h/?/F1 Show this window\n" @@ -909,11 +909,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, "d Zoom into current DSO\n" "t Zoom into current Thread\n"); continue; - case NEWT_KEY_ENTER: - case NEWT_KEY_RIGHT: + case K_ENTER: + case K_RIGHT: /* menu */ break; - case NEWT_KEY_LEFT: { + case K_LEFT: { const void *top; if (pstack__empty(fstack)) { @@ -931,7 +931,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, goto zoom_out_thread; continue; } - case NEWT_KEY_ESCAPE: + case K_ESC: if (!left_exits && !ui__dialog_yesno("Do you really want to exit?")) continue; @@ -1091,12 +1091,11 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, key = ui_browser__run(&menu->b, delay_secs); switch (key) { - case -1: - /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */ + case K_TIMER: timer(arg); continue; - case NEWT_KEY_RIGHT: - case NEWT_KEY_ENTER: + case K_RIGHT: + case K_ENTER: if (!menu->selection) continue; pos = menu->selection; @@ -1114,19 +1113,19 @@ browse_hists: arg, delay_secs); ui_browser__show_title(&menu->b, title); switch (key) { - case NEWT_KEY_TAB: + case K_TAB: if (pos->node.next == &evlist->entries) pos = list_entry(evlist->entries.next, struct perf_evsel, node); else pos = list_entry(pos->node.next, struct perf_evsel, node); goto browse_hists; - case NEWT_KEY_UNTAB: + case K_UNTAB: if (pos->node.prev == &evlist->entries) pos = list_entry(evlist->entries.prev, struct perf_evsel, node); else pos = list_entry(pos->node.prev, struct perf_evsel, node); goto browse_hists; - case NEWT_KEY_ESCAPE: + case K_ESC: if (!ui__dialog_yesno("Do you really want to exit?")) continue; /* Fall thru */ @@ -1136,9 +1135,9 @@ browse_hists: default: continue; } - case NEWT_KEY_LEFT: + case K_LEFT: continue; - case NEWT_KEY_ESCAPE: + case K_ESC: if (!ui__dialog_yesno("Do you really want to exit?")) continue; /* Fall thru */ diff --git a/tools/perf/util/ui/keysyms.h b/tools/perf/util/ui/keysyms.h new file mode 100644 index 00000000000..3458b198576 --- /dev/null +++ b/tools/perf/util/ui/keysyms.h @@ -0,0 +1,25 @@ +#ifndef _PERF_KEYSYMS_H_ +#define _PERF_KEYSYMS_H_ 1 + +#include "libslang.h" + +#define K_DOWN SL_KEY_DOWN +#define K_END SL_KEY_END +#define K_ENTER '\r' +#define K_ESC 033 +#define K_F1 SL_KEY_F(1) +#define K_HOME SL_KEY_HOME +#define K_LEFT SL_KEY_LEFT +#define K_PGDN SL_KEY_NPAGE +#define K_PGUP SL_KEY_PPAGE +#define K_RIGHT SL_KEY_RIGHT +#define K_TAB '\t' +#define K_UNTAB SL_KEY_UNTAB +#define K_UP SL_KEY_UP + +/* Not really keys */ +#define K_TIMER -1 +#define K_ERROR -2 +#define K_RESIZE -3 + +#endif /* _PERF_KEYSYMS_H_ */ diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/util/ui/libslang.h index 2b63e1c9b18..4d54b6450f5 100644 --- a/tools/perf/util/ui/libslang.h +++ b/tools/perf/util/ui/libslang.h @@ -24,4 +24,6 @@ #define sltt_set_color SLtt_set_color #endif +#define SL_KEY_UNTAB 0x1000 + #endif /* _PERF_UI_SLANG_H_ */ diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c index 5111f1ae044..1e6ba06980c 100644 --- a/tools/perf/util/ui/setup.c +++ b/tools/perf/util/ui/setup.c @@ -18,6 +18,18 @@ static void newt_suspend(void *d __used) newtResume(); } +static int ui__init(void) +{ + int err = SLkp_init(); + + if (err < 0) + goto out; + + SLkp_define_keysym((char *)"^(kB)", SL_KEY_UNTAB); +out: + return err; +} + static void ui__exit(void) { SLtt_set_cursor_visibility(1); @@ -44,6 +56,7 @@ void setup_browser(bool fallback_to_pager) use_browser = 1; newtInit(); + ui__init(); newtSetSuspendCallback(newt_suspend, NULL); ui_helpline__init(); ui_browser__init(); -- cgit v1.2.3-70-g09d2 From ae55795ef2d9ba71d46e4111b87a4d0cde93abea Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 26 Oct 2011 08:00:55 -0200 Subject: perf ui: Reimplement the popup windows using libslang Just another step in stopping the use of libnewt in perf. Cc: David Ahern Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-vtxnmz1t1807ykprapnk9njl@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/annotate.c | 9 ++- tools/perf/util/debug.h | 1 + tools/perf/util/ui/browsers/annotate.c | 14 ++--- tools/perf/util/ui/setup.c | 8 +-- tools/perf/util/ui/util.c | 110 ++++++++++++++++++--------------- tools/perf/util/ui/util.h | 2 + 6 files changed, 77 insertions(+), 67 deletions(-) (limited to 'tools/perf/util/ui/browsers/annotate.c') diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index bc8f4773d4d..119e996035c 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -310,9 +310,12 @@ fallback: } err = -ENOENT; dso->annotate_warned = 1; - pr_err("Can't annotate %s: No vmlinux file%s was found in the " - "path.\nPlease use 'perf buildid-cache -av vmlinux' or " - "--vmlinux vmlinux.\n", + pr_err("Can't annotate %s:\n\n" + "No vmlinux file%s\nwas found in the path.\n\n" + "Please use:\n\n" + " perf buildid-cache -av vmlinux\n\n" + "or:\n\n" + " --vmlinux vmlinux", sym->name, build_id_msg ?: ""); goto out_free_filename; } diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 510adaccba8..9c59b9551ad 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h @@ -29,5 +29,6 @@ int ui_helpline__show_help(const char *format, va_list ap); void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); void ui__warning_paranoid(void); +void ui__error(const char *format, ...) __attribute__((format(printf, 1, 2))); #endif /* __PERF_DEBUG_H */ diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 4e0cb7fea7d..0575905d120 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -1,6 +1,9 @@ +#include "../../util.h" #include "../browser.h" #include "../helpline.h" #include "../libslang.h" +#include "../ui.h" +#include "../util.h" #include "../../annotate.h" #include "../../hist.h" #include "../../sort.h" @@ -8,15 +11,6 @@ #include #include -static void ui__error_window(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - newtWinMessagev((char *)"Error", (char *)"Ok", (char *)fmt, ap); - va_end(ap); -} - struct annotate_browser { struct ui_browser b; struct rb_root entries; @@ -400,7 +394,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, return -1; if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) { - ui__error_window(ui_helpline__last_msg); + ui__error("%s", ui_helpline__last_msg); return -1; } diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c index c4e025fbd6b..85a69faa09a 100644 --- a/tools/perf/util/ui/setup.c +++ b/tools/perf/util/ui/setup.c @@ -146,10 +146,10 @@ void setup_browser(bool fallback_to_pager) void exit_browser(bool wait_for_ok) { if (use_browser > 0) { - if (wait_for_ok) { - char title[] = "Fatal Error", ok[] = "Ok"; - newtWinMessage(title, ok, ui_helpline__last_msg); - } + if (wait_for_ok) + ui__question_window("Fatal Error", + ui_helpline__last_msg, + "Press any key...", 0); ui__exit(); } } diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c index 37e6fe081a5..ef9b79332fe 100644 --- a/tools/perf/util/ui/util.c +++ b/tools/perf/util/ui/util.c @@ -1,6 +1,5 @@ -#include +#include "../util.h" #include -#include #include #include #include @@ -12,6 +11,7 @@ #include "helpline.h" #include "ui.h" #include "util.h" +#include "libslang.h" static void ui_browser__argv_write(struct ui_browser *browser, void *entry, int row) @@ -56,23 +56,6 @@ static int popup_menu__run(struct ui_browser *menu) return key; } -static void newt_form__set_exit_keys(newtComponent self) -{ - newtFormAddHotKey(self, NEWT_KEY_LEFT); - newtFormAddHotKey(self, NEWT_KEY_ESCAPE); - newtFormAddHotKey(self, 'Q'); - newtFormAddHotKey(self, 'q'); - newtFormAddHotKey(self, CTRL('c')); -} - -static newtComponent newt_form__new(void) -{ - newtComponent self = newtForm(NULL, NULL, 0); - if (self) - newt_form__set_exit_keys(self); - return self; -} - int ui__popup_menu(int argc, char * const argv[]) { struct ui_browser menu = { @@ -86,17 +69,13 @@ int ui__popup_menu(int argc, char * const argv[]) return popup_menu__run(&menu); } -int ui__help_window(const char *text) +int ui__question_window(const char *title, const char *text, + const char *exit_msg, int delay_secs) { - struct newtExitStruct es; - newtComponent tb, form = newt_form__new(); - int rc = -1; + int x, y; int max_len = 0, nr_lines = 0; const char *t; - if (form == NULL) - return -1; - t = text; while (1) { const char *sep = strchr(t, '\n'); @@ -113,28 +92,56 @@ int ui__help_window(const char *text) t = sep + 1; } - tb = newtTextbox(0, 0, max_len, nr_lines, 0); - if (tb == NULL) - goto out_destroy_form; - - newtTextboxSetText(tb, text); - newtFormAddComponent(form, tb); - newtCenteredWindow(max_len, nr_lines, NULL); - newtFormRun(form, &es); - newtPopWindow(); - rc = 0; -out_destroy_form: - newtFormDestroy(form); - return rc; + max_len += 2; + nr_lines += 4; + y = SLtt_Screen_Rows / 2 - nr_lines / 2, + x = SLtt_Screen_Cols / 2 - max_len / 2; + + SLsmg_set_color(0); + SLsmg_draw_box(y, x++, nr_lines, max_len); + if (title) { + SLsmg_gotorc(y, x + 1); + SLsmg_write_string((char *)title); + } + SLsmg_gotorc(++y, x); + nr_lines -= 2; + max_len -= 2; + SLsmg_write_wrapped_string((unsigned char *)text, y, x, + nr_lines, max_len, 1); + SLsmg_gotorc(y + nr_lines - 2, x); + SLsmg_write_nstring((char *)" ", max_len); + SLsmg_gotorc(y + nr_lines - 1, x); + SLsmg_write_nstring((char *)exit_msg, max_len); + SLsmg_refresh(); + return ui__getch(delay_secs); } -static const char yes[] = "Yes", no[] = "No", - warning_str[] = "Warning!", ok[] = "Ok"; +int ui__help_window(const char *text) +{ + return ui__question_window("Help", text, "Press any key...", 0); +} bool ui__dialog_yesno(const char *msg) { - /* newtWinChoice should really be accepting const char pointers... */ - return newtWinChoice(NULL, (char *)yes, (char *)no, (char *)msg) == 1; + int answer = ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0); + + return answer == K_ENTER; +} + +static void __ui__warning(const char *title, const char *format, va_list args) +{ + char *s; + + if (use_browser > 0 && vasprintf(&s, format, args) > 0) { + pthread_mutex_lock(&ui__lock); + ui__question_window(title, s, "Press any key...", 0); + pthread_mutex_unlock(&ui__lock); + free(s); + return; + } + + fprintf(stderr, "%s:\n", title); + vfprintf(stderr, format, args); } void ui__warning(const char *format, ...) @@ -142,12 +149,15 @@ void ui__warning(const char *format, ...) va_list args; va_start(args, format); - if (use_browser > 0) { - pthread_mutex_lock(&ui__lock); - newtWinMessagev((char *)warning_str, (char *)ok, - (char *)format, args); - pthread_mutex_unlock(&ui__lock); - } else - vfprintf(stderr, format, args); + __ui__warning("Warning", format, args); + va_end(args); +} + +void ui__error(const char *format, ...) +{ + va_list args; + + va_start(args, format); + __ui__warning("Error", format, args); va_end(args); } diff --git a/tools/perf/util/ui/util.h b/tools/perf/util/ui/util.h index e53c3d33490..9a25538d473 100644 --- a/tools/perf/util/ui/util.h +++ b/tools/perf/util/ui/util.h @@ -7,5 +7,7 @@ int ui__getch(int delay_secs); int ui__popup_menu(int argc, char * const argv[]); int ui__help_window(const char *text); bool ui__dialog_yesno(const char *msg); +int ui__question_window(const char *title, const char *text, + const char *exit_msg, int delay_secs); #endif /* _PERF_UI_UTIL_H_ */ -- cgit v1.2.3-70-g09d2