diff options
Diffstat (limited to 'tools')
-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 | } |