~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to tools/perf/util/ui/browsers/annotate.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include "../browser.h"
2
2
#include "../helpline.h"
3
3
#include "../libslang.h"
 
4
#include "../../annotate.h"
4
5
#include "../../hist.h"
5
6
#include "../../sort.h"
6
7
#include "../../symbol.h"
 
8
#include <pthread.h>
7
9
 
8
10
static void ui__error_window(const char *fmt, ...)
9
11
{
42
44
                struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
43
45
                ui_browser__set_percent_color(self, olrb->percent, current_entry);
44
46
                slsmg_printf(" %7.2f ", olrb->percent);
45
 
                if (!current_entry)
46
 
                        ui_browser__set_color(self, HE_COLORSET_CODE);
47
47
        } else {
48
48
                ui_browser__set_percent_color(self, 0, current_entry);
49
49
                slsmg_write_nstring(" ", 9);
55
55
                slsmg_write_nstring(" ", width - 18);
56
56
        else
57
57
                slsmg_write_nstring(ol->line, width - 18);
 
58
 
 
59
        if (!current_entry)
 
60
                ui_browser__set_color(self, HE_COLORSET_CODE);
58
61
}
59
62
 
60
63
static double objdump_line__calc_percent(struct objdump_line *self,
61
 
                                         struct list_head *head,
62
 
                                         struct symbol *sym)
 
64
                                         struct symbol *sym, int evidx)
63
65
{
64
66
        double percent = 0.0;
65
67
 
66
68
        if (self->offset != -1) {
67
69
                int len = sym->end - sym->start;
68
70
                unsigned int hits = 0;
69
 
                struct sym_priv *priv = symbol__priv(sym);
70
 
                struct sym_ext *sym_ext = priv->ext;
71
 
                struct sym_hist *h = priv->hist;
 
71
                struct annotation *notes = symbol__annotation(sym);
 
72
                struct source_line *src_line = notes->src->lines;
 
73
                struct sym_hist *h = annotation__histogram(notes, evidx);
72
74
                s64 offset = self->offset;
73
 
                struct objdump_line *next = objdump__get_next_ip_line(head, self);
74
 
 
75
 
 
 
75
                struct objdump_line *next;
 
76
 
 
77
                next = objdump__get_next_ip_line(&notes->src->source, self);
76
78
                while (offset < (s64)len &&
77
79
                       (next == NULL || offset < next->offset)) {
78
 
                        if (sym_ext) {
79
 
                                percent += sym_ext[offset].percent;
 
80
                        if (src_line) {
 
81
                                percent += src_line[offset].percent;
80
82
                        } else
81
 
                                hits += h->ip[offset];
 
83
                                hits += h->addr[offset];
82
84
 
83
85
                        ++offset;
84
86
                }
85
 
 
86
 
                if (sym_ext == NULL && h->sum)
 
87
                /*
 
88
                 * If the percentage wasn't already calculated in
 
89
                 * symbol__get_source_line, do it now:
 
90
                 */
 
91
                if (src_line == NULL && h->sum)
87
92
                        percent = 100.0 * hits / h->sum;
88
93
        }
89
94
 
133
138
        self->curr_hot = nd;
134
139
}
135
140
 
136
 
static int annotate_browser__run(struct annotate_browser *self)
137
 
{
138
 
        struct rb_node *nd;
139
 
        struct hist_entry *he = self->b.priv;
 
141
static void annotate_browser__calc_percent(struct annotate_browser *browser,
 
142
                                           int evidx)
 
143
{
 
144
        struct symbol *sym = browser->b.priv;
 
145
        struct annotation *notes = symbol__annotation(sym);
 
146
        struct objdump_line *pos;
 
147
 
 
148
        browser->entries = RB_ROOT;
 
149
 
 
150
        pthread_mutex_lock(&notes->lock);
 
151
 
 
152
        list_for_each_entry(pos, &notes->src->source, node) {
 
153
                struct objdump_line_rb_node *rbpos = objdump_line__rb(pos);
 
154
                rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
 
155
                if (rbpos->percent < 0.01) {
 
156
                        RB_CLEAR_NODE(&rbpos->rb_node);
 
157
                        continue;
 
158
                }
 
159
                objdump__insert_line(&browser->entries, rbpos);
 
160
        }
 
161
        pthread_mutex_unlock(&notes->lock);
 
162
 
 
163
        browser->curr_hot = rb_last(&browser->entries);
 
164
}
 
165
 
 
166
static int annotate_browser__run(struct annotate_browser *self, int evidx,
 
167
                                 int refresh)
 
168
{
 
169
        struct rb_node *nd = NULL;
 
170
        struct symbol *sym = self->b.priv;
 
171
        /*
 
172
         * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
 
173
         * examining the exit key for this function.
 
174
         */
 
175
        int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
 
176
                            NEWT_KEY_RIGHT, 0 };
140
177
        int key;
141
178
 
142
 
        if (ui_browser__show(&self->b, he->ms.sym->name,
143
 
                             "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
 
179
        if (ui_browser__show(&self->b, sym->name,
 
180
                             "<-, -> or ESC: exit, TAB/shift+TAB: "
 
181
                             "cycle hottest lines, H: Hottest") < 0)
144
182
                return -1;
145
 
        /*
146
 
         * To allow builtin-annotate to cycle thru multiple symbols by
147
 
         * examining the exit key for this function.
148
 
         */
149
 
        ui_browser__add_exit_key(&self->b, NEWT_KEY_RIGHT);
 
183
 
 
184
        ui_browser__add_exit_keys(&self->b, exit_keys);
 
185
        annotate_browser__calc_percent(self, evidx);
 
186
 
 
187
        if (self->curr_hot)
 
188
                annotate_browser__set_top(self, self->curr_hot);
150
189
 
151
190
        nd = self->curr_hot;
152
 
        if (nd) {
153
 
                int tabs[] = { NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0 };
154
 
                ui_browser__add_exit_keys(&self->b, tabs);
155
 
        }
 
191
 
 
192
        if (refresh != 0)
 
193
                newtFormSetTimer(self->b.form, refresh);
156
194
 
157
195
        while (1) {
158
196
                key = ui_browser__run(&self->b);
159
197
 
 
198
                if (refresh != 0) {
 
199
                        annotate_browser__calc_percent(self, evidx);
 
200
                        /*
 
201
                         * Current line focus got out of the list of most active
 
202
                         * lines, NULL it so that if TAB|UNTAB is pressed, we
 
203
                         * move to curr_hot (current hottest line).
 
204
                         */
 
205
                        if (nd != NULL && RB_EMPTY_NODE(nd))
 
206
                                nd = NULL;
 
207
                }
 
208
 
160
209
                switch (key) {
 
210
                case -1:
 
211
                        /*
 
212
                         * FIXME we need to check if it was
 
213
                         * es.reason == NEWT_EXIT_TIMER
 
214
                         */
 
215
                        if (refresh != 0)
 
216
                                symbol__annotate_decay_histogram(sym, evidx);
 
217
                        continue;
161
218
                case NEWT_KEY_TAB:
162
 
                        nd = rb_prev(nd);
163
 
                        if (nd == NULL)
164
 
                                nd = rb_last(&self->entries);
165
 
                        annotate_browser__set_top(self, nd);
 
219
                        if (nd != NULL) {
 
220
                                nd = rb_prev(nd);
 
221
                                if (nd == NULL)
 
222
                                        nd = rb_last(&self->entries);
 
223
                        } else
 
224
                                nd = self->curr_hot;
166
225
                        break;
167
226
                case NEWT_KEY_UNTAB:
168
 
                        nd = rb_next(nd);
169
 
                        if (nd == NULL)
170
 
                                nd = rb_first(&self->entries);
171
 
                        annotate_browser__set_top(self, nd);
 
227
                        if (nd != NULL)
 
228
                                nd = rb_next(nd);
 
229
                                if (nd == NULL)
 
230
                                        nd = rb_first(&self->entries);
 
231
                        else
 
232
                                nd = self->curr_hot;
 
233
                        break;
 
234
                case 'H':
 
235
                        nd = self->curr_hot;
172
236
                        break;
173
237
                default:
174
238
                        goto out;
175
239
                }
 
240
 
 
241
                if (nd != NULL)
 
242
                        annotate_browser__set_top(self, nd);
176
243
        }
177
244
out:
178
245
        ui_browser__hide(&self->b);
179
246
        return key;
180
247
}
181
248
 
182
 
int hist_entry__tui_annotate(struct hist_entry *self)
 
249
int hist_entry__tui_annotate(struct hist_entry *he, int evidx)
 
250
{
 
251
        return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0);
 
252
}
 
253
 
 
254
int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 
255
                         int refresh)
183
256
{
184
257
        struct objdump_line *pos, *n;
185
 
        struct objdump_line_rb_node *rbpos;
186
 
        LIST_HEAD(head);
 
258
        struct annotation *notes;
187
259
        struct annotate_browser browser = {
188
260
                .b = {
189
 
                        .entries = &head,
190
261
                        .refresh = ui_browser__list_head_refresh,
191
262
                        .seek    = ui_browser__list_head_seek,
192
263
                        .write   = annotate_browser__write,
193
 
                        .priv    = self,
 
264
                        .priv    = sym,
194
265
                },
195
266
        };
196
267
        int ret;
197
268
 
198
 
        if (self->ms.sym == NULL)
199
 
                return -1;
200
 
 
201
 
        if (self->ms.map->dso->annotate_warned)
202
 
                return -1;
203
 
 
204
 
        if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) {
 
269
        if (sym == NULL)
 
270
                return -1;
 
271
 
 
272
        if (map->dso->annotate_warned)
 
273
                return -1;
 
274
 
 
275
        if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
205
276
                ui__error_window(ui_helpline__last_msg);
206
277
                return -1;
207
278
        }
208
279
 
209
280
        ui_helpline__push("Press <- or ESC to exit");
210
281
 
211
 
        list_for_each_entry(pos, &head, node) {
 
282
        notes = symbol__annotation(sym);
 
283
 
 
284
        list_for_each_entry(pos, &notes->src->source, node) {
 
285
                struct objdump_line_rb_node *rbpos;
212
286
                size_t line_len = strlen(pos->line);
 
287
 
213
288
                if (browser.b.width < line_len)
214
289
                        browser.b.width = line_len;
215
290
                rbpos = objdump_line__rb(pos);
216
291
                rbpos->idx = browser.b.nr_entries++;
217
 
                rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym);
218
 
                if (rbpos->percent < 0.01)
219
 
                        continue;
220
 
                objdump__insert_line(&browser.entries, rbpos);
221
292
        }
222
293
 
223
 
        /*
224
 
         * Position the browser at the hottest line.
225
 
         */
226
 
        browser.curr_hot = rb_last(&browser.entries);
227
 
        if (browser.curr_hot)
228
 
                annotate_browser__set_top(&browser, browser.curr_hot);
229
 
 
 
294
        browser.b.entries = &notes->src->source,
230
295
        browser.b.width += 18; /* Percentage */
231
 
        ret = annotate_browser__run(&browser);
232
 
        list_for_each_entry_safe(pos, n, &head, node) {
 
296
        ret = annotate_browser__run(&browser, evidx, refresh);
 
297
        list_for_each_entry_safe(pos, n, &notes->src->source, node) {
233
298
                list_del(&pos->node);
234
299
                objdump_line__free(pos);
235
300
        }