aboutsummaryrefslogtreecommitdiff
path: root/tools/perf/util/ui
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/ui')
-rw-r--r--tools/perf/util/ui/browser.h2
-rw-r--r--tools/perf/util/ui/browsers/annotate.c18
-rw-r--r--tools/perf/util/ui/browsers/hists.c119
-rw-r--r--tools/perf/util/ui/browsers/map.c2
-rw-r--r--tools/perf/util/ui/keysyms.h2
-rw-r--r--tools/perf/util/ui/util.c82
6 files changed, 198 insertions, 27 deletions
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index 84d761b730c1..6ee82f60feaf 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -49,6 +49,8 @@ int ui_browser__warning(struct ui_browser *browser, int timeout,
const char *format, ...);
int ui_browser__help_window(struct ui_browser *browser, const char *text);
bool ui_browser__dialog_yesno(struct ui_browser *browser, const char *text);
+int ui_browser__input_window(const char *title, const char *text, char *input,
+ const char *exit_msg, int delay_sec);
void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 295a9c93f945..57a4c6ef3fd2 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -69,14 +69,17 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
if (!self->navkeypressed)
width += 1;
+ if (!ab->hide_src_code && ol->offset != -1)
+ if (!current_entry || (self->use_navkeypressed &&
+ !self->navkeypressed))
+ ui_browser__set_color(self, HE_COLORSET_CODE);
+
if (!*ol->line)
slsmg_write_nstring(" ", width - 18);
else
slsmg_write_nstring(ol->line, width - 18);
- if (!current_entry)
- ui_browser__set_color(self, HE_COLORSET_CODE);
- else
+ if (current_entry)
ab->selection = ol;
}
@@ -230,9 +233,9 @@ 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";
+ const char *help = "<-/ESC: Exit, TAB/shift+TAB: Cycle hot lines, "
+ "H: Go to hottest line, ->/ENTER: Line action, "
+ "S: Toggle source code view";
int key;
if (ui_browser__show(&self->b, sym->name, help) < 0)
@@ -284,9 +287,11 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
nd = self->curr_hot;
break;
case 'H':
+ case 'h':
nd = self->curr_hot;
break;
case 'S':
+ case 's':
if (annotate_browser__toggle_source(self))
ui_helpline__puts(help);
continue;
@@ -338,6 +343,7 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
pthread_mutex_unlock(&notes->lock);
symbol__tui_annotate(target, ms->map, evidx,
timer, arg, delay_secs);
+ ui_browser__show_title(&self->b, sym->name);
}
continue;
case K_LEFT:
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index bb9197c9c4a4..d7a1c4afe28b 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -805,8 +805,11 @@ 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;
+ self->b.use_navkeypressed = true;
+ if (sort__branch_mode == 1)
+ self->has_symbols = sort_sym_from.list.next != NULL;
+ else
+ self->has_symbols = sort_sym.list.next != NULL;
}
return self;
@@ -839,6 +842,9 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
nr_events = convert_unit(nr_events, &unit);
printed = scnprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
+ if (self->uid_filter_str)
+ printed += snprintf(bf + printed, size - printed,
+ ", UID: %s", self->uid_filter_str);
if (thread)
printed += scnprintf(bf + printed, size - printed,
", Thread: %s(%d)",
@@ -850,6 +856,16 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
return printed;
}
+static inline void free_popup_options(char **options, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ free(options[i]);
+ options[i] = NULL;
+ }
+}
+
static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
const char *helpline, const char *ev_name,
bool left_exits,
@@ -858,8 +874,12 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
{
struct hists *self = &evsel->hists;
struct hist_browser *browser = hist_browser__new(self);
+ struct branch_info *bi;
struct pstack *fstack;
+ char *options[16];
+ int nr_options = 0;
int key = -1;
+ char buf[64];
if (browser == NULL)
return -1;
@@ -870,13 +890,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
ui_helpline__push(helpline);
+ memset(options, 0, sizeof(options));
+
while (1) {
const struct thread *thread = NULL;
const struct dso *dso = NULL;
- char *options[16];
- int nr_options = 0, choice = 0, i,
+ int choice = 0,
annotate = -2, zoom_dso = -2, zoom_thread = -2,
- browse_map = -2;
+ annotate_f = -2, annotate_t = -2, browse_map = -2;
+
+ nr_options = 0;
key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
@@ -884,7 +907,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
thread = hist_browser__selected_thread(browser);
dso = browser->selection->map ? browser->selection->map->dso : NULL;
}
-
switch (key) {
case K_TAB:
case K_UNTAB:
@@ -899,7 +921,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols) {
ui_browser__warning(&browser->b, delay_secs * 2,
"Annotation is only available for symbolic views, "
- "include \"sym\" in --sort to use it.");
+ "include \"sym*\" in --sort to use it.");
continue;
}
@@ -912,6 +934,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
goto zoom_dso;
case 't':
goto zoom_thread;
+ case 's':
+ if (ui_browser__input_window("Symbol to show",
+ "Please enter the name of symbol you want to see",
+ buf, "ENTER: OK, ESC: Cancel",
+ delay_secs * 2) == K_ENTER) {
+ self->symbol_filter_str = *buf ? buf : NULL;
+ hists__filter_by_symbol(self);
+ hist_browser__reset(browser);
+ }
+ continue;
case K_F1:
case 'h':
case '?':
@@ -929,7 +961,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
"C Collapse all callchains\n"
"E Expand all callchains\n"
"d Zoom into current DSO\n"
- "t Zoom into current Thread");
+ "t Zoom into current Thread\n"
+ "s Filter symbol by name");
continue;
case K_ENTER:
case K_RIGHT:
@@ -969,12 +1002,34 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols)
goto add_exit_option;
- if (browser->selection != NULL &&
- browser->selection->sym != NULL &&
- !browser->selection->map->dso->annotate_warned &&
- asprintf(&options[nr_options], "Annotate %s",
- browser->selection->sym->name) > 0)
- annotate = nr_options++;
+ if (sort__branch_mode == 1) {
+ bi = browser->he_selection->branch_info;
+ if (browser->selection != NULL &&
+ bi &&
+ bi->from.sym != NULL &&
+ !bi->from.map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ bi->from.sym->name) > 0)
+ annotate_f = nr_options++;
+
+ if (browser->selection != NULL &&
+ bi &&
+ bi->to.sym != NULL &&
+ !bi->to.map->dso->annotate_warned &&
+ (bi->to.sym != bi->from.sym ||
+ bi->to.map->dso != bi->from.map->dso) &&
+ asprintf(&options[nr_options], "Annotate %s",
+ bi->to.sym->name) > 0)
+ annotate_t = nr_options++;
+ } else {
+
+ if (browser->selection != NULL &&
+ browser->selection->sym != NULL &&
+ !browser->selection->map->dso->annotate_warned &&
+ asprintf(&options[nr_options], "Annotate %s",
+ browser->selection->sym->name) > 0)
+ annotate = nr_options++;
+ }
if (thread != NULL &&
asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
@@ -995,25 +1050,39 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
browse_map = nr_options++;
add_exit_option:
options[nr_options++] = (char *)"Exit";
-
+retry_popup_menu:
choice = ui__popup_menu(nr_options, options);
- for (i = 0; i < nr_options - 1; ++i)
- free(options[i]);
-
if (choice == nr_options - 1)
break;
- if (choice == -1)
+ if (choice == -1) {
+ free_popup_options(options, nr_options - 1);
continue;
+ }
- if (choice == annotate) {
+ if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he;
int err;
do_annotate:
he = hist_browser__selected_entry(browser);
if (he == NULL)
continue;
+
+ /*
+ * we stash the branch_info symbol + map into the
+ * the ms so we don't have to rewrite all the annotation
+ * code to use branch_info.
+ * in branch mode, the ms struct is not used
+ */
+ if (choice == annotate_f) {
+ he->ms.sym = he->branch_info->from.sym;
+ he->ms.map = he->branch_info->from.map;
+ } else if (choice == annotate_t) {
+ he->ms.sym = he->branch_info->to.sym;
+ he->ms.map = he->branch_info->to.map;
+ }
+
/*
* Don't let this be freed, say, by hists__decay_entry.
*/
@@ -1021,9 +1090,18 @@ do_annotate:
err = hist_entry__tui_annotate(he, evsel->idx,
timer, arg, delay_secs);
he->used = false;
+ /*
+ * offer option to annotate the other branch source or target
+ * (if they exists) when returning from annotate
+ */
+ if ((err == 'q' || err == CTRL('c'))
+ && annotate_t != -2 && annotate_f != -2)
+ goto retry_popup_menu;
+
ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
if (err)
ui_browser__handle_resize(&browser->b);
+
} else if (choice == browse_map)
map__browse(browser->selection->map);
else if (choice == zoom_dso) {
@@ -1069,6 +1147,7 @@ out_free_stack:
pstack__delete(fstack);
out:
hist_browser__delete(browser);
+ free_popup_options(options, nr_options - 1);
return key;
}
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index 6905bcc8be2d..eca6575abfd0 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -3,9 +3,9 @@
#include <newt.h>
#include <inttypes.h>
#include <sys/ttydefaults.h>
-#include <ctype.h>
#include <string.h>
#include <linux/bitops.h>
+#include "../../util.h"
#include "../../debug.h"
#include "../../symbol.h"
#include "../browser.h"
diff --git a/tools/perf/util/ui/keysyms.h b/tools/perf/util/ui/keysyms.h
index 3458b1985761..809eca5707fa 100644
--- a/tools/perf/util/ui/keysyms.h
+++ b/tools/perf/util/ui/keysyms.h
@@ -16,6 +16,8 @@
#define K_TAB '\t'
#define K_UNTAB SL_KEY_UNTAB
#define K_UP SL_KEY_UP
+#define K_BKSPC 0x7f
+#define K_DEL SL_KEY_DELETE
/* Not really keys */
#define K_TIMER -1
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 45daa7c41dad..ad4374a16bb0 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -69,6 +69,88 @@ int ui__popup_menu(int argc, char * const argv[])
return popup_menu__run(&menu);
}
+int ui_browser__input_window(const char *title, const char *text, char *input,
+ const char *exit_msg, int delay_secs)
+{
+ int x, y, len, key;
+ int max_len = 60, nr_lines = 0;
+ static char buf[50];
+ const char *t;
+
+ t = text;
+ while (1) {
+ const char *sep = strchr(t, '\n');
+
+ if (sep == NULL)
+ sep = strchr(t, '\0');
+ len = sep - t;
+ if (max_len < len)
+ max_len = len;
+ ++nr_lines;
+ if (*sep == '\0')
+ break;
+ t = sep + 1;
+ }
+
+ max_len += 2;
+ nr_lines += 8;
+ 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 -= 7;
+ max_len -= 2;
+ SLsmg_write_wrapped_string((unsigned char *)text, y, x,
+ nr_lines, max_len, 1);
+ y += nr_lines;
+ len = 5;
+ while (len--) {
+ SLsmg_gotorc(y + len - 1, x);
+ SLsmg_write_nstring((char *)" ", max_len);
+ }
+ SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
+
+ SLsmg_gotorc(y + 3, x);
+ SLsmg_write_nstring((char *)exit_msg, max_len);
+ SLsmg_refresh();
+
+ x += 2;
+ len = 0;
+ key = ui__getch(delay_secs);
+ while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+ if (key == K_BKSPC) {
+ if (len == 0)
+ goto next_key;
+ SLsmg_gotorc(y, x + --len);
+ SLsmg_write_char(' ');
+ } else {
+ buf[len] = key;
+ SLsmg_gotorc(y, x + len++);
+ SLsmg_write_char(key);
+ }
+ SLsmg_refresh();
+
+ /* XXX more graceful overflow handling needed */
+ if (len == sizeof(buf) - 1) {
+ ui_helpline__push("maximum size of symbol name reached!");
+ key = K_ENTER;
+ break;
+ }
+next_key:
+ key = ui__getch(delay_secs);
+ }
+
+ buf[len] = '\0';
+ strncpy(input, buf, len+1);
+ return key;
+}
+
int ui__question_window(const char *title, const char *text,
const char *exit_msg, int delay_secs)
{