aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-10-15 10:57:48 -0400
committerIngo Molnar <mingo@elte.hu>2011-10-15 10:57:48 -0400
commitc73a3cb356f94b443aa7624b539493191dbf44c1 (patch)
treea813dbd5e3e2cf77ce33729e07f6fda3a819e3bb /tools/perf
parent910e94dd0cc5abacebf0bd5ffd859f61b9583857 (diff)
parent6c3c5b26d08569ed80e10d3e02d3c997ed1e6e7c (diff)
Merge branch 'perf/core' of git://github.com/acmel/linux into perf/core
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-top.c25
-rw-r--r--tools/perf/perf.c24
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.c24
-rw-r--r--tools/perf/util/hist.h11
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/ui/browser.c228
-rw-r--r--tools/perf/util/ui/browser.h10
-rw-r--r--tools/perf/util/ui/browsers/annotate.c95
-rw-r--r--tools/perf/util/ui/browsers/hists.c110
-rw-r--r--tools/perf/util/ui/browsers/map.c6
-rw-r--r--tools/perf/util/ui/helpline.h2
13 files changed, 375 insertions, 165 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index c5aebf6eb746..e211304a0dd7 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -304,7 +304,7 @@ static void print_sym_table(void)
304 304
305 hists__collapse_resort_threaded(&top.sym_evsel->hists); 305 hists__collapse_resort_threaded(&top.sym_evsel->hists);
306 hists__output_resort_threaded(&top.sym_evsel->hists); 306 hists__output_resort_threaded(&top.sym_evsel->hists);
307 hists__decay_entries(&top.sym_evsel->hists); 307 hists__decay_entries_threaded(&top.sym_evsel->hists);
308 hists__output_recalc_col_len(&top.sym_evsel->hists, winsize.ws_row - 3); 308 hists__output_recalc_col_len(&top.sym_evsel->hists, winsize.ws_row - 3);
309 putchar('\n'); 309 putchar('\n');
310 hists__fprintf(&top.sym_evsel->hists, NULL, false, false, 310 hists__fprintf(&top.sym_evsel->hists, NULL, false, false,
@@ -555,7 +555,7 @@ static void perf_top__sort_new_samples(void *arg)
555 555
556 hists__collapse_resort_threaded(&t->sym_evsel->hists); 556 hists__collapse_resort_threaded(&t->sym_evsel->hists);
557 hists__output_resort_threaded(&t->sym_evsel->hists); 557 hists__output_resort_threaded(&t->sym_evsel->hists);
558 hists__decay_entries(&t->sym_evsel->hists); 558 hists__decay_entries_threaded(&t->sym_evsel->hists);
559 hists__output_recalc_col_len(&t->sym_evsel->hists, winsize.ws_row - 3); 559 hists__output_recalc_col_len(&t->sym_evsel->hists, winsize.ws_row - 3);
560} 560}
561 561
@@ -585,16 +585,31 @@ static void *display_thread(void *arg __used)
585 tc.c_cc[VMIN] = 0; 585 tc.c_cc[VMIN] = 0;
586 tc.c_cc[VTIME] = 0; 586 tc.c_cc[VTIME] = 0;
587 587
588 pthread__unblock_sigwinch();
588repeat: 589repeat:
589 delay_msecs = top.delay_secs * 1000; 590 delay_msecs = top.delay_secs * 1000;
590 tcsetattr(0, TCSANOW, &tc); 591 tcsetattr(0, TCSANOW, &tc);
591 /* trash return*/ 592 /* trash return*/
592 getc(stdin); 593 getc(stdin);
593 594
594 do { 595 while (1) {
595 print_sym_table(); 596 print_sym_table();
596 } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 597 /*
597 598 * Either timeout expired or we got an EINTR due to SIGWINCH,
599 * refresh screen in both cases.
600 */
601 switch (poll(&stdin_poll, 1, delay_msecs)) {
602 case 0:
603 continue;
604 case -1:
605 if (errno == EINTR)
606 continue;
607 /* Fall trhu */
608 default:
609 goto process_hotkey;
610 }
611 }
612process_hotkey:
598 c = getc(stdin); 613 c = getc(stdin);
599 tcsetattr(0, TCSAFLUSH, &save); 614 tcsetattr(0, TCSAFLUSH, &save);
600 615
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index ec635b7cc8ea..73d0cac8b67e 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -427,6 +427,24 @@ static void get_debugfs_mntpt(void)
427 debugfs_mntpt[0] = '\0'; 427 debugfs_mntpt[0] = '\0';
428} 428}
429 429
430static void pthread__block_sigwinch(void)
431{
432 sigset_t set;
433
434 sigemptyset(&set);
435 sigaddset(&set, SIGWINCH);
436 pthread_sigmask(SIG_BLOCK, &set, NULL);
437}
438
439void pthread__unblock_sigwinch(void)
440{
441 sigset_t set;
442
443 sigemptyset(&set);
444 sigaddset(&set, SIGWINCH);
445 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
446}
447
430int main(int argc, const char **argv) 448int main(int argc, const char **argv)
431{ 449{
432 const char *cmd; 450 const char *cmd;
@@ -480,6 +498,12 @@ int main(int argc, const char **argv)
480 * time. 498 * time.
481 */ 499 */
482 setup_path(); 500 setup_path();
501 /*
502 * Block SIGWINCH notifications so that the thread that wants it can
503 * unblock and get syscalls like select interrupted instead of waiting
504 * forever while the signal goes to some other non interested thread.
505 */
506 pthread__block_sigwinch();
483 507
484 while (1) { 508 while (1) {
485 static int done_help; 509 static int done_help;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 08b0b5e82a44..914c895510f7 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -183,4 +183,6 @@ struct ip_callchain {
183extern bool perf_host, perf_guest; 183extern bool perf_host, perf_guest;
184extern const char perf_version_string[]; 184extern const char perf_version_string[];
185 185
186void pthread__unblock_sigwinch(void);
187
186#endif 188#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index f2ceb0f7d669..2143a32638c2 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1289,7 +1289,7 @@ int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
1289 if (access(linkname, F_OK)) 1289 if (access(linkname, F_OK))
1290 goto out_free; 1290 goto out_free;
1291 1291
1292 if (readlink(linkname, filename, size) < 0) 1292 if (readlink(linkname, filename, size - 1) < 0)
1293 goto out_free; 1293 goto out_free;
1294 1294
1295 if (unlink(linkname)) 1295 if (unlink(linkname))
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 50c8fece1681..a7193c5a0422 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -100,13 +100,15 @@ static void hist_entry__decay(struct hist_entry *he)
100 100
101static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 101static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
102{ 102{
103 if (he->period == 0)
104 return true;
103 hists->stats.total_period -= he->period; 105 hists->stats.total_period -= he->period;
104 hist_entry__decay(he); 106 hist_entry__decay(he);
105 hists->stats.total_period += he->period; 107 hists->stats.total_period += he->period;
106 return he->period == 0; 108 return he->period == 0;
107} 109}
108 110
109void hists__decay_entries(struct hists *hists) 111static void __hists__decay_entries(struct hists *hists, bool threaded)
110{ 112{
111 struct rb_node *next = rb_first(&hists->entries); 113 struct rb_node *next = rb_first(&hists->entries);
112 struct hist_entry *n; 114 struct hist_entry *n;
@@ -114,11 +116,15 @@ void hists__decay_entries(struct hists *hists)
114 while (next) { 116 while (next) {
115 n = rb_entry(next, struct hist_entry, rb_node); 117 n = rb_entry(next, struct hist_entry, rb_node);
116 next = rb_next(&n->rb_node); 118 next = rb_next(&n->rb_node);
117 119 /*
118 if (hists__decay_entry(hists, n)) { 120 * We may be annotating this, for instance, so keep it here in
121 * case some it gets new samples, we'll eventually free it when
122 * the user stops browsing and it agains gets fully decayed.
123 */
124 if (hists__decay_entry(hists, n) && !n->used) {
119 rb_erase(&n->rb_node, &hists->entries); 125 rb_erase(&n->rb_node, &hists->entries);
120 126
121 if (sort__need_collapse) 127 if (sort__need_collapse || threaded)
122 rb_erase(&n->rb_node_in, &hists->entries_collapsed); 128 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
123 129
124 hist_entry__free(n); 130 hist_entry__free(n);
@@ -127,6 +133,16 @@ void hists__decay_entries(struct hists *hists)
127 } 133 }
128} 134}
129 135
136void hists__decay_entries(struct hists *hists)
137{
138 return __hists__decay_entries(hists, false);
139}
140
141void hists__decay_entries_threaded(struct hists *hists)
142{
143 return __hists__decay_entries(hists, true);
144}
145
130/* 146/*
131 * histogram, sorted on item, collects periods 147 * histogram, sorted on item, collects periods
132 */ 148 */
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 7ea1e560e008..bcc8ab91e26f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -79,6 +79,7 @@ void hists__collapse_resort(struct hists *self);
79void hists__collapse_resort_threaded(struct hists *hists); 79void hists__collapse_resort_threaded(struct hists *hists);
80 80
81void hists__decay_entries(struct hists *hists); 81void hists__decay_entries(struct hists *hists);
82void hists__decay_entries_threaded(struct hists *hists);
82void hists__output_recalc_col_len(struct hists *hists, int max_rows); 83void hists__output_recalc_col_len(struct hists *hists, int max_rows);
83 84
84void hists__inc_nr_events(struct hists *self, u32 type); 85void hists__inc_nr_events(struct hists *self, u32 type);
@@ -103,16 +104,20 @@ struct perf_evlist;
103#ifdef NO_NEWT_SUPPORT 104#ifdef NO_NEWT_SUPPORT
104static inline 105static inline
105int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used, 106int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
106 const char *help __used, void(*timer)(void *arg) __used, void *arg, 107 const char *help __used,
108 void(*timer)(void *arg) __used,
109 void *arg __used,
107 int refresh __used) 110 int refresh __used)
108{ 111{
109 return 0; 112 return 0;
110} 113}
111 114
112static inline int hist_entry__tui_annotate(struct hist_entry *self __used, 115static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
113 int evidx __used, int nr_events __used, 116 int evidx __used,
117 int nr_events __used,
114 void(*timer)(void *arg) __used, 118 void(*timer)(void *arg) __used,
115 void *arg __used, int delay_secs __used); 119 void *arg __used,
120 int delay_secs __used)
116{ 121{
117 return 0; 122 return 0;
118} 123}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 03851e301721..3f67ae395752 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -64,6 +64,7 @@ struct hist_entry {
64 64
65 bool init_have_children; 65 bool init_have_children;
66 char level; 66 char level;
67 bool used;
67 u8 filtered; 68 u8 filtered;
68 struct symbol *parent; 69 struct symbol *parent;
69 union { 70 union {
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 611219f80680..a54b926efe2b 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -1,4 +1,7 @@
1#include "../util.h"
2#include "../../perf.h"
1#include "libslang.h" 3#include "libslang.h"
4#include <newt.h>
2#include "ui.h" 5#include "ui.h"
3#include <linux/compiler.h> 6#include <linux/compiler.h>
4#include <linux/list.h> 7#include <linux/list.h>
@@ -8,8 +11,8 @@
8#include "browser.h" 11#include "browser.h"
9#include "helpline.h" 12#include "helpline.h"
10#include "../color.h" 13#include "../color.h"
11#include "../util.h" 14
12#include <stdio.h> 15int newtGetKey(void);
13 16
14static int ui_browser__percent_color(double percent, bool current) 17static int ui_browser__percent_color(double percent, bool current)
15{ 18{
@@ -39,31 +42,62 @@ void ui_browser__gotorc(struct ui_browser *self, int y, int x)
39 SLsmg_gotorc(self->y + y, self->x + x); 42 SLsmg_gotorc(self->y + y, self->x + x);
40} 43}
41 44
45static struct list_head *
46ui_browser__list_head_filter_entries(struct ui_browser *browser,
47 struct list_head *pos)
48{
49 do {
50 if (!browser->filter || !browser->filter(browser, pos))
51 return pos;
52 pos = pos->next;
53 } while (pos != browser->entries);
54
55 return NULL;
56}
57
58static struct list_head *
59ui_browser__list_head_filter_prev_entries(struct ui_browser *browser,
60 struct list_head *pos)
61{
62 do {
63 if (!browser->filter || !browser->filter(browser, pos))
64 return pos;
65 pos = pos->prev;
66 } while (pos != browser->entries);
67
68 return NULL;
69}
70
42void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence) 71void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence)
43{ 72{
44 struct list_head *head = self->entries; 73 struct list_head *head = self->entries;
45 struct list_head *pos; 74 struct list_head *pos;
46 75
76 if (self->nr_entries == 0)
77 return;
78
47 switch (whence) { 79 switch (whence) {
48 case SEEK_SET: 80 case SEEK_SET:
49 pos = head->next; 81 pos = ui_browser__list_head_filter_entries(self, head->next);
50 break; 82 break;
51 case SEEK_CUR: 83 case SEEK_CUR:
52 pos = self->top; 84 pos = self->top;
53 break; 85 break;
54 case SEEK_END: 86 case SEEK_END:
55 pos = head->prev; 87 pos = ui_browser__list_head_filter_prev_entries(self, head->prev);
56 break; 88 break;
57 default: 89 default:
58 return; 90 return;
59 } 91 }
60 92
93 assert(pos != NULL);
94
61 if (offset > 0) { 95 if (offset > 0) {
62 while (offset-- != 0) 96 while (offset-- != 0)
63 pos = pos->next; 97 pos = ui_browser__list_head_filter_entries(self, pos->next);
64 } else { 98 } else {
65 while (offset++ != 0) 99 while (offset++ != 0)
66 pos = pos->prev; 100 pos = ui_browser__list_head_filter_prev_entries(self, pos->prev);
67 } 101 }
68 102
69 self->top = pos; 103 self->top = pos;
@@ -127,11 +161,8 @@ bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row)
127 161
128void ui_browser__refresh_dimensions(struct ui_browser *self) 162void ui_browser__refresh_dimensions(struct ui_browser *self)
129{ 163{
130 int cols, rows; 164 self->width = SLtt_Screen_Cols - 1;
131 newtGetScreenSize(&cols, &rows); 165 self->height = SLtt_Screen_Rows - 2;
132
133 self->width = cols - 1;
134 self->height = rows - 2;
135 self->y = 1; 166 self->y = 1;
136 self->x = 0; 167 self->x = 0;
137} 168}
@@ -142,26 +173,11 @@ void ui_browser__reset_index(struct ui_browser *self)
142 self->seek(self, 0, SEEK_SET); 173 self->seek(self, 0, SEEK_SET);
143} 174}
144 175
145void ui_browser__add_exit_key(struct ui_browser *self, int key)
146{
147 newtFormAddHotKey(self->form, key);
148}
149
150void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
151{
152 int i = 0;
153
154 while (keys[i] && i < 64) {
155 ui_browser__add_exit_key(self, keys[i]);
156 ++i;
157 }
158}
159
160void __ui_browser__show_title(struct ui_browser *browser, const char *title) 176void __ui_browser__show_title(struct ui_browser *browser, const char *title)
161{ 177{
162 SLsmg_gotorc(0, 0); 178 SLsmg_gotorc(0, 0);
163 ui_browser__set_color(browser, NEWT_COLORSET_ROOT); 179 ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
164 slsmg_write_nstring(title, browser->width); 180 slsmg_write_nstring(title, browser->width + 1);
165} 181}
166 182
167void ui_browser__show_title(struct ui_browser *browser, const char *title) 183void ui_browser__show_title(struct ui_browser *browser, const char *title)
@@ -174,77 +190,143 @@ void ui_browser__show_title(struct ui_browser *browser, const char *title)
174int ui_browser__show(struct ui_browser *self, const char *title, 190int ui_browser__show(struct ui_browser *self, const char *title,
175 const char *helpline, ...) 191 const char *helpline, ...)
176{ 192{
193 int err;
177 va_list ap; 194 va_list ap;
178 int keys[] = { NEWT_KEY_UP, NEWT_KEY_DOWN, NEWT_KEY_PGUP,
179 NEWT_KEY_PGDN, NEWT_KEY_HOME, NEWT_KEY_END, ' ',
180 NEWT_KEY_LEFT, NEWT_KEY_ESCAPE, 'q', CTRL('c'), 0 };
181
182 if (self->form != NULL)
183 newtFormDestroy(self->form);
184 195
185 ui_browser__refresh_dimensions(self); 196 ui_browser__refresh_dimensions(self);
186 self->form = newtForm(NULL, NULL, 0);
187 if (self->form == NULL)
188 return -1;
189
190 self->sb = newtVerticalScrollbar(self->width, 1, self->height,
191 HE_COLORSET_NORMAL,
192 HE_COLORSET_SELECTED);
193 if (self->sb == NULL)
194 return -1;
195 197
196 pthread_mutex_lock(&ui__lock); 198 pthread_mutex_lock(&ui__lock);
197 __ui_browser__show_title(self, title); 199 __ui_browser__show_title(self, title);
198 200
199 ui_browser__add_exit_keys(self, keys); 201 self->title = title;
200 newtFormAddComponent(self->form, self->sb); 202 free(self->helpline);
203 self->helpline = NULL;
201 204
202 va_start(ap, helpline); 205 va_start(ap, helpline);
203 ui_helpline__vpush(helpline, ap); 206 err = vasprintf(&self->helpline, helpline, ap);
204 va_end(ap); 207 va_end(ap);
208 if (err > 0)
209 ui_helpline__push(self->helpline);
205 pthread_mutex_unlock(&ui__lock); 210 pthread_mutex_unlock(&ui__lock);
206 return 0; 211 return err ? 0 : -1;
207} 212}
208 213
209void ui_browser__hide(struct ui_browser *self) 214void ui_browser__hide(struct ui_browser *browser __used)
210{ 215{
211 pthread_mutex_lock(&ui__lock); 216 pthread_mutex_lock(&ui__lock);
212 newtFormDestroy(self->form);
213 self->form = NULL;
214 ui_helpline__pop(); 217 ui_helpline__pop();
215 pthread_mutex_unlock(&ui__lock); 218 pthread_mutex_unlock(&ui__lock);
216} 219}
217 220
218int ui_browser__refresh(struct ui_browser *self) 221static void ui_browser__scrollbar_set(struct ui_browser *browser)
222{
223 int height = browser->height, h = 0, pct = 0,
224 col = browser->width,
225 row = browser->y - 1;
226
227 if (browser->nr_entries > 1) {
228 pct = ((browser->index * (browser->height - 1)) /
229 (browser->nr_entries - 1));
230 }
231
232 while (h < height) {
233 ui_browser__gotorc(browser, row++, col);
234 SLsmg_set_char_set(1);
235 SLsmg_write_char(h == pct ? SLSMG_DIAMOND_CHAR : SLSMG_BOARD_CHAR);
236 SLsmg_set_char_set(0);
237 ++h;
238 }
239}
240
241static int __ui_browser__refresh(struct ui_browser *browser)
219{ 242{
220 int row; 243 int row;
221 244
245 row = browser->refresh(browser);
246 ui_browser__set_color(browser, HE_COLORSET_NORMAL);
247 SLsmg_fill_region(browser->y + row, browser->x,
248 browser->height - row, browser->width, ' ');
249 ui_browser__scrollbar_set(browser);
250
251 return 0;
252}
253
254int ui_browser__refresh(struct ui_browser *browser)
255{
222 pthread_mutex_lock(&ui__lock); 256 pthread_mutex_lock(&ui__lock);
223 newtScrollbarSet(self->sb, self->index, self->nr_entries - 1); 257 __ui_browser__refresh(browser);
224 row = self->refresh(self);
225 ui_browser__set_color(self, HE_COLORSET_NORMAL);
226 SLsmg_fill_region(self->y + row, self->x,
227 self->height - row, self->width, ' ');
228 pthread_mutex_unlock(&ui__lock); 258 pthread_mutex_unlock(&ui__lock);
229 259
230 return 0; 260 return 0;
231} 261}
232 262
233int ui_browser__run(struct ui_browser *self) 263/*
264 * Here we're updating nr_entries _after_ we started browsing, i.e. we have to
265 * forget about any reference to any entry in the underlying data structure,
266 * that is why we do a SEEK_SET. Think about 'perf top' in the hists browser
267 * after an output_resort and hist decay.
268 */
269void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries)
270{
271 off_t offset = nr_entries - browser->nr_entries;
272
273 browser->nr_entries = nr_entries;
274
275 if (offset < 0) {
276 if (browser->top_idx < (u64)-offset)
277 offset = -browser->top_idx;
278
279 browser->index += offset;
280 browser->top_idx += offset;
281 }
282
283 browser->top = NULL;
284 browser->seek(browser, browser->top_idx, SEEK_SET);
285}
286
287int ui_browser__run(struct ui_browser *self, int delay_secs)
234{ 288{
235 struct newtExitStruct es; 289 int err, key;
290 struct timeval timeout, *ptimeout = delay_secs ? &timeout : NULL;
236 291
237 if (ui_browser__refresh(self) < 0) 292 pthread__unblock_sigwinch();
238 return -1;
239 293
240 while (1) { 294 while (1) {
241 off_t offset; 295 off_t offset;
296 fd_set read_set;
242 297
243 newtFormRun(self->form, &es); 298 pthread_mutex_lock(&ui__lock);
299 err = __ui_browser__refresh(self);
300 SLsmg_refresh();
301 pthread_mutex_unlock(&ui__lock);
302 if (err < 0)
303 break;
304
305 FD_ZERO(&read_set);
306 FD_SET(0, &read_set);
307
308 if (delay_secs) {
309 timeout.tv_sec = delay_secs;
310 timeout.tv_usec = 0;
311 }
244 312
245 if (es.reason != NEWT_EXIT_HOTKEY) 313 err = select(1, &read_set, NULL, NULL, ptimeout);
314 if (err > 0 && FD_ISSET(0, &read_set))
315 key = newtGetKey();
316 else if (err == 0)
246 break; 317 break;
247 switch (es.u.key) { 318 else {
319 pthread_mutex_lock(&ui__lock);
320 SLtt_get_screen_size();
321 SLsmg_reinit_smg();
322 pthread_mutex_unlock(&ui__lock);
323 ui_browser__refresh_dimensions(self);
324 __ui_browser__show_title(self, self->title);
325 ui_helpline__puts(self->helpline);
326 continue;
327 }
328
329 switch (key) {
248 case NEWT_KEY_DOWN: 330 case NEWT_KEY_DOWN:
249 if (self->index == self->nr_entries - 1) 331 if (self->index == self->nr_entries - 1)
250 break; 332 break;
@@ -301,10 +383,8 @@ int ui_browser__run(struct ui_browser *self)
301 self->seek(self, -offset, SEEK_END); 383 self->seek(self, -offset, SEEK_END);
302 break; 384 break;
303 default: 385 default:
304 return es.u.key; 386 return key;
305 } 387 }
306 if (ui_browser__refresh(self) < 0)
307 return -1;
308 } 388 }
309 return -1; 389 return -1;
310} 390}
@@ -316,27 +396,29 @@ unsigned int ui_browser__list_head_refresh(struct ui_browser *self)
316 int row = 0; 396 int row = 0;
317 397
318 if (self->top == NULL || self->top == self->entries) 398 if (self->top == NULL || self->top == self->entries)
319 self->top = head->next; 399 self->top = ui_browser__list_head_filter_entries(self, head->next);
320 400
321 pos = self->top; 401 pos = self->top;
322 402
323 list_for_each_from(pos, head) { 403 list_for_each_from(pos, head) {
324 ui_browser__gotorc(self, row, 0); 404 if (!self->filter || !self->filter(self, pos)) {
325 self->write(self, pos, row); 405 ui_browser__gotorc(self, row, 0);
326 if (++row == self->height) 406 self->write(self, pos, row);
327 break; 407 if (++row == self->height)
408 break;
409 }
328 } 410 }
329 411
330 return row; 412 return row;
331} 413}
332 414
333static struct newtPercentTreeColors { 415static struct ui_browser__colors {
334 const char *topColorFg, *topColorBg; 416 const char *topColorFg, *topColorBg;
335 const char *mediumColorFg, *mediumColorBg; 417 const char *mediumColorFg, *mediumColorBg;
336 const char *normalColorFg, *normalColorBg; 418 const char *normalColorFg, *normalColorBg;
337 const char *selColorFg, *selColorBg; 419 const char *selColorFg, *selColorBg;
338 const char *codeColorFg, *codeColorBg; 420 const char *codeColorFg, *codeColorBg;
339} defaultPercentTreeColors = { 421} ui_browser__default_colors = {
340 "red", "lightgray", 422 "red", "lightgray",
341 "green", "lightgray", 423 "green", "lightgray",
342 "black", "lightgray", 424 "black", "lightgray",
@@ -346,7 +428,7 @@ static struct newtPercentTreeColors {
346 428
347void ui_browser__init(void) 429void ui_browser__init(void)
348{ 430{
349 struct newtPercentTreeColors *c = &defaultPercentTreeColors; 431 struct ui_browser__colors *c = &ui_browser__default_colors;
350 432
351 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg); 433 sltt_set_color(HE_COLORSET_TOP, NULL, c->topColorFg, c->topColorBg);
352 sltt_set_color(HE_COLORSET_MEDIUM, NULL, c->mediumColorFg, c->mediumColorBg); 434 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 fc63dda10910..351c006dd4b5 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -2,7 +2,6 @@
2#define _PERF_UI_BROWSER_H_ 1 2#define _PERF_UI_BROWSER_H_ 1
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include <newt.h>
6#include <sys/types.h> 5#include <sys/types.h>
7#include "../types.h" 6#include "../types.h"
8 7
@@ -13,14 +12,16 @@
13#define HE_COLORSET_CODE 54 12#define HE_COLORSET_CODE 54
14 13
15struct ui_browser { 14struct ui_browser {
16 newtComponent form, sb;
17 u64 index, top_idx; 15 u64 index, top_idx;
18 void *top, *entries; 16 void *top, *entries;
19 u16 y, x, width, height; 17 u16 y, x, width, height;
20 void *priv; 18 void *priv;
19 const char *title;
20 char *helpline;
21 unsigned int (*refresh)(struct ui_browser *self); 21 unsigned int (*refresh)(struct ui_browser *self);
22 void (*write)(struct ui_browser *self, void *entry, int row); 22 void (*write)(struct ui_browser *self, void *entry, int row);
23 void (*seek)(struct ui_browser *self, off_t offset, int whence); 23 void (*seek)(struct ui_browser *self, off_t offset, int whence);
24 bool (*filter)(struct ui_browser *self, void *entry);
24 u32 nr_entries; 25 u32 nr_entries;
25}; 26};
26 27
@@ -32,15 +33,14 @@ void ui_browser__refresh_dimensions(struct ui_browser *self);
32void ui_browser__reset_index(struct ui_browser *self); 33void ui_browser__reset_index(struct ui_browser *self);
33 34
34void ui_browser__gotorc(struct ui_browser *self, int y, int x); 35void ui_browser__gotorc(struct ui_browser *self, int y, int x);
35void ui_browser__add_exit_key(struct ui_browser *self, int key);
36void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]);
37void __ui_browser__show_title(struct ui_browser *browser, const char *title); 36void __ui_browser__show_title(struct ui_browser *browser, const char *title);
38void ui_browser__show_title(struct ui_browser *browser, const char *title); 37void ui_browser__show_title(struct ui_browser *browser, const char *title);
39int ui_browser__show(struct ui_browser *self, const char *title, 38int ui_browser__show(struct ui_browser *self, const char *title,
40 const char *helpline, ...); 39 const char *helpline, ...);
41void ui_browser__hide(struct ui_browser *self); 40void ui_browser__hide(struct ui_browser *self);
42int ui_browser__refresh(struct ui_browser *self); 41int ui_browser__refresh(struct ui_browser *self);
43int ui_browser__run(struct ui_browser *self); 42int ui_browser__run(struct ui_browser *browser, int delay_secs);
43void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
44 44
45void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence); 45void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
46unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self); 46unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 674b55e686fd..eb2712ecb601 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -21,12 +21,16 @@ struct annotate_browser {
21 struct rb_root entries; 21 struct rb_root entries;
22 struct rb_node *curr_hot; 22 struct rb_node *curr_hot;
23 struct objdump_line *selection; 23 struct objdump_line *selection;
24 int nr_asm_entries;
25 int nr_entries;
26 bool hide_src_code;
24}; 27};
25 28
26struct objdump_line_rb_node { 29struct objdump_line_rb_node {
27 struct rb_node rb_node; 30 struct rb_node rb_node;
28 double percent; 31 double percent;
29 u32 idx; 32 u32 idx;
33 int idx_asm;
30}; 34};
31 35
32static inline 36static inline
@@ -35,10 +39,22 @@ struct objdump_line_rb_node *objdump_line__rb(struct objdump_line *self)
35 return (struct objdump_line_rb_node *)(self + 1); 39 return (struct objdump_line_rb_node *)(self + 1);
36} 40}
37 41
42static bool objdump_line__filter(struct ui_browser *browser, void *entry)
43{
44 struct annotate_browser *ab = container_of(browser, struct annotate_browser, b);
45
46 if (ab->hide_src_code) {
47 struct objdump_line *ol = list_entry(entry, struct objdump_line, node);
48 return ol->offset == -1;
49 }
50
51 return false;
52}
53
38static void annotate_browser__write(struct ui_browser *self, void *entry, int row) 54static void annotate_browser__write(struct ui_browser *self, void *entry, int row)
39{ 55{
40 struct annotate_browser *ab = container_of(self, struct annotate_browser, b); 56 struct annotate_browser *ab = container_of(self, struct annotate_browser, b);
41 struct objdump_line *ol = rb_entry(entry, struct objdump_line, node); 57 struct objdump_line *ol = list_entry(entry, struct objdump_line, node);
42 bool current_entry = ui_browser__is_current_entry(self, row); 58 bool current_entry = ui_browser__is_current_entry(self, row);
43 int width = self->width; 59 int width = self->width;
44 60
@@ -168,6 +184,45 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
168 browser->curr_hot = rb_last(&browser->entries); 184 browser->curr_hot = rb_last(&browser->entries);
169} 185}
170 186
187static bool annotate_browser__toggle_source(struct annotate_browser *browser)
188{
189 struct objdump_line *ol;
190 struct objdump_line_rb_node *olrb;
191 off_t offset = browser->b.index - browser->b.top_idx;
192
193 browser->b.seek(&browser->b, offset, SEEK_CUR);
194 ol = list_entry(browser->b.top, struct objdump_line, node);
195 olrb = objdump_line__rb(ol);
196
197 if (browser->hide_src_code) {
198 if (olrb->idx_asm < offset)
199 offset = olrb->idx;
200
201 browser->b.nr_entries = browser->nr_entries;
202 browser->hide_src_code = false;
203 browser->b.seek(&browser->b, -offset, SEEK_CUR);
204 browser->b.top_idx = olrb->idx - offset;
205 browser->b.index = olrb->idx;
206 } else {
207 if (olrb->idx_asm < 0) {
208 ui_helpline__puts("Only available for assembly lines.");
209 browser->b.seek(&browser->b, -offset, SEEK_CUR);
210 return false;
211 }
212
213 if (olrb->idx_asm < offset)
214 offset = olrb->idx_asm;
215
216 browser->b.nr_entries = browser->nr_asm_entries;
217 browser->hide_src_code = true;
218 browser->b.seek(&browser->b, -offset, SEEK_CUR);
219 browser->b.top_idx = olrb->idx_asm - offset;
220 browser->b.index = olrb->idx_asm;
221 }
222
223 return true;
224}
225
171static int annotate_browser__run(struct annotate_browser *self, int evidx, 226static int annotate_browser__run(struct annotate_browser *self, int evidx,
172 int nr_events, void(*timer)(void *arg), 227 int nr_events, void(*timer)(void *arg),
173 void *arg, int delay_secs) 228 void *arg, int delay_secs)
@@ -175,20 +230,14 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
175 struct rb_node *nd = NULL; 230 struct rb_node *nd = NULL;
176 struct map_symbol *ms = self->b.priv; 231 struct map_symbol *ms = self->b.priv;
177 struct symbol *sym = ms->sym; 232 struct symbol *sym = ms->sym;
178 /* 233 const char *help = "<-, ESC: exit, TAB/shift+TAB: cycle hottest lines, "
179 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by 234 "H: Hottest, -> Line action, S -> Toggle source "
180 * examining the exit key for this function. 235 "code view";
181 */
182 int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
183 NEWT_KEY_RIGHT, NEWT_KEY_ENTER, 0 };
184 int key; 236 int key;
185 237
186 if (ui_browser__show(&self->b, sym->name, 238 if (ui_browser__show(&self->b, sym->name, help) < 0)
187 "<- or ESC: exit, TAB/shift+TAB: "
188 "cycle hottest lines, H: Hottest, -> Line action") < 0)
189 return -1; 239 return -1;
190 240
191 ui_browser__add_exit_keys(&self->b, exit_keys);
192 annotate_browser__calc_percent(self, evidx); 241 annotate_browser__calc_percent(self, evidx);
193 242
194 if (self->curr_hot) 243 if (self->curr_hot)
@@ -196,11 +245,8 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
196 245
197 nd = self->curr_hot; 246 nd = self->curr_hot;
198 247
199 if (delay_secs != 0)
200 newtFormSetTimer(self->b.form, delay_secs * 1000);
201
202 while (1) { 248 while (1) {
203 key = ui_browser__run(&self->b); 249 key = ui_browser__run(&self->b, delay_secs);
204 250
205 if (delay_secs != 0) { 251 if (delay_secs != 0) {
206 annotate_browser__calc_percent(self, evidx); 252 annotate_browser__calc_percent(self, evidx);
@@ -244,6 +290,10 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
244 case 'H': 290 case 'H':
245 nd = self->curr_hot; 291 nd = self->curr_hot;
246 break; 292 break;
293 case 'S':
294 if (annotate_browser__toggle_source(self))
295 ui_helpline__puts(help);
296 continue;
247 case NEWT_KEY_ENTER: 297 case NEWT_KEY_ENTER:
248 case NEWT_KEY_RIGHT: 298 case NEWT_KEY_RIGHT:
249 if (self->selection == NULL) { 299 if (self->selection == NULL) {
@@ -295,8 +345,13 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
295 timer, arg, delay_secs); 345 timer, arg, delay_secs);
296 } 346 }
297 break; 347 break;
298 default: 348 case NEWT_KEY_LEFT:
349 case NEWT_KEY_ESCAPE:
350 case 'q':
351 case CTRL('c'):
299 goto out; 352 goto out;
353 default:
354 continue;
300 } 355 }
301 356
302 if (nd != NULL) 357 if (nd != NULL)
@@ -329,6 +384,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
329 .refresh = ui_browser__list_head_refresh, 384 .refresh = ui_browser__list_head_refresh,
330 .seek = ui_browser__list_head_seek, 385 .seek = ui_browser__list_head_seek,
331 .write = annotate_browser__write, 386 .write = annotate_browser__write,
387 .filter = objdump_line__filter,
332 .priv = &ms, 388 .priv = &ms,
333 }, 389 },
334 }; 390 };
@@ -356,9 +412,14 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
356 if (browser.b.width < line_len) 412 if (browser.b.width < line_len)
357 browser.b.width = line_len; 413 browser.b.width = line_len;
358 rbpos = objdump_line__rb(pos); 414 rbpos = objdump_line__rb(pos);
359 rbpos->idx = browser.b.nr_entries++; 415 rbpos->idx = browser.nr_entries++;
416 if (pos->offset != -1)
417 rbpos->idx_asm = browser.nr_asm_entries++;
418 else
419 rbpos->idx_asm = -1;
360 } 420 }
361 421
422 browser.b.nr_entries = browser.nr_entries;
362 browser.b.entries = &notes->src->source, 423 browser.b.entries = &notes->src->source,
363 browser.b.width += 18; /* Percentage */ 424 browser.b.width += 18; /* Percentage */
364 ret = annotate_browser__run(&browser, evidx, nr_events, 425 ret = annotate_browser__run(&browser, evidx, nr_events,
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index e64d9527f14e..b144b108029a 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -301,11 +301,7 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
301 void(*timer)(void *arg), void *arg, int delay_secs) 301 void(*timer)(void *arg), void *arg, int delay_secs)
302{ 302{
303 int key; 303 int key;
304 int delay_msecs = delay_secs * 1000;
305 char title[160]; 304 char title[160];
306 int sym_exit_keys[] = { 'a', 'h', 'C', 'd', 'E', 't', 0, };
307 int exit_keys[] = { '?', 'h', 'D', NEWT_KEY_LEFT, NEWT_KEY_RIGHT,
308 NEWT_KEY_TAB, NEWT_KEY_UNTAB, NEWT_KEY_ENTER, 0, };
309 305
310 self->b.entries = &self->hists->entries; 306 self->b.entries = &self->hists->entries;
311 self->b.nr_entries = self->hists->nr_entries; 307 self->b.nr_entries = self->hists->nr_entries;
@@ -318,27 +314,14 @@ static int hist_browser__run(struct hist_browser *self, const char *ev_name,
318 "Press '?' for help on key bindings") < 0) 314 "Press '?' for help on key bindings") < 0)
319 return -1; 315 return -1;
320 316
321 if (timer != NULL)
322 newtFormSetTimer(self->b.form, delay_msecs);
323
324 ui_browser__add_exit_keys(&self->b, exit_keys);
325 if (self->has_symbols)
326 ui_browser__add_exit_keys(&self->b, sym_exit_keys);
327
328 while (1) { 317 while (1) {
329 key = ui_browser__run(&self->b); 318 key = ui_browser__run(&self->b, delay_secs);
330 319
331 switch (key) { 320 switch (key) {
332 case -1: 321 case -1:
333 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */ 322 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
334 timer(arg); 323 timer(arg);
335 /* 324 ui_browser__update_nr_entries(&self->b, self->hists->nr_entries);
336 * The timer may have changed the number of entries.
337 * XXX: Find better way to keep this in synch, probably
338 * removing this timer function altogether and just sync
339 * using the hists->lock...
340 */
341 self->b.nr_entries = self->hists->nr_entries;
342 hists__browser_title(self->hists, title, sizeof(title), 325 hists__browser_title(self->hists, title, sizeof(title),
343 ev_name, self->dso_filter, 326 ev_name, self->dso_filter,
344 self->thread_filter); 327 self->thread_filter);
@@ -617,14 +600,23 @@ static int hist_browser__show_entry(struct hist_browser *self,
617 return printed; 600 return printed;
618} 601}
619 602
603static void ui_browser__hists_init_top(struct ui_browser *browser)
604{
605 if (browser->top == NULL) {
606 struct hist_browser *hb;
607
608 hb = container_of(browser, struct hist_browser, b);
609 browser->top = rb_first(&hb->hists->entries);
610 }
611}
612
620static unsigned int hist_browser__refresh(struct ui_browser *self) 613static unsigned int hist_browser__refresh(struct ui_browser *self)
621{ 614{
622 unsigned row = 0; 615 unsigned row = 0;
623 struct rb_node *nd; 616 struct rb_node *nd;
624 struct hist_browser *hb = container_of(self, struct hist_browser, b); 617 struct hist_browser *hb = container_of(self, struct hist_browser, b);
625 618
626 if (self->top == NULL) 619 ui_browser__hists_init_top(self);
627 self->top = rb_first(&hb->hists->entries);
628 620
629 for (nd = self->top; nd; nd = rb_next(nd)) { 621 for (nd = self->top; nd; nd = rb_next(nd)) {
630 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 622 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
@@ -676,6 +668,8 @@ static void ui_browser__hists_seek(struct ui_browser *self,
676 if (self->nr_entries == 0) 668 if (self->nr_entries == 0)
677 return; 669 return;
678 670
671 ui_browser__hists_init_top(self);
672
679 switch (whence) { 673 switch (whence) {
680 case SEEK_SET: 674 case SEEK_SET:
681 nd = hists__filter_entries(rb_first(self->entries)); 675 nd = hists__filter_entries(rb_first(self->entries));
@@ -931,8 +925,11 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
931 !ui__dialog_yesno("Do you really want to exit?")) 925 !ui__dialog_yesno("Do you really want to exit?"))
932 continue; 926 continue;
933 /* Fall thru */ 927 /* Fall thru */
934 default: 928 case 'q':
929 case CTRL('c'):
935 goto out_free_stack; 930 goto out_free_stack;
931 default:
932 continue;
936 } 933 }
937 934
938 if (!browser->has_symbols) 935 if (!browser->has_symbols)
@@ -982,9 +979,14 @@ do_annotate:
982 he = hist_browser__selected_entry(browser); 979 he = hist_browser__selected_entry(browser);
983 if (he == NULL) 980 if (he == NULL)
984 continue; 981 continue;
985 982 /*
983 * Don't let this be freed, say, by hists__decay_entry.
984 */
985 he->used = true;
986 hist_entry__tui_annotate(he, evsel->idx, nr_events, 986 hist_entry__tui_annotate(he, evsel->idx, nr_events,
987 timer, arg, delay_secs); 987 timer, arg, delay_secs);
988 he->used = false;
989 ui_browser__update_nr_entries(&browser->b, browser->hists->nr_entries);
988 } else if (choice == browse_map) 990 } else if (choice == browse_map)
989 map__browse(browser->selection->map); 991 map__browse(browser->selection->map);
990 else if (choice == zoom_dso) { 992 else if (choice == zoom_dso) {
@@ -1061,8 +1063,6 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1061 int nr_events, const char *help, 1063 int nr_events, const char *help,
1062 void(*timer)(void *arg), void *arg, int delay_secs) 1064 void(*timer)(void *arg), void *arg, int delay_secs)
1063{ 1065{
1064 int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
1065 int delay_msecs = delay_secs * 1000;
1066 struct perf_evlist *evlist = menu->b.priv; 1066 struct perf_evlist *evlist = menu->b.priv;
1067 struct perf_evsel *pos; 1067 struct perf_evsel *pos;
1068 const char *ev_name, *title = "Available samples"; 1068 const char *ev_name, *title = "Available samples";
@@ -1072,13 +1072,8 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1072 "ESC: exit, ENTER|->: Browse histograms") < 0) 1072 "ESC: exit, ENTER|->: Browse histograms") < 0)
1073 return -1; 1073 return -1;
1074 1074
1075 if (timer != NULL)
1076 newtFormSetTimer(menu->b.form, delay_msecs);
1077
1078 ui_browser__add_exit_keys(&menu->b, exit_keys);
1079
1080 while (1) { 1075 while (1) {
1081 key = ui_browser__run(&menu->b); 1076 key = ui_browser__run(&menu->b, delay_secs);
1082 1077
1083 switch (key) { 1078 switch (key) {
1084 case -1: 1079 case -1:
@@ -1090,44 +1085,53 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
1090 if (!menu->selection) 1085 if (!menu->selection)
1091 continue; 1086 continue;
1092 pos = menu->selection; 1087 pos = menu->selection;
1093 perf_evlist__set_selected(evlist, pos);
1094browse_hists: 1088browse_hists:
1089 perf_evlist__set_selected(evlist, pos);
1090 /*
1091 * Give the calling tool a chance to populate the non
1092 * default evsel resorted hists tree.
1093 */
1094 if (timer)
1095 timer(arg);
1095 ev_name = event_name(pos); 1096 ev_name = event_name(pos);
1096 key = perf_evsel__hists_browse(pos, nr_events, help, 1097 key = perf_evsel__hists_browse(pos, nr_events, help,
1097 ev_name, true, timer, 1098 ev_name, true, timer,
1098 arg, delay_secs); 1099 arg, delay_secs);
1099 ui_browser__show_title(&menu->b, title); 1100 ui_browser__show_title(&menu->b, title);
1100 break; 1101 switch (key) {
1102 case NEWT_KEY_TAB:
1103 if (pos->node.next == &evlist->entries)
1104 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1105 else
1106 pos = list_entry(pos->node.next, struct perf_evsel, node);
1107 goto browse_hists;
1108 case NEWT_KEY_UNTAB:
1109 if (pos->node.prev == &evlist->entries)
1110 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1111 else
1112 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1113 goto browse_hists;
1114 case NEWT_KEY_ESCAPE:
1115 if (!ui__dialog_yesno("Do you really want to exit?"))
1116 continue;
1117 /* Fall thru */
1118 case 'q':
1119 case CTRL('c'):
1120 goto out;
1121 default:
1122 continue;
1123 }
1101 case NEWT_KEY_LEFT: 1124 case NEWT_KEY_LEFT:
1102 continue; 1125 continue;
1103 case NEWT_KEY_ESCAPE: 1126 case NEWT_KEY_ESCAPE:
1104 if (!ui__dialog_yesno("Do you really want to exit?")) 1127 if (!ui__dialog_yesno("Do you really want to exit?"))
1105 continue; 1128 continue;
1106 /* Fall thru */ 1129 /* Fall thru */
1107 default:
1108 goto out;
1109 }
1110
1111 switch (key) {
1112 case NEWT_KEY_TAB:
1113 if (pos->node.next == &evlist->entries)
1114 pos = list_entry(evlist->entries.next, struct perf_evsel, node);
1115 else
1116 pos = list_entry(pos->node.next, struct perf_evsel, node);
1117 perf_evlist__set_selected(evlist, pos);
1118 goto browse_hists;
1119 case NEWT_KEY_UNTAB:
1120 if (pos->node.prev == &evlist->entries)
1121 pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
1122 else
1123 pos = list_entry(pos->node.prev, struct perf_evsel, node);
1124 perf_evlist__set_selected(evlist, pos);
1125 goto browse_hists;
1126 case 'q': 1130 case 'q':
1127 case CTRL('c'): 1131 case CTRL('c'):
1128 goto out; 1132 goto out;
1129 default: 1133 default:
1130 break; 1134 continue;
1131 } 1135 }
1132 } 1136 }
1133 1137
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index 8462bffe20bc..6905bcc8be2d 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -1,5 +1,6 @@
1#include "../libslang.h" 1#include "../libslang.h"
2#include <elf.h> 2#include <elf.h>
3#include <newt.h>
3#include <inttypes.h> 4#include <inttypes.h>
4#include <sys/ttydefaults.h> 5#include <sys/ttydefaults.h>
5#include <ctype.h> 6#include <ctype.h>
@@ -108,11 +109,8 @@ static int map_browser__run(struct map_browser *self)
108 verbose ? "" : "restart with -v to use") < 0) 109 verbose ? "" : "restart with -v to use") < 0)
109 return -1; 110 return -1;
110 111
111 if (verbose)
112 ui_browser__add_exit_key(&self->b, '/');
113
114 while (1) { 112 while (1) {
115 key = ui_browser__run(&self->b); 113 key = ui_browser__run(&self->b, 0);
116 114
117 if (verbose && key == '/') 115 if (verbose && key == '/')
118 map_browser__search(self); 116 map_browser__search(self);
diff --git a/tools/perf/util/ui/helpline.h b/tools/perf/util/ui/helpline.h
index ab6028d0c401..809975759080 100644
--- a/tools/perf/util/ui/helpline.h
+++ b/tools/perf/util/ui/helpline.h
@@ -1,6 +1,8 @@
1#ifndef _PERF_UI_HELPLINE_H_ 1#ifndef _PERF_UI_HELPLINE_H_
2#define _PERF_UI_HELPLINE_H_ 1 2#define _PERF_UI_HELPLINE_H_ 1
3 3
4#include <stdio.h>
5
4void ui_helpline__init(void); 6void ui_helpline__init(void);
5void ui_helpline__pop(void); 7void ui_helpline__pop(void);
6void ui_helpline__push(const char *msg); 8void ui_helpline__push(const char *msg);