aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/ui/browsers/annotate.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/ui/browsers/annotate.c')
-rw-r--r--tools/perf/util/ui/browsers/annotate.c126
1 files changed, 90 insertions, 36 deletions
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index cfb5a27f15d..8c17a8730e4 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -6,6 +6,7 @@
6#include "../../sort.h" 6#include "../../sort.h"
7#include "../../symbol.h" 7#include "../../symbol.h"
8#include "../../annotate.h" 8#include "../../annotate.h"
9#include <pthread.h>
9 10
10static void ui__error_window(const char *fmt, ...) 11static void ui__error_window(const char *fmt, ...)
11{ 12{
@@ -138,46 +139,108 @@ static void annotate_browser__set_top(struct annotate_browser *self,
138 self->curr_hot = nd; 139 self->curr_hot = nd;
139} 140}
140 141
141static int annotate_browser__run(struct annotate_browser *self) 142static void annotate_browser__calc_percent(struct annotate_browser *browser,
143 int evidx)
142{ 144{
143 struct rb_node *nd; 145 struct symbol *sym = browser->b.priv;
146 struct annotation *notes = symbol__annotation(sym);
147 struct objdump_line *pos;
148
149 browser->entries = RB_ROOT;
150
151 pthread_mutex_lock(&notes->lock);
152
153 list_for_each_entry(pos, &notes->src->source, node) {
154 struct objdump_line_rb_node *rbpos = objdump_line__rb(pos);
155 rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
156 if (rbpos->percent < 0.01) {
157 RB_CLEAR_NODE(&rbpos->rb_node);
158 continue;
159 }
160 objdump__insert_line(&browser->entries, rbpos);
161 }
162 pthread_mutex_unlock(&notes->lock);
163
164 browser->curr_hot = rb_last(&browser->entries);
165}
166
167static int annotate_browser__run(struct annotate_browser *self, int evidx,
168 int refresh)
169{
170 struct rb_node *nd = NULL;
144 struct symbol *sym = self->b.priv; 171 struct symbol *sym = self->b.priv;
172 /*
173 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
174 * examining the exit key for this function.
175 */
176 int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
177 NEWT_KEY_RIGHT, 0 };
145 int key; 178 int key;
146 179
147 if (ui_browser__show(&self->b, sym->name, 180 if (ui_browser__show(&self->b, sym->name,
148 "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0) 181 "<-, -> or ESC: exit, TAB/shift+TAB: "
182 "cycle hottest lines, H: Hottest") < 0)
149 return -1; 183 return -1;
150 /* 184
151 * To allow builtin-annotate to cycle thru multiple symbols by 185 ui_browser__add_exit_keys(&self->b, exit_keys);
152 * examining the exit key for this function. 186 annotate_browser__calc_percent(self, evidx);
153 */ 187
154 ui_browser__add_exit_key(&self->b, NEWT_KEY_RIGHT); 188 if (self->curr_hot)
189 annotate_browser__set_top(self, self->curr_hot);
155 190
156 nd = self->curr_hot; 191 nd = self->curr_hot;
157 if (nd) { 192
158 int tabs[] = { NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0 }; 193 if (refresh != 0)
159 ui_browser__add_exit_keys(&self->b, tabs); 194 newtFormSetTimer(self->b.form, refresh);
160 }
161 195
162 while (1) { 196 while (1) {
163 key = ui_browser__run(&self->b); 197 key = ui_browser__run(&self->b);
164 198
199 if (refresh != 0) {
200 annotate_browser__calc_percent(self, evidx);
201 /*
202 * Current line focus got out of the list of most active
203 * lines, NULL it so that if TAB|UNTAB is pressed, we
204 * move to curr_hot (current hottest line).
205 */
206 if (nd != NULL && RB_EMPTY_NODE(nd))
207 nd = NULL;
208 }
209
165 switch (key) { 210 switch (key) {
211 case -1:
212 /*
213 * FIXME we need to check if it was
214 * es.reason == NEWT_EXIT_TIMER
215 */
216 if (refresh != 0)
217 symbol__annotate_decay_histogram(sym, evidx);
218 continue;
166 case NEWT_KEY_TAB: 219 case NEWT_KEY_TAB:
167 nd = rb_prev(nd); 220 if (nd != NULL) {
168 if (nd == NULL) 221 nd = rb_prev(nd);
169 nd = rb_last(&self->entries); 222 if (nd == NULL)
170 annotate_browser__set_top(self, nd); 223 nd = rb_last(&self->entries);
224 } else
225 nd = self->curr_hot;
171 break; 226 break;
172 case NEWT_KEY_UNTAB: 227 case NEWT_KEY_UNTAB:
173 nd = rb_next(nd); 228 if (nd != NULL)
174 if (nd == NULL) 229 nd = rb_next(nd);
175 nd = rb_first(&self->entries); 230 if (nd == NULL)
176 annotate_browser__set_top(self, nd); 231 nd = rb_first(&self->entries);
232 else
233 nd = self->curr_hot;
234 break;
235 case 'H':
236 nd = self->curr_hot;
177 break; 237 break;
178 default: 238 default:
179 goto out; 239 goto out;
180 } 240 }
241
242 if (nd != NULL)
243 annotate_browser__set_top(self, nd);
181 } 244 }
182out: 245out:
183 ui_browser__hide(&self->b); 246 ui_browser__hide(&self->b);
@@ -186,13 +249,13 @@ out:
186 249
187int hist_entry__tui_annotate(struct hist_entry *he, int evidx) 250int hist_entry__tui_annotate(struct hist_entry *he, int evidx)
188{ 251{
189 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx); 252 return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0);
190} 253}
191 254
192int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx) 255int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
256 int refresh)
193{ 257{
194 struct objdump_line *pos, *n; 258 struct objdump_line *pos, *n;
195 struct objdump_line_rb_node *rbpos;
196 struct annotation *notes = symbol__annotation(sym); 259 struct annotation *notes = symbol__annotation(sym);
197 struct annotate_browser browser = { 260 struct annotate_browser browser = {
198 .b = { 261 .b = {
@@ -211,7 +274,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
211 if (map->dso->annotate_warned) 274 if (map->dso->annotate_warned)
212 return -1; 275 return -1;
213 276
214 if (symbol__annotate(sym, map, sizeof(*rbpos)) < 0) { 277 if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
215 ui__error_window(ui_helpline__last_msg); 278 ui__error_window(ui_helpline__last_msg);
216 return -1; 279 return -1;
217 } 280 }
@@ -219,26 +282,17 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
219 ui_helpline__push("Press <- or ESC to exit"); 282 ui_helpline__push("Press <- or ESC to exit");
220 283
221 list_for_each_entry(pos, &notes->src->source, node) { 284 list_for_each_entry(pos, &notes->src->source, node) {
285 struct objdump_line_rb_node *rbpos;
222 size_t line_len = strlen(pos->line); 286 size_t line_len = strlen(pos->line);
287
223 if (browser.b.width < line_len) 288 if (browser.b.width < line_len)
224 browser.b.width = line_len; 289 browser.b.width = line_len;
225 rbpos = objdump_line__rb(pos); 290 rbpos = objdump_line__rb(pos);
226 rbpos->idx = browser.b.nr_entries++; 291 rbpos->idx = browser.b.nr_entries++;
227 rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
228 if (rbpos->percent < 0.01)
229 continue;
230 objdump__insert_line(&browser.entries, rbpos);
231 } 292 }
232 293
233 /*
234 * Position the browser at the hottest line.
235 */
236 browser.curr_hot = rb_last(&browser.entries);
237 if (browser.curr_hot)
238 annotate_browser__set_top(&browser, browser.curr_hot);
239
240 browser.b.width += 18; /* Percentage */ 294 browser.b.width += 18; /* Percentage */
241 ret = annotate_browser__run(&browser); 295 ret = annotate_browser__run(&browser, evidx, refresh);
242 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 296 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
243 list_del(&pos->node); 297 list_del(&pos->node);
244 objdump_line__free(pos); 298 objdump_line__free(pos);