2 * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
4 * Parts came from builtin-{top,stat,record}.c, see those files for further
7 * Released under the GPL v2. (and only v2, not any later version)
9 #include "../browser.h"
10 #include "../../annotate.h"
11 #include "../helpline.h"
12 #include "../libslang.h"
14 #include "../../evlist.h"
15 #include "../../hist.h"
16 #include "../../sort.h"
17 #include "../../symbol.h"
18 #include "../../top.h"
20 struct perf_top_browser
{
23 struct sym_entry
*selection
;
30 static void perf_top_browser__write(struct ui_browser
*browser
, void *entry
, int row
)
32 struct perf_top_browser
*top_browser
= container_of(browser
, struct perf_top_browser
, b
);
33 struct sym_entry
*syme
= rb_entry(entry
, struct sym_entry
, rb_node
);
34 bool current_entry
= ui_browser__is_current_entry(browser
, row
);
35 struct symbol
*symbol
= sym_entry__symbol(syme
);
36 struct perf_top
*top
= browser
->priv
;
37 int width
= browser
->width
;
40 pcnt
= 100.0 - (100.0 * ((top_browser
->sum_ksamples
- syme
->snap_count
) /
41 top_browser
->sum_ksamples
));
42 ui_browser__set_percent_color(browser
, pcnt
, current_entry
);
44 if (top
->evlist
->nr_entries
== 1 || !top
->display_weighted
) {
45 slsmg_printf("%20.2f ", syme
->weight
);
48 slsmg_printf("%9.1f %10ld ", syme
->weight
, syme
->snap_count
);
52 slsmg_printf("%4.1f%%", pcnt
);
56 slsmg_printf(" %016" PRIx64
, symbol
->start
);
60 slsmg_printf(" %-*.*s ", top_browser
->sym_width
, top_browser
->sym_width
,
62 width
-= top_browser
->sym_width
;
63 slsmg_write_nstring(width
>= syme
->map
->dso
->long_name_len
?
64 syme
->map
->dso
->long_name
:
65 syme
->map
->dso
->short_name
, width
);
68 top_browser
->selection
= syme
;
71 static void perf_top_browser__update_rb_tree(struct perf_top_browser
*browser
)
73 struct perf_top
*top
= browser
->b
.priv
;
74 u64 top_idx
= browser
->b
.top_idx
;
76 browser
->root
= RB_ROOT
;
77 browser
->b
.top
= NULL
;
78 browser
->sum_ksamples
= perf_top__decay_samples(top
, &browser
->root
);
82 if (top
->rb_entries
== 0)
85 perf_top__find_widths(top
, &browser
->root
, &browser
->dso_width
,
86 &browser
->dso_short_width
,
88 if (browser
->sym_width
+ browser
->dso_width
> browser
->b
.width
- 29) {
89 browser
->dso_width
= browser
->dso_short_width
;
90 if (browser
->sym_width
+ browser
->dso_width
> browser
->b
.width
- 29)
91 browser
->sym_width
= browser
->b
.width
- browser
->dso_width
- 29;
95 * Adjust the ui_browser indexes since the entries in the browser->root
96 * rb_tree may have changed, then seek it from start, so that we get a
97 * possible new top of the screen.
99 browser
->b
.nr_entries
= top
->rb_entries
;
101 if (top_idx
>= browser
->b
.nr_entries
) {
102 if (browser
->b
.height
>= browser
->b
.nr_entries
)
103 top_idx
= browser
->b
.nr_entries
- browser
->b
.height
;
108 if (browser
->b
.index
>= top_idx
+ browser
->b
.height
)
109 browser
->b
.index
= top_idx
+ browser
->b
.index
- browser
->b
.top_idx
;
111 if (browser
->b
.index
>= browser
->b
.nr_entries
)
112 browser
->b
.index
= browser
->b
.nr_entries
- 1;
114 browser
->b
.top_idx
= top_idx
;
115 browser
->b
.seek(&browser
->b
, top_idx
, SEEK_SET
);
118 static void perf_top_browser__annotate(struct perf_top_browser
*browser
)
120 struct sym_entry
*syme
= browser
->selection
;
121 struct symbol
*sym
= sym_entry__symbol(syme
);
122 struct annotation
*notes
= symbol__annotation(sym
);
123 struct perf_top
*top
= browser
->b
.priv
;
125 if (notes
->src
!= NULL
)
128 pthread_mutex_lock(¬es
->lock
);
130 top
->sym_filter_entry
= NULL
;
132 if (symbol__alloc_hist(sym
, top
->evlist
->nr_entries
) < 0) {
133 pr_err("Not enough memory for annotating '%s' symbol!\n",
135 pthread_mutex_unlock(¬es
->lock
);
139 top
->sym_filter_entry
= syme
;
141 pthread_mutex_unlock(¬es
->lock
);
143 symbol__tui_annotate(sym
, syme
->map
, 0, top
->delay_secs
* 1000);
146 static int perf_top_browser__run(struct perf_top_browser
*browser
)
150 struct perf_top
*top
= browser
->b
.priv
;
151 int delay_msecs
= top
->delay_secs
* 1000;
152 int exit_keys
[] = { 'a', NEWT_KEY_ENTER
, NEWT_KEY_RIGHT
, 0, };
154 perf_top_browser__update_rb_tree(browser
);
155 perf_top__header_snprintf(top
, title
, sizeof(title
));
156 perf_top__reset_sample_counters(top
);
158 if (ui_browser__show(&browser
->b
, title
,
159 "ESC: exit, ENTER|->|a: Live Annotate") < 0)
162 newtFormSetTimer(browser
->b
.form
, delay_msecs
);
163 ui_browser__add_exit_keys(&browser
->b
, exit_keys
);
166 key
= ui_browser__run(&browser
->b
);
170 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
171 perf_top_browser__update_rb_tree(browser
);
172 perf_top__header_snprintf(top
, title
, sizeof(title
));
173 perf_top__reset_sample_counters(top
);
174 ui_browser__set_color(&browser
->b
, NEWT_COLORSET_ROOT
);
176 slsmg_write_nstring(title
, browser
->b
.width
);
181 if (browser
->selection
)
182 perf_top_browser__annotate(browser
);
186 case NEWT_KEY_ESCAPE
:
187 if (!ui__dialog_yesno("Do you really want to exit?"))
195 ui_browser__hide(&browser
->b
);
199 int perf_top__tui_browser(struct perf_top
*top
)
201 struct perf_top_browser browser
= {
203 .entries
= &browser
.root
,
204 .refresh
= ui_browser__rb_tree_refresh
,
205 .seek
= ui_browser__rb_tree_seek
,
206 .write
= perf_top_browser__write
,
211 return perf_top_browser__run(&browser
);