diff options
| -rw-r--r-- | tools/perf/util/ui/browsers/annotate.c | 102 |
1 files changed, 77 insertions, 25 deletions
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index d2156aebd4f1..73e78ef38a50 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c | |||
| @@ -17,6 +17,7 @@ static void ui__error_window(const char *fmt, ...) | |||
| 17 | struct annotate_browser { | 17 | struct annotate_browser { |
| 18 | struct ui_browser b; | 18 | struct ui_browser b; |
| 19 | struct rb_root entries; | 19 | struct rb_root entries; |
| 20 | struct rb_node *curr_hot; | ||
| 20 | }; | 21 | }; |
| 21 | 22 | ||
| 22 | struct objdump_line_rb_node { | 23 | struct objdump_line_rb_node { |
| @@ -110,12 +111,83 @@ static void objdump__insert_line(struct rb_root *self, | |||
| 110 | rb_insert_color(&line->rb_node, self); | 111 | rb_insert_color(&line->rb_node, self); |
| 111 | } | 112 | } |
| 112 | 113 | ||
| 114 | static void annotate_browser__set_top(struct annotate_browser *self, | ||
| 115 | struct rb_node *nd) | ||
| 116 | { | ||
| 117 | struct objdump_line_rb_node *rbpos; | ||
| 118 | struct objdump_line *pos; | ||
| 119 | unsigned back; | ||
| 120 | |||
| 121 | ui_browser__refresh_dimensions(&self->b); | ||
| 122 | back = self->b.height / 2; | ||
| 123 | rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node); | ||
| 124 | pos = ((struct objdump_line *)rbpos) - 1; | ||
| 125 | self->b.top_idx = self->b.index = rbpos->idx; | ||
| 126 | |||
| 127 | while (self->b.top_idx != 0 && back != 0) { | ||
| 128 | pos = list_entry(pos->node.prev, struct objdump_line, node); | ||
| 129 | |||
| 130 | --self->b.top_idx; | ||
| 131 | --back; | ||
| 132 | } | ||
| 133 | |||
| 134 | self->b.top = pos; | ||
| 135 | self->curr_hot = nd; | ||
| 136 | } | ||
| 137 | |||
| 138 | static int annotate_browser__run(struct annotate_browser *self, | ||
| 139 | struct newtExitStruct *es) | ||
| 140 | { | ||
| 141 | struct rb_node *nd; | ||
| 142 | struct hist_entry *he = self->b.priv; | ||
| 143 | |||
| 144 | if (ui_browser__show(&self->b, he->ms.sym->name) < 0) | ||
| 145 | return -1; | ||
| 146 | |||
| 147 | ui_helpline__fpush("<- or ESC: exit, TAB/shift+TAB: cycle thru samples"); | ||
| 148 | newtFormAddHotKey(self->b.form, NEWT_KEY_LEFT); | ||
| 149 | |||
| 150 | nd = self->curr_hot; | ||
| 151 | if (nd) { | ||
| 152 | newtFormAddHotKey(self->b.form, NEWT_KEY_TAB); | ||
| 153 | newtFormAddHotKey(self->b.form, NEWT_KEY_UNTAB); | ||
| 154 | } | ||
| 155 | |||
| 156 | while (1) { | ||
| 157 | ui_browser__run(&self->b, es); | ||
| 158 | |||
| 159 | if (es->reason != NEWT_EXIT_HOTKEY) | ||
| 160 | break; | ||
| 161 | |||
| 162 | switch (es->u.key) { | ||
| 163 | case NEWT_KEY_TAB: | ||
| 164 | nd = rb_prev(nd); | ||
| 165 | if (nd == NULL) | ||
| 166 | nd = rb_last(&self->entries); | ||
| 167 | annotate_browser__set_top(self, nd); | ||
| 168 | break; | ||
| 169 | case NEWT_KEY_UNTAB: | ||
| 170 | nd = rb_next(nd); | ||
| 171 | if (nd == NULL) | ||
| 172 | nd = rb_first(&self->entries); | ||
| 173 | annotate_browser__set_top(self, nd); | ||
| 174 | break; | ||
| 175 | default: | ||
| 176 | goto out; | ||
| 177 | } | ||
| 178 | } | ||
| 179 | out: | ||
| 180 | newtFormDestroy(self->b.form); | ||
| 181 | newtPopWindow(); | ||
| 182 | ui_helpline__pop(); | ||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 113 | int hist_entry__tui_annotate(struct hist_entry *self) | 186 | int hist_entry__tui_annotate(struct hist_entry *self) |
| 114 | { | 187 | { |
| 115 | struct newtExitStruct es; | 188 | struct newtExitStruct es; |
| 116 | struct objdump_line *pos, *n; | 189 | struct objdump_line *pos, *n; |
| 117 | struct objdump_line_rb_node *rbpos; | 190 | struct objdump_line_rb_node *rbpos; |
| 118 | struct rb_node *nd; | ||
| 119 | LIST_HEAD(head); | 191 | LIST_HEAD(head); |
| 120 | struct annotate_browser browser = { | 192 | struct annotate_browser browser = { |
| 121 | .b = { | 193 | .b = { |
| @@ -156,35 +228,15 @@ int hist_entry__tui_annotate(struct hist_entry *self) | |||
| 156 | /* | 228 | /* |
| 157 | * Position the browser at the hottest line. | 229 | * Position the browser at the hottest line. |
| 158 | */ | 230 | */ |
| 159 | nd = rb_last(&browser.entries); | 231 | browser.curr_hot = rb_last(&browser.entries); |
| 160 | if (nd != NULL) { | 232 | if (browser.curr_hot) |
| 161 | unsigned back; | 233 | annotate_browser__set_top(&browser, browser.curr_hot); |
| 162 | |||
| 163 | ui_browser__refresh_dimensions(&browser.b); | ||
| 164 | back = browser.b.height / 2; | ||
| 165 | rbpos = rb_entry(nd, struct objdump_line_rb_node, rb_node); | ||
| 166 | pos = ((struct objdump_line *)rbpos) - 1; | ||
| 167 | browser.b.top_idx = browser.b.index = rbpos->idx; | ||
| 168 | |||
| 169 | while (browser.b.top_idx != 0 && back != 0) { | ||
| 170 | pos = list_entry(pos->node.prev, struct objdump_line, node); | ||
| 171 | |||
| 172 | --browser.b.top_idx; | ||
| 173 | --back; | ||
| 174 | } | ||
| 175 | |||
| 176 | browser.b.top = pos; | ||
| 177 | } | ||
| 178 | 234 | ||
| 179 | browser.b.width += 18; /* Percentage */ | 235 | browser.b.width += 18; /* Percentage */ |
| 180 | ui_browser__show(&browser.b, self->ms.sym->name); | 236 | ret = annotate_browser__run(&browser, &es); |
| 181 | ret = ui_browser__run(&browser.b, &es); | ||
| 182 | newtFormDestroy(browser.b.form); | ||
| 183 | newtPopWindow(); | ||
| 184 | list_for_each_entry_safe(pos, n, &head, node) { | 237 | list_for_each_entry_safe(pos, n, &head, node) { |
| 185 | list_del(&pos->node); | 238 | list_del(&pos->node); |
| 186 | objdump_line__free(pos); | 239 | objdump_line__free(pos); |
| 187 | } | 240 | } |
| 188 | ui_helpline__pop(); | ||
| 189 | return ret; | 241 | return ret; |
| 190 | } | 242 | } |
