From 3e6a2a7f3b9d0e521bb3284573b696d0cbe1952c Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Tue, 17 May 2011 17:32:07 +0200 Subject: perf annotate: Make output more readable This patch adds two new options to perf annotate: - --no-asm-raw : Do not display raw instruction encodings - --no-source : Do not interleave source code with assembly code We believe those options make the output of annotate more readable. Systematically displaying source can make it hard to follow code and especially optimized code. Raw encodings are not useful in most cases. Cc: Ingo Molnar Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20110517153207.GA9834@quad Signed-off-by: Stephane Eranian [committer note: Use the 'no-' option inverting logic] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 555aefd7fe0..5015e04b821 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -267,6 +267,10 @@ static const struct option options[] = { OPT_BOOLEAN('P', "full-paths", &full_paths, "Don't shorten the displayed pathnames"), OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), + OPT_BOOLEAN('0', "source", &symbol_conf.annotate_src, + "Interleave source code with assembly code (default)"), + OPT_BOOLEAN('0', "asm-raw", &symbol_conf.annotate_asm_raw, + "Display raw encoding of assembly instructions (default)"), OPT_END() }; -- cgit v1.2.3-70-g09d2 From e71a059832753a8834a5a5080366879954ccdc4d Mon Sep 17 00:00:00 2001 From: Stephane Eranian Date: Sat, 30 Jul 2011 01:20:40 +0200 Subject: perf annotate: Add --symfs option If you have --symfs in perf report, then you also need it for perf annotate. This allows off-box assembly level analysis of perf.data samples. This patch complements: commit ec5761eab318e50e69fcf8e63e9edaef5949c067 Author: David Ahern Date: Thu Dec 9 13:27:07 2010 -0700 perf symbols: Add symfs option for off-box analysis using specified tree Acked-by: David Ahern Cc: Ingo Molnar Cc: Peter Zijlstra Cc: David Ahern Link: http://lkml.kernel.org/r/20110729232040.GA21838@quad Signed-off-by: Stephane Eranian Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-annotate.txt | 3 +++ tools/perf/builtin-annotate.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 5bc06001557..98a31e3181a 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -80,6 +80,9 @@ OPTIONS Interleave source code with assembly code. Enabled by default, disable with --no-source. +--symfs=:: + Look for files with symbols relative to this directory. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5015e04b821..c5be28851f0 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -267,6 +267,8 @@ static const struct option options[] = { OPT_BOOLEAN('P', "full-paths", &full_paths, "Don't shorten the displayed pathnames"), OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), + OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", + "Look for files with symbols relative to this directory"), OPT_BOOLEAN('0', "source", &symbol_conf.annotate_src, "Interleave source code with assembly code (default)"), OPT_BOOLEAN('0', "asm-raw", &symbol_conf.annotate_asm_raw, -- cgit v1.2.3-70-g09d2 From f69b64f73e1d7f47a9205c1cd46e0e1c3c65e1cd Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 15 Sep 2011 14:31:41 -0700 Subject: perf: Support setting the disassembler style Add -M option to report/annotate to pass directly to objdump. This allows to use -M intel for intel style disassembler syntax, which is useful for people who are very used to the Intel syntax. Link: http://lkml.kernel.org/r/1316122302-24306-2-git-send-email-andi@firstfloor.org [committer note: Add missing Documentation bits, fixup conflicts with 3e6a2a7] Cc: Frederic Weisbecker Cc: Stephane Eranian Signed-off-by: Andi Kleen Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-annotate.txt | 3 +++ tools/perf/Documentation/perf-report.txt | 3 +++ tools/perf/builtin-annotate.c | 2 ++ tools/perf/builtin-report.c | 2 ++ tools/perf/util/annotate.c | 6 +++++- tools/perf/util/annotate.h | 2 ++ 6 files changed, 17 insertions(+), 1 deletion(-) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 98a31e3181a..0102d83600d 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -83,6 +83,9 @@ OPTIONS --symfs=:: Look for files with symbols relative to this directory. +-M:: +--disassembler-style=:: Set disassembler style for objdump. + SEE ALSO -------- linkperf:perf-record[1], linkperf:perf-report[1] diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 04253c07d19..6349b6c0e3e 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -134,6 +134,9 @@ OPTIONS CPUs are specified with -: 0-2. Default is to report samples on all CPUs. +-M:: +--disassembler-style=:: Set disassembler style for objdump. + SEE ALSO -------- linkperf:perf-stat[1] diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index c5be28851f0..cf68819f745 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -273,6 +273,8 @@ static const struct option options[] = { "Interleave source code with assembly code (default)"), OPT_BOOLEAN('0', "asm-raw", &symbol_conf.annotate_asm_raw, "Display raw encoding of assembly instructions (default)"), + OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", + "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_END() }; diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index d7ff277bdb7..a0673eeeae8 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -487,6 +487,8 @@ static const struct option options[] = { OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), + OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", + "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_END() }; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 01d36ba5405..bc8f4773d4d 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -16,6 +16,8 @@ #include "annotate.h" #include +const char *disassembler_style; + int symbol__annotate_init(struct map *map __used, struct symbol *sym) { struct annotation *notes = symbol__annotation(sym); @@ -323,9 +325,11 @@ fallback: dso, dso->long_name, sym, sym->name); snprintf(command, sizeof(command), - "objdump --start-address=0x%016" PRIx64 + "objdump %s%s --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -d %s %s -C %s|grep -v %s|expand", + disassembler_style ? "-M " : "", + disassembler_style ? disassembler_style : "", map__rip_2objdump(map, sym->start), map__rip_2objdump(map, sym->end), symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index c2c28689680..6ede1286ee7 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -100,4 +100,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, int refresh); #endif +extern const char *disassembler_style; + #endif /* __PERF_ANNOTATE_H */ -- cgit v1.2.3-70-g09d2 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/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 7 ++- tools/perf/util/annotate.h | 7 ++- tools/perf/util/evlist.c | 6 ++ tools/perf/util/evlist.h | 4 ++ tools/perf/util/hist.h | 14 +++-- tools/perf/util/ui/browsers/annotate.c | 25 +++++--- tools/perf/util/ui/browsers/hists.c | 105 ++++++++++++++++++++++----------- tools/perf/util/ui/browsers/top.c | 2 +- 9 files changed, 116 insertions(+), 56 deletions(-) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index cf68819f745..39e3d382b2d 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -137,7 +137,7 @@ find_next: } if (use_browser > 0) { - key = hist_entry__tui_annotate(he, evidx); + key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0); switch (key) { case KEY_RIGHT: next = rb_next(nd); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index c1cc7ab6f84..e7140c6289b 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -327,9 +327,10 @@ static int __cmd_report(void) goto out_delete; } - if (use_browser > 0) - perf_evlist__tui_browse_hists(session->evlist, help); - else + if (use_browser > 0) { + perf_evlist__tui_browse_hists(session->evlist, help, + NULL, NULL, 0); + } else perf_evlist__tty_browse_hists(session->evlist, help); out_delete: diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 6ede1286ee7..aafbc7e9a9b 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -91,13 +91,16 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, #ifdef NO_NEWT_SUPPORT static inline int symbol__tui_annotate(struct symbol *sym __used, struct map *map __used, - int evidx __used, int refresh __used) + int evidx __used, + void(*timer)(void *arg) __used, + void *arg __used, int delay_secs __used) { return 0; } #else int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, - int refresh); + void(*timer)(void *arg), void *arg, + int delay_secs); #endif extern const char *disassembler_style; diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 72e9f4886b6..2f6bc89027d 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -533,3 +533,9 @@ bool perf_evlist__sample_id_all(const struct perf_evlist *evlist) first = list_entry(evlist->entries.next, struct perf_evsel, node); return first->attr.sample_id_all; } + +void perf_evlist__set_selected(struct perf_evlist *evlist, + struct perf_evsel *evsel) +{ + evlist->selected = evsel; +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index f3491500274..6be71fc5779 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -25,6 +25,7 @@ struct perf_evlist { struct pollfd *pollfd; struct thread_map *threads; struct cpu_map *cpus; + struct perf_evsel *selected; }; struct perf_evsel; @@ -56,6 +57,9 @@ void perf_evlist__munmap(struct perf_evlist *evlist); void perf_evlist__disable(struct perf_evlist *evlist); void perf_evlist__enable(struct perf_evlist *evlist); +void perf_evlist__set_selected(struct perf_evlist *evlist, + struct perf_evsel *evsel); + static inline void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, struct thread_map *threads) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d3f976cc7c5..424f9eb8310 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -100,13 +100,16 @@ struct perf_evlist; #ifdef NO_NEWT_SUPPORT static inline int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, - const char *help __used) + const char *help __used, void(*timer)(void *arg) __used, void *arg, + int refresh __used) { return 0; } static inline int hist_entry__tui_annotate(struct hist_entry *self __used, - int evidx __used) + int evidx __used, + void(*timer)(void *arg) __used, + void *arg __used, int delay_secs __used); { return 0; } @@ -114,12 +117,15 @@ 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 *self, int evidx); +int hist_entry__tui_annotate(struct hist_entry *he, int evidx, + 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); +int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, + void(*timer)(void *arg), void *arg, + int refresh); #endif unsigned int hists__sort_list_width(struct hists *self); 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); diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 5d767c622df..6244d19bd1f 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c @@ -24,8 +24,14 @@ struct hist_browser { struct hists *hists; struct hist_entry *he_selection; struct map_symbol *selection; + const struct thread *thread_filter; + const struct dso *dso_filter; }; +static int hists__browser_title(struct hists *self, char *bf, size_t size, + const char *ev_name, const struct dso *dso, + const struct thread *thread); + static void hist_browser__refresh_dimensions(struct hist_browser *self) { /* 3 == +/- toggle symbol before actual hist_entry rendering */ @@ -290,9 +296,12 @@ static void hist_browser__set_folding(struct hist_browser *self, bool unfold) ui_browser__reset_index(&self->b); } -static int hist_browser__run(struct hist_browser *self, const char *title) +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 exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't', NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT, NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0, }; @@ -301,17 +310,30 @@ static int hist_browser__run(struct hist_browser *self, const char *title) self->b.nr_entries = self->hists->nr_entries; hist_browser__refresh_dimensions(self); + hists__browser_title(self->hists, title, sizeof(title), ev_name, + self->dso_filter, self->thread_filter); if (ui_browser__show(&self->b, title, "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); while (1) { key = ui_browser__run(&self->b); switch (key) { + case -1: + /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */ + timer(arg); + hists__browser_title(self->hists, title, sizeof(title), + ev_name, self->dso_filter, + self->thread_filter); + ui_browser__show_title(&self->b, title); + continue; case 'D': { /* Debug */ static int seq; struct hist_entry *h = rb_entry(self->b.top, @@ -805,14 +827,13 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size, static int perf_evsel__hists_browse(struct perf_evsel *evsel, const char *helpline, const char *ev_name, - bool left_exits) + bool left_exits, + void(*timer)(void *arg), void *arg, + int delay_secs) { struct hists *self = &evsel->hists; struct hist_browser *browser = hist_browser__new(self); struct pstack *fstack; - const struct thread *thread_filter = NULL; - const struct dso *dso_filter = NULL; - char msg[160]; int key = -1; if (browser == NULL) @@ -824,8 +845,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, ui_helpline__push(helpline); - hists__browser_title(self, msg, sizeof(msg), ev_name, - dso_filter, thread_filter); while (1) { const struct thread *thread = NULL; const struct dso *dso = NULL; @@ -834,7 +853,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, annotate = -2, zoom_dso = -2, zoom_thread = -2, browse_map = -2; - key = hist_browser__run(browser, msg); + key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); if (browser->he_selection != NULL) { thread = hist_browser__selected_thread(browser); @@ -889,9 +908,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, continue; } top = pstack__pop(fstack); - if (top == &dso_filter) + if (top == &browser->dso_filter) goto zoom_out_dso; - if (top == &thread_filter) + if (top == &browser->thread_filter) goto zoom_out_thread; continue; } @@ -913,14 +932,14 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, if (thread != NULL && asprintf(&options[nr_options], "Zoom %s %s(%d) thread", - (thread_filter ? "out of" : "into"), + (browser->thread_filter ? "out of" : "into"), (thread->comm_set ? thread->comm : ""), thread->pid) > 0) zoom_thread = nr_options++; if (dso != NULL && asprintf(&options[nr_options], "Zoom %s %s DSO", - (dso_filter ? "out of" : "into"), + (browser->dso_filter ? "out of" : "into"), (dso->kernel ? "the Kernel" : dso->short_name)) > 0) zoom_dso = nr_options++; @@ -949,45 +968,42 @@ do_annotate: if (he == NULL) continue; - hist_entry__tui_annotate(he, evsel->idx); + hist_entry__tui_annotate(he, evsel->idx, + timer, arg, delay_secs); } else if (choice == browse_map) map__browse(browser->selection->map); else if (choice == zoom_dso) { zoom_dso: - if (dso_filter) { - pstack__remove(fstack, &dso_filter); + if (browser->dso_filter) { + pstack__remove(fstack, &browser->dso_filter); zoom_out_dso: ui_helpline__pop(); - dso_filter = NULL; + browser->dso_filter = NULL; } else { if (dso == NULL) continue; ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s DSO\"", dso->kernel ? "the Kernel" : dso->short_name); - dso_filter = dso; - pstack__push(fstack, &dso_filter); + browser->dso_filter = dso; + pstack__push(fstack, &browser->dso_filter); } - hists__filter_by_dso(self, dso_filter); - hists__browser_title(self, msg, sizeof(msg), ev_name, - dso_filter, thread_filter); + hists__filter_by_dso(self, browser->dso_filter); hist_browser__reset(browser); } else if (choice == zoom_thread) { zoom_thread: - if (thread_filter) { - pstack__remove(fstack, &thread_filter); + if (browser->thread_filter) { + pstack__remove(fstack, &browser->thread_filter); zoom_out_thread: ui_helpline__pop(); - thread_filter = NULL; + browser->thread_filter = NULL; } else { ui_helpline__fpush("To zoom out press <- or -> + \"Zoom out of %s(%d) thread\"", thread->comm_set ? thread->comm : "", thread->pid); - thread_filter = thread; - pstack__push(fstack, &thread_filter); + browser->thread_filter = thread; + pstack__push(fstack, &browser->thread_filter); } - hists__filter_by_thread(self, thread_filter); - hists__browser_title(self, msg, sizeof(msg), ev_name, - dso_filter, thread_filter); + hists__filter_by_thread(self, browser->thread_filter); hist_browser__reset(browser); } } @@ -1026,9 +1042,11 @@ 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, const char *help, + 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"; @@ -1038,20 +1056,29 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help) "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); switch (key) { + case -1: + /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */ + timer(arg); + continue; case NEWT_KEY_RIGHT: case NEWT_KEY_ENTER: if (!menu->selection) continue; pos = menu->selection; + perf_evlist__set_selected(evlist, pos); browse_hists: ev_name = event_name(pos); - key = perf_evsel__hists_browse(pos, help, ev_name, true); + key = perf_evsel__hists_browse(pos, help, ev_name, true, + timer, arg, delay_secs); ui_browser__show_title(&menu->b, title); break; case NEWT_KEY_LEFT: @@ -1091,7 +1118,9 @@ out: } static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, - const char *help) + const char *help, + void(*timer)(void *arg), void *arg, + int delay_secs) { struct perf_evsel *pos; struct perf_evsel_menu menu = { @@ -1121,18 +1150,22 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, pos->name = strdup(ev_name); } - return perf_evsel_menu__run(&menu, help); + return perf_evsel_menu__run(&menu, help, timer, arg, delay_secs); } -int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help) +int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, + void(*timer)(void *arg), void *arg, + int delay_secs) { if (evlist->nr_entries == 1) { 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); + return perf_evsel__hists_browse(first, help, ev_name, false, + timer, arg, delay_secs); } - return __perf_evlist__tui_browse_hists(evlist, help); + return __perf_evlist__tui_browse_hists(evlist, help, + timer, arg, delay_secs); } diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c index 9b6b43b32ac..d43875b2356 100644 --- a/tools/perf/util/ui/browsers/top.c +++ b/tools/perf/util/ui/browsers/top.c @@ -142,7 +142,7 @@ static void perf_top_browser__annotate(struct perf_top_browser *browser) pthread_mutex_unlock(¬es->lock); do_annotation: - symbol__tui_annotate(sym, syme->map, 0, top->delay_secs * 1000); + symbol__tui_annotate(sym, syme->map, 0, NULL, NULL, top->delay_secs * 1000); } static void perf_top_browser__warn_lost(struct perf_top_browser *browser) -- 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/builtin-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 64c6f0c7f8db449e05ee16e35a7083df69addd1d Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 6 Oct 2011 12:48:31 -0300 Subject: perf tools: Make --no-asm-raw the default And add the annotation output knobs to all the tools that have integrated annotation (top, report). 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-gnlob67mke6sji2kf4nstp7m@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-annotate.txt | 3 +-- tools/perf/Documentation/perf-report.txt | 9 ++++++++- tools/perf/Documentation/perf-top.txt | 10 ++++++++++ tools/perf/builtin-annotate.c | 4 ++-- tools/perf/builtin-report.c | 4 ++++ tools/perf/builtin-top.c | 6 ++++++ tools/perf/util/symbol.c | 1 - 7 files changed, 31 insertions(+), 6 deletions(-) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 0102d83600d..fe6762ed56b 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -73,8 +73,7 @@ OPTIONS CPUs. --asm-raw:: - Show raw instruction encoding of assembly instructions. They - are displayed by default, disable with --no-asm-raw. + Show raw instruction encoding of assembly instructions. --source:: Interleave source code with assembly code. Enabled by default, diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 4ed17072ea8..212f24d672e 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt @@ -137,6 +137,13 @@ OPTIONS -M:: --disassembler-style=:: Set disassembler style for objdump. +--source:: + Interleave source code with assembly code. Enabled by default, + disable with --no-source. + +--asm-raw:: + Show raw instruction encoding of assembly instructions. + --show-total-period:: Show a column with the sum of periods. -I:: @@ -147,4 +154,4 @@ OPTIONS SEE ALSO -------- -linkperf:perf-stat[1] +linkperf:perf-stat[1], linkperf:perf-annotate[1] diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index e2e5cd0023c..b1a5bbbfebe 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt @@ -126,6 +126,16 @@ Default is to monitor all CPUS. --symbols:: Only consider these symbols. +-M:: +--disassembler-style=:: Set disassembler style for objdump. + +--source:: + Interleave source code with assembly code. Enabled by default, + disable with --no-source. + +--asm-raw:: + Show raw instruction encoding of assembly instructions. + -G [type,min,order]:: --call-graph:: Display call chains using type, min percent threshold and order. diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 24db9d2db7b..3ea764a7805 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -272,9 +272,9 @@ static const struct option options[] = { OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", "Look for files with symbols relative to this directory"), - OPT_BOOLEAN('0', "source", &symbol_conf.annotate_src, + OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, "Interleave source code with assembly code (default)"), - OPT_BOOLEAN('0', "asm-raw", &symbol_conf.annotate_asm_raw, + OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 66fe822b181..4d7c8340c32 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -491,6 +491,10 @@ static const struct option options[] = { OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_BOOLEAN('I', "show-info", &show_full_info, "Display extended information about perf.data file"), + OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, + "Interleave source code with assembly code (default)"), + OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, + "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index cc877bc83eb..c5aebf6eb74 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1117,6 +1117,12 @@ static const struct option options[] = { "only consider symbols in these comms"), OPT_STRING(0, "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", "only consider these symbols"), + OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, + "Interleave source code with assembly code (default)"), + OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, + "Display raw encoding of assembly instructions (default)"), + OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", + "Specify disassembler style (e.g. -M intel for intel syntax)"), OPT_END() }; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 077df15ee70..3f09a23f71b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -46,7 +46,6 @@ struct symbol_conf symbol_conf = { .exclude_other = true, .use_modules = true, .try_vmlinux_path = true, - .annotate_asm_raw = true, .annotate_src = true, .symfs = "", }; -- 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/builtin-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