diff options
Diffstat (limited to 'tools/perf/util/ui/browsers/annotate.c')
-rw-r--r-- | tools/perf/util/ui/browsers/annotate.c | 126 |
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 | ||
10 | static void ui__error_window(const char *fmt, ...) | 11 | static 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 | ||
141 | static int annotate_browser__run(struct annotate_browser *self) | 142 | static 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(¬es->lock); | ||
152 | |||
153 | list_for_each_entry(pos, ¬es->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(¬es->lock); | ||
163 | |||
164 | browser->curr_hot = rb_last(&browser->entries); | ||
165 | } | ||
166 | |||
167 | static 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 | } |
182 | out: | 245 | out: |
183 | ui_browser__hide(&self->b); | 246 | ui_browser__hide(&self->b); |
@@ -186,13 +249,13 @@ out: | |||
186 | 249 | ||
187 | int hist_entry__tui_annotate(struct hist_entry *he, int evidx) | 250 | int 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 | ||
192 | int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx) | 255 | int 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, ¬es->src->source, node) { | 284 | list_for_each_entry(pos, ¬es->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, ¬es->src->source, node) { | 296 | list_for_each_entry_safe(pos, n, ¬es->src->source, node) { |
243 | list_del(&pos->node); | 297 | list_del(&pos->node); |
244 | objdump_line__free(pos); | 298 | objdump_line__free(pos); |