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"
13 #include "../../evlist.h"
14 #include "../../hist.h"
15 #include "../../sort.h"
16 #include "../../symbol.h"
17 #include "../../top.h"
19 struct perf_top_browser
{
22 struct sym_entry
*selection
;
29 static void perf_top_browser__write(struct ui_browser
*browser
, void *entry
, int row
)
31 struct perf_top_browser
*top_browser
= container_of(browser
, struct perf_top_browser
, b
);
32 struct sym_entry
*syme
= rb_entry(entry
, struct sym_entry
, rb_node
);
33 bool current_entry
= ui_browser__is_current_entry(browser
, row
);
34 struct symbol
*symbol
= sym_entry__symbol(syme
);
35 struct perf_top
*top
= browser
->priv
;
36 int width
= browser
->width
;
39 pcnt
= 100.0 - (100.0 * ((top_browser
->sum_ksamples
- syme
->snap_count
) /
40 top_browser
->sum_ksamples
));
41 ui_browser__set_percent_color(browser
, pcnt
, current_entry
);
43 if (top
->evlist
->nr_entries
== 1 || !top
->display_weighted
) {
44 slsmg_printf("%20.2f ", syme
->weight
);
47 slsmg_printf("%9.1f %10ld ", syme
->weight
, syme
->snap_count
);
51 slsmg_printf("%4.1f%%", pcnt
);
55 slsmg_printf(" %016" PRIx64
, symbol
->start
);
59 slsmg_printf(" %-*.*s ", top_browser
->sym_width
, top_browser
->sym_width
,
61 width
-= top_browser
->sym_width
;
62 slsmg_write_nstring(width
>= syme
->map
->dso
->long_name_len
?
63 syme
->map
->dso
->long_name
:
64 syme
->map
->dso
->short_name
, width
);
67 top_browser
->selection
= syme
;
70 static void perf_top_browser__update_rb_tree(struct perf_top_browser
*browser
)
72 struct perf_top
*top
= browser
->b
.priv
;
73 u64 top_idx
= browser
->b
.top_idx
;
75 browser
->root
= RB_ROOT
;
76 browser
->b
.top
= NULL
;
77 browser
->sum_ksamples
= perf_top__decay_samples(top
, &browser
->root
);
78 perf_top__find_widths(top
, &browser
->root
, &browser
->dso_width
,
79 &browser
->dso_short_width
,
81 if (browser
->sym_width
+ browser
->dso_width
> browser
->b
.width
- 29) {
82 browser
->dso_width
= browser
->dso_short_width
;
83 if (browser
->sym_width
+ browser
->dso_width
> browser
->b
.width
- 29)
84 browser
->sym_width
= browser
->b
.width
- browser
->dso_width
- 29;
88 * Adjust the ui_browser indexes since the entries in the browser->root
89 * rb_tree may have changed, then seek it from start, so that we get a
90 * possible new top of the screen.
92 browser
->b
.nr_entries
= top
->rb_entries
;
94 if (top_idx
>= browser
->b
.nr_entries
) {
95 if (browser
->b
.height
>= browser
->b
.nr_entries
)
96 top_idx
= browser
->b
.nr_entries
- browser
->b
.height
;
101 if (browser
->b
.index
>= top_idx
+ browser
->b
.height
)
102 browser
->b
.index
= top_idx
+ browser
->b
.index
- browser
->b
.top_idx
;
104 if (browser
->b
.index
>= browser
->b
.nr_entries
)
105 browser
->b
.index
= browser
->b
.nr_entries
- 1;
107 browser
->b
.top_idx
= top_idx
;
108 browser
->b
.seek(&browser
->b
, top_idx
, SEEK_SET
);
111 static void perf_top_browser__annotate(struct perf_top_browser
*browser
)
113 struct sym_entry
*syme
= browser
->selection
;
114 struct symbol
*sym
= sym_entry__symbol(syme
);
115 struct annotation
*notes
= symbol__annotation(sym
);
116 struct perf_top
*top
= browser
->b
.priv
;
118 if (notes
->src
!= NULL
)
121 pthread_mutex_lock(¬es
->lock
);
123 top
->sym_filter_entry
= NULL
;
125 if (symbol__alloc_hist(sym
, top
->evlist
->nr_entries
) < 0) {
126 pr_err("Not enough memory for annotating '%s' symbol!\n",
128 pthread_mutex_unlock(¬es
->lock
);
132 top
->sym_filter_entry
= syme
;
134 pthread_mutex_unlock(¬es
->lock
);
136 symbol__tui_annotate(sym
, syme
->map
, 0, top
->delay_secs
* 1000);
139 static int perf_top_browser__run(struct perf_top_browser
*browser
)
143 struct perf_top
*top
= browser
->b
.priv
;
144 int delay_msecs
= top
->delay_secs
* 1000;
145 int exit_keys
[] = { 'a', NEWT_KEY_ENTER
, NEWT_KEY_RIGHT
, 0, };
147 perf_top_browser__update_rb_tree(browser
);
148 perf_top__header_snprintf(top
, title
, sizeof(title
));
149 perf_top__reset_sample_counters(top
);
151 if (ui_browser__show(&browser
->b
, title
,
152 "ESC: exit, ENTER|->|a: Live Annotate") < 0)
155 newtFormSetTimer(browser
->b
.form
, delay_msecs
);
156 ui_browser__add_exit_keys(&browser
->b
, exit_keys
);
159 key
= ui_browser__run(&browser
->b
);
163 /* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
164 perf_top_browser__update_rb_tree(browser
);
165 perf_top__header_snprintf(top
, title
, sizeof(title
));
166 perf_top__reset_sample_counters(top
);
167 ui_browser__set_color(&browser
->b
, NEWT_COLORSET_ROOT
);
169 slsmg_write_nstring(title
, browser
->b
.width
);
174 if (browser
->selection
)
175 perf_top_browser__annotate(browser
);
182 ui_browser__hide(&browser
->b
);
186 int perf_top__tui_browser(struct perf_top
*top
)
188 struct perf_top_browser browser
= {
190 .entries
= &browser
.root
,
191 .refresh
= ui_browser__rb_tree_refresh
,
192 .seek
= ui_browser__rb_tree_seek
,
193 .write
= perf_top_browser__write
,
198 ui_helpline__push("Press <- or ESC to exit");
199 return perf_top_browser__run(&browser
);