aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-annotate.c14
-rw-r--r--tools/perf/builtin-report.c5
-rw-r--r--tools/perf/builtin-top.c67
-rw-r--r--tools/perf/util/annotate.c85
-rw-r--r--tools/perf/util/annotate.h34
-rw-r--r--tools/perf/util/hist.c5
-rw-r--r--tools/perf/util/hist.h3
-rw-r--r--tools/perf/util/top.h6
-rw-r--r--tools/perf/util/ui/browsers/annotate.c18
9 files changed, 126 insertions, 111 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index ea6a1165956f..427182953fd7 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -62,7 +62,8 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
62 * All aggregated on the first sym_hist. 62 * All aggregated on the first sym_hist.
63 */ 63 */
64 struct annotation *notes = symbol__annotation(he->ms.sym); 64 struct annotation *notes = symbol__annotation(he->ms.sym);
65 if (notes->histograms == NULL && symbol__alloc_hist(he->ms.sym, 1) < 0) 65 if (notes->src == NULL &&
66 symbol__alloc_hist(he->ms.sym, 1) < 0)
66 return -ENOMEM; 67 return -ENOMEM;
67 68
68 return hist_entry__inc_addr_samples(he, 0, al->addr); 69 return hist_entry__inc_addr_samples(he, 0, al->addr);
@@ -77,7 +78,8 @@ static int process_sample_event(union perf_event *event,
77{ 78{
78 struct addr_location al; 79 struct addr_location al;
79 80
80 if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 81 if (perf_event__preprocess_sample(event, session, &al, sample,
82 symbol__annotate_init) < 0) {
81 pr_warning("problem processing %d event, skipping it.\n", 83 pr_warning("problem processing %d event, skipping it.\n",
82 event->header.type); 84 event->header.type);
83 return -1; 85 return -1;
@@ -111,7 +113,7 @@ static void hists__find_annotations(struct hists *self)
111 goto find_next; 113 goto find_next;
112 114
113 notes = symbol__annotation(he->ms.sym); 115 notes = symbol__annotation(he->ms.sym);
114 if (notes->histograms == NULL) { 116 if (notes->src == NULL) {
115find_next: 117find_next:
116 if (key == KEY_LEFT) 118 if (key == KEY_LEFT)
117 nd = rb_prev(nd); 119 nd = rb_prev(nd);
@@ -142,11 +144,11 @@ find_next:
142 nd = rb_next(nd); 144 nd = rb_next(nd);
143 /* 145 /*
144 * Since we have a hist_entry per IP for the same 146 * Since we have a hist_entry per IP for the same
145 * symbol, free he->ms.sym->histogram to signal we already 147 * symbol, free he->ms.sym->src to signal we already
146 * processed this symbol. 148 * processed this symbol.
147 */ 149 */
148 free(notes->histograms); 150 free(notes->src);
149 notes->histograms = NULL; 151 notes->src = NULL;
150 } 152 }
151 } 153 }
152} 154}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index de06bf55efff..f403aced4cba 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -123,7 +123,7 @@ static int perf_session__add_hist_entry(struct perf_session *session,
123 * All aggregated on the first sym_hist. 123 * All aggregated on the first sym_hist.
124 */ 124 */
125 struct annotation *notes = symbol__annotation(he->ms.sym); 125 struct annotation *notes = symbol__annotation(he->ms.sym);
126 if (notes->histograms == NULL && 126 if (notes->src == NULL &&
127 symbol__alloc_hist(he->ms.sym, 1) < 0) 127 symbol__alloc_hist(he->ms.sym, 1) < 0)
128 err = -ENOMEM; 128 err = -ENOMEM;
129 else 129 else
@@ -166,7 +166,8 @@ static int process_sample_event(union perf_event *event,
166 struct addr_location al; 166 struct addr_location al;
167 struct perf_event_attr *attr; 167 struct perf_event_attr *attr;
168 168
169 if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) { 169 if (perf_event__preprocess_sample(event, session, &al, sample,
170 symbol__annotate_init) < 0) {
170 fprintf(stderr, "problem processing %d event, skipping it.\n", 171 fprintf(stderr, "problem processing %d event, skipping it.\n",
171 event->header.type); 172 event->header.type);
172 return -1; 173 return -1;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index b790673cb0aa..7dbf22d096b8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -139,7 +139,7 @@ static void sig_winch_handler(int sig __used)
139static int parse_source(struct sym_entry *syme) 139static int parse_source(struct sym_entry *syme)
140{ 140{
141 struct symbol *sym; 141 struct symbol *sym;
142 struct sym_entry_source *source; 142 struct annotation *notes;
143 struct map *map; 143 struct map *map;
144 int err = -1; 144 int err = -1;
145 145
@@ -152,39 +152,35 @@ static int parse_source(struct sym_entry *syme)
152 /* 152 /*
153 * We can't annotate with just /proc/kallsyms 153 * We can't annotate with just /proc/kallsyms
154 */ 154 */
155 if (map->dso->origin == DSO__ORIG_KERNEL) 155 if (map->dso->origin == DSO__ORIG_KERNEL) {
156 pr_err("Can't annotate %s: No vmlinux file was found in the "
157 "path\n", sym->name);
158 sleep(1);
156 return -1; 159 return -1;
157
158 if (syme->src == NULL) {
159 syme->src = zalloc(sizeof(*source));
160 if (syme->src == NULL)
161 return -1;
162 pthread_mutex_init(&syme->src->lock, NULL);
163 INIT_LIST_HEAD(&syme->src->head);
164 } 160 }
165 161
166 source = syme->src; 162 notes = symbol__annotation(sym);
167 163 if (notes->src != NULL) {
168 if (symbol__annotation(sym)->histograms != NULL) { 164 pthread_mutex_lock(&notes->lock);
169 pthread_mutex_lock(&source->lock);
170 goto out_assign; 165 goto out_assign;
171 } 166 }
172 167
173 pthread_mutex_lock(&source->lock); 168 pthread_mutex_lock(&notes->lock);
174 169
175 if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) { 170 if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
176 pr_err("Not enough memory for annotating '%s' symbol!\n", 171 pr_err("Not enough memory for annotating '%s' symbol!\n",
177 sym->name); 172 sym->name);
173 sleep(1);
178 goto out_unlock; 174 goto out_unlock;
179 } 175 }
180 176
181 err = symbol__annotate(sym, syme->map, &source->head, 0); 177 err = symbol__annotate(sym, syme->map, 0);
182 if (err == 0) { 178 if (err == 0) {
183out_assign: 179out_assign:
184 sym_filter_entry = syme; 180 sym_filter_entry = syme;
185 } 181 }
186out_unlock: 182out_unlock:
187 pthread_mutex_unlock(&source->lock); 183 pthread_mutex_unlock(&notes->lock);
188 return err; 184 return err;
189} 185}
190 186
@@ -196,20 +192,27 @@ static void __zero_source_counters(struct sym_entry *syme)
196 192
197static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip) 193static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
198{ 194{
195 struct annotation *notes;
196 struct symbol *sym;
197
199 if (syme != sym_filter_entry) 198 if (syme != sym_filter_entry)
200 return; 199 return;
201 200
202 if (pthread_mutex_trylock(&syme->src->lock)) 201 sym = sym_entry__symbol(syme);
202 notes = symbol__annotation(sym);
203
204 if (pthread_mutex_trylock(&notes->lock))
203 return; 205 return;
204 206
205 ip = syme->map->map_ip(syme->map, ip); 207 ip = syme->map->map_ip(syme->map, ip);
206 symbol__inc_addr_samples(sym_entry__symbol(syme), syme->map, counter, ip); 208 symbol__inc_addr_samples(sym, syme->map, counter, ip);
207 209
208 pthread_mutex_unlock(&syme->src->lock); 210 pthread_mutex_unlock(&notes->lock);
209} 211}
210 212
211static void show_details(struct sym_entry *syme) 213static void show_details(struct sym_entry *syme)
212{ 214{
215 struct annotation *notes;
213 struct symbol *symbol; 216 struct symbol *symbol;
214 int more; 217 int more;
215 218
@@ -217,24 +220,26 @@ static void show_details(struct sym_entry *syme)
217 return; 220 return;
218 221
219 symbol = sym_entry__symbol(syme); 222 symbol = sym_entry__symbol(syme);
220 if (!syme->src || symbol__annotation(symbol)->histograms == NULL) 223 notes = symbol__annotation(symbol);
221 return; 224
225 pthread_mutex_lock(&notes->lock);
226
227 if (notes->src == NULL)
228 goto out_unlock;
222 229
223 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name); 230 printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
224 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter); 231 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
225 232
226 pthread_mutex_lock(&syme->src->lock); 233 more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx,
227 more = symbol__annotate_printf(symbol, syme->map, &syme->src->head, 234 0, sym_pcnt_filter, top.print_entries);
228 top.sym_evsel->idx, 0, sym_pcnt_filter,
229 top.print_entries);
230 if (top.zero) 235 if (top.zero)
231 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx); 236 symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
232 else 237 else
233 symbol__annotate_decay_histogram(symbol, &syme->src->head, 238 symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx);
234 top.sym_evsel->idx);
235 pthread_mutex_unlock(&syme->src->lock);
236 if (more != 0) 239 if (more != 0)
237 printf("%d lines not displayed, maybe increase display entries [e]\n", more); 240 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
241out_unlock:
242 pthread_mutex_unlock(&notes->lock);
238} 243}
239 244
240static const char CONSOLE_CLEAR[] = ""; 245static const char CONSOLE_CLEAR[] = "";
@@ -372,10 +377,8 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
372 377
373 /* zero counters of active symbol */ 378 /* zero counters of active symbol */
374 if (syme) { 379 if (syme) {
375 pthread_mutex_lock(&syme->src->lock);
376 __zero_source_counters(syme); 380 __zero_source_counters(syme);
377 *target = NULL; 381 *target = NULL;
378 pthread_mutex_unlock(&syme->src->lock);
379 } 382 }
380 383
381 fprintf(stdout, "\n%s: ", msg); 384 fprintf(stdout, "\n%s: ", msg);
@@ -554,10 +557,8 @@ static void handle_keypress(struct perf_session *session, int c)
554 else { 557 else {
555 struct sym_entry *syme = sym_filter_entry; 558 struct sym_entry *syme = sym_filter_entry;
556 559
557 pthread_mutex_lock(&syme->src->lock);
558 sym_filter_entry = NULL; 560 sym_filter_entry = NULL;
559 __zero_source_counters(syme); 561 __zero_source_counters(syme);
560 pthread_mutex_unlock(&syme->src->lock);
561 } 562 }
562 break; 563 break;
563 case 'U': 564 case 'U':
@@ -653,7 +654,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
653 654
654 syme = symbol__priv(sym); 655 syme = symbol__priv(sym);
655 syme->map = map; 656 syme->map = map;
656 syme->src = NULL; 657 symbol__annotate_init(map, sym);
657 658
658 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { 659 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
659 /* schedule initial sym_filter_entry setup */ 660 /* schedule initial sym_filter_entry setup */
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 6db435167d74..c777bdaf91da 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -14,25 +14,39 @@
14#include "symbol.h" 14#include "symbol.h"
15#include "debug.h" 15#include "debug.h"
16#include "annotate.h" 16#include "annotate.h"
17#include <pthread.h>
17 18
18int symbol__alloc_hist(struct symbol *sym, int nevents) 19int symbol__annotate_init(struct map *map __used, struct symbol *sym)
19{ 20{
20 struct annotation *notes = symbol__annotation(sym); 21 struct annotation *notes = symbol__annotation(sym);
22 pthread_mutex_init(&notes->lock, NULL);
23 return 0;
24}
21 25
22 notes->sizeof_sym_hist = (sizeof(*notes->histograms) + 26int symbol__alloc_hist(struct symbol *sym, int nevents)
27{
28 struct annotation *notes = symbol__annotation(sym);
29 size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
23 (sym->end - sym->start) * sizeof(u64)); 30 (sym->end - sym->start) * sizeof(u64));
24 notes->histograms = calloc(nevents, notes->sizeof_sym_hist); 31
25 notes->nr_histograms = nevents; 32 notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
26 return notes->histograms == NULL ? -1 : 0; 33 if (notes->src == NULL)
34 return -1;
35 notes->src->sizeof_sym_hist = sizeof_sym_hist;
36 notes->src->nr_histograms = nevents;
37 INIT_LIST_HEAD(&notes->src->source);
38 return 0;
27} 39}
28 40
29void symbol__annotate_zero_histograms(struct symbol *sym) 41void symbol__annotate_zero_histograms(struct symbol *sym)
30{ 42{
31 struct annotation *notes = symbol__annotation(sym); 43 struct annotation *notes = symbol__annotation(sym);
32 44
33 if (notes->histograms != NULL) 45 pthread_mutex_lock(&notes->lock);
34 memset(notes->histograms, 0, 46 if (notes->src != NULL)
35 notes->nr_histograms * notes->sizeof_sym_hist); 47 memset(notes->src->histograms, 0,
48 notes->src->nr_histograms * notes->src->sizeof_sym_hist);
49 pthread_mutex_unlock(&notes->lock);
36} 50}
37 51
38int symbol__inc_addr_samples(struct symbol *sym, struct map *map, 52int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
@@ -43,7 +57,7 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
43 struct sym_hist *h; 57 struct sym_hist *h;
44 58
45 notes = symbol__annotation(sym); 59 notes = symbol__annotation(sym);
46 if (notes->histograms == NULL) 60 if (notes->src == NULL)
47 return -ENOMEM; 61 return -ENOMEM;
48 62
49 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr)); 63 pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
@@ -95,8 +109,7 @@ struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
95 return NULL; 109 return NULL;
96} 110}
97 111
98static int objdump_line__print(struct objdump_line *oline, 112static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
99 struct list_head *head, struct symbol *sym,
100 int evidx, u64 len, int min_pcnt, 113 int evidx, u64 len, int min_pcnt,
101 int printed, int max_lines) 114 int printed, int max_lines)
102{ 115{
@@ -109,10 +122,12 @@ static int objdump_line__print(struct objdump_line *oline,
109 double percent = 0.0; 122 double percent = 0.0;
110 const char *color; 123 const char *color;
111 struct annotation *notes = symbol__annotation(sym); 124 struct annotation *notes = symbol__annotation(sym);
112 struct source_line *src_line = notes->src_line; 125 struct source_line *src_line = notes->src->lines;
113 struct sym_hist *h = annotation__histogram(notes, evidx); 126 struct sym_hist *h = annotation__histogram(notes, evidx);
114 s64 offset = oline->offset; 127 s64 offset = oline->offset;
115 struct objdump_line *next = objdump__get_next_ip_line(head, oline); 128 struct objdump_line *next;
129
130 next = objdump__get_next_ip_line(&notes->src->source, oline);
116 131
117 while (offset < (s64)len && 132 while (offset < (s64)len &&
118 (next == NULL || offset < next->offset)) { 133 (next == NULL || offset < next->offset)) {
@@ -166,9 +181,10 @@ static int objdump_line__print(struct objdump_line *oline,
166 return 0; 181 return 0;
167} 182}
168 183
169static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file, 184static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
170 struct list_head *head, size_t privsize) 185 FILE *file, size_t privsize)
171{ 186{
187 struct annotation *notes = symbol__annotation(sym);
172 struct objdump_line *objdump_line; 188 struct objdump_line *objdump_line;
173 char *line = NULL, *tmp, *tmp2, *c; 189 char *line = NULL, *tmp, *tmp2, *c;
174 size_t line_len; 190 size_t line_len;
@@ -222,13 +238,12 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE
222 free(line); 238 free(line);
223 return -1; 239 return -1;
224 } 240 }
225 objdump__add_line(head, objdump_line); 241 objdump__add_line(&notes->src->source, objdump_line);
226 242
227 return 0; 243 return 0;
228} 244}
229 245
230int symbol__annotate(struct symbol *sym, struct map *map, 246int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
231 struct list_head *head, size_t privsize)
232{ 247{
233 struct dso *dso = map->dso; 248 struct dso *dso = map->dso;
234 char *filename = dso__build_id_filename(dso, NULL, 0); 249 char *filename = dso__build_id_filename(dso, NULL, 0);
@@ -297,7 +312,7 @@ fallback:
297 goto out_free_filename; 312 goto out_free_filename;
298 313
299 while (!feof(file)) 314 while (!feof(file))
300 if (symbol__parse_objdump_line(sym, map, file, head, privsize) < 0) 315 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
301 break; 316 break;
302 317
303 pclose(file); 318 pclose(file);
@@ -330,14 +345,14 @@ static void insert_source_line(struct rb_root *root, struct source_line *src_lin
330static void symbol__free_source_line(struct symbol *sym, int len) 345static void symbol__free_source_line(struct symbol *sym, int len)
331{ 346{
332 struct annotation *notes = symbol__annotation(sym); 347 struct annotation *notes = symbol__annotation(sym);
333 struct source_line *src_line = notes->src_line; 348 struct source_line *src_line = notes->src->lines;
334 int i; 349 int i;
335 350
336 for (i = 0; i < len; i++) 351 for (i = 0; i < len; i++)
337 free(src_line[i].path); 352 free(src_line[i].path);
338 353
339 free(src_line); 354 free(src_line);
340 notes->src_line = NULL; 355 notes->src->lines = NULL;
341} 356}
342 357
343/* Get the filename:line for the colored entries */ 358/* Get the filename:line for the colored entries */
@@ -355,8 +370,8 @@ static int symbol__get_source_line(struct symbol *sym, struct map *map,
355 if (!h->sum) 370 if (!h->sum)
356 return 0; 371 return 0;
357 372
358 src_line = notes->src_line = calloc(len, sizeof(struct source_line)); 373 src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
359 if (!notes->src_line) 374 if (!notes->src->lines)
360 return -1; 375 return -1;
361 376
362 start = map->unmap_ip(map, sym->start); 377 start = map->unmap_ip(map, sym->start);
@@ -436,12 +451,12 @@ static void symbol__annotate_hits(struct symbol *sym, int evidx)
436 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum); 451 printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
437} 452}
438 453
439int symbol__annotate_printf(struct symbol *sym, struct map *map, 454int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
440 struct list_head *head, int evidx, bool full_paths, 455 bool full_paths, int min_pcnt, int max_lines)
441 int min_pcnt, int max_lines)
442{ 456{
443 struct dso *dso = map->dso; 457 struct dso *dso = map->dso;
444 const char *filename = dso->long_name, *d_filename; 458 const char *filename = dso->long_name, *d_filename;
459 struct annotation *notes = symbol__annotation(sym);
445 struct objdump_line *pos; 460 struct objdump_line *pos;
446 int printed = 2; 461 int printed = 2;
447 int more = 0; 462 int more = 0;
@@ -460,8 +475,8 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
460 if (verbose) 475 if (verbose)
461 symbol__annotate_hits(sym, evidx); 476 symbol__annotate_hits(sym, evidx);
462 477
463 list_for_each_entry(pos, head, node) { 478 list_for_each_entry(pos, &notes->src->source, node) {
464 switch (objdump_line__print(pos, head, sym, evidx, len, min_pcnt, 479 switch (objdump_line__print(pos, sym, evidx, len, min_pcnt,
465 printed, max_lines)) { 480 printed, max_lines)) {
466 case 0: 481 case 0:
467 ++printed; 482 ++printed;
@@ -485,11 +500,10 @@ void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
485 struct annotation *notes = symbol__annotation(sym); 500 struct annotation *notes = symbol__annotation(sym);
486 struct sym_hist *h = annotation__histogram(notes, evidx); 501 struct sym_hist *h = annotation__histogram(notes, evidx);
487 502
488 memset(h, 0, notes->sizeof_sym_hist); 503 memset(h, 0, notes->src->sizeof_sym_hist);
489} 504}
490 505
491void symbol__annotate_decay_histogram(struct symbol *sym, 506void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
492 struct list_head *head, int evidx)
493{ 507{
494 struct annotation *notes = symbol__annotation(sym); 508 struct annotation *notes = symbol__annotation(sym);
495 struct sym_hist *h = annotation__histogram(notes, evidx); 509 struct sym_hist *h = annotation__histogram(notes, evidx);
@@ -497,7 +511,7 @@ void symbol__annotate_decay_histogram(struct symbol *sym,
497 511
498 h->sum = 0; 512 h->sum = 0;
499 513
500 list_for_each_entry(pos, head, node) { 514 list_for_each_entry(pos, &notes->src->source, node) {
501 if (pos->offset != -1) { 515 if (pos->offset != -1) {
502 h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8; 516 h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
503 h->sum += h->addr[pos->offset]; 517 h->sum += h->addr[pos->offset];
@@ -522,10 +536,9 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
522 struct dso *dso = map->dso; 536 struct dso *dso = map->dso;
523 const char *filename = dso->long_name; 537 const char *filename = dso->long_name;
524 struct rb_root source_line = RB_ROOT; 538 struct rb_root source_line = RB_ROOT;
525 LIST_HEAD(head);
526 u64 len; 539 u64 len;
527 540
528 if (symbol__annotate(sym, map, &head, 0) < 0) 541 if (symbol__annotate(sym, map, 0) < 0)
529 return -1; 542 return -1;
530 543
531 len = sym->end - sym->start; 544 len = sym->end - sym->start;
@@ -536,12 +549,12 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
536 print_summary(&source_line, filename); 549 print_summary(&source_line, filename);
537 } 550 }
538 551
539 symbol__annotate_printf(sym, map, &head, evidx, full_paths, 552 symbol__annotate_printf(sym, map, evidx, full_paths,
540 min_pcnt, max_lines); 553 min_pcnt, max_lines);
541 if (print_lines) 554 if (print_lines)
542 symbol__free_source_line(sym, len); 555 symbol__free_source_line(sym, len);
543 556
544 objdump_line_list__purge(&head); 557 objdump_line_list__purge(&symbol__annotation(sym)->src->source);
545 558
546 return 0; 559 return 0;
547} 560}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index bc08b36a713a..b237c8678c22 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -28,22 +28,29 @@ struct source_line {
28 char *path; 28 char *path;
29}; 29};
30 30
31/** struct annotation - symbols with hits have this attached as in sannotation 31/** struct annotated_source - symbols with hits have this attached as in sannotation
32 * 32 *
33 * @histogram: Array of addr hit histograms per event being monitored 33 * @histogram: Array of addr hit histograms per event being monitored
34 * @src_line: If 'print_lines' is specified, per source code line percentages 34 * @lines: If 'print_lines' is specified, per source code line percentages
35 * @source: source parsed from objdump -dS
35 * 36 *
36 * src_line is allocated, percentages calculated and all sorted by percentage 37 * lines is allocated, percentages calculated and all sorted by percentage
37 * when the annotation is about to be presented, so the percentages are for 38 * when the annotation is about to be presented, so the percentages are for
38 * one of the entries in the histogram array, i.e. for the event/counter being 39 * one of the entries in the histogram array, i.e. for the event/counter being
39 * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate 40 * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
40 * returns. 41 * returns.
41 */ 42 */
42struct annotation { 43struct annotated_source {
43 struct source_line *src_line; 44 struct list_head source;
44 struct sym_hist *histograms; 45 struct source_line *lines;
45 int nr_histograms; 46 int nr_histograms;
46 int sizeof_sym_hist; 47 int sizeof_sym_hist;
48 struct sym_hist histograms[0];
49};
50
51struct annotation {
52 pthread_mutex_t lock;
53 struct annotated_source *src;
47}; 54};
48 55
49struct sannotation { 56struct sannotation {
@@ -53,7 +60,8 @@ struct sannotation {
53 60
54static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx) 61static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
55{ 62{
56 return ((void *)notes->histograms) + (notes->sizeof_sym_hist * idx); 63 return (((void *)&notes->src->histograms) +
64 (notes->src->sizeof_sym_hist * idx));
57} 65}
58 66
59static inline struct annotation *symbol__annotation(struct symbol *sym) 67static inline struct annotation *symbol__annotation(struct symbol *sym)
@@ -67,14 +75,12 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
67int symbol__alloc_hist(struct symbol *sym, int nevents); 75int symbol__alloc_hist(struct symbol *sym, int nevents);
68void symbol__annotate_zero_histograms(struct symbol *sym); 76void symbol__annotate_zero_histograms(struct symbol *sym);
69 77
70int symbol__annotate(struct symbol *sym, struct map *map, 78int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
71 struct list_head *head, size_t privsize); 79int symbol__annotate_init(struct map *map __used, struct symbol *sym);
72int symbol__annotate_printf(struct symbol *sym, struct map *map, 80int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
73 struct list_head *head, int evidx, bool full_paths, 81 bool full_paths, int min_pcnt, int max_lines);
74 int min_pcnt, int max_lines);
75void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 82void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
76void symbol__annotate_decay_histogram(struct symbol *sym, 83void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
77 struct list_head *head, int evidx);
78void objdump_line_list__purge(struct list_head *head); 84void objdump_line_list__purge(struct list_head *head);
79 85
80int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, 86int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index bac5ab684967..3f437236f193 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -955,10 +955,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
955 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 955 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
956} 956}
957 957
958int hist_entry__annotate(struct hist_entry *he, struct list_head *head, 958int hist_entry__annotate(struct hist_entry *he, size_t privsize)
959 size_t privsize)
960{ 959{
961 return symbol__annotate(he->ms.sym, he->ms.map, head, privsize); 960 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
962} 961}
963 962
964void hists__inc_nr_events(struct hists *self, u32 type) 963void hists__inc_nr_events(struct hists *self, u32 type)
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2c6cdae6a764..37c79089de09 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -78,8 +78,7 @@ size_t hists__fprintf(struct hists *self, struct hists *pair,
78 bool show_displacement, FILE *fp); 78 bool show_displacement, FILE *fp);
79 79
80int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 80int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
81int hist_entry__annotate(struct hist_entry *self, struct list_head *head, 81int hist_entry__annotate(struct hist_entry *self, size_t privsize);
82 size_t privsize);
83 82
84void hists__filter_by_dso(struct hists *self, const struct dso *dso); 83void hists__filter_by_dso(struct hists *self, const struct dso *dso);
85void hists__filter_by_thread(struct hists *self, const struct thread *thread); 84void hists__filter_by_thread(struct hists *self, const struct thread *thread);
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 62e32939f3d1..4f769f47e19a 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -11,11 +11,6 @@
11struct perf_evlist; 11struct perf_evlist;
12struct perf_evsel; 12struct perf_evsel;
13 13
14struct sym_entry_source {
15 struct list_head head;
16 pthread_mutex_t lock;
17};
18
19struct sym_entry { 14struct sym_entry {
20 struct rb_node rb_node; 15 struct rb_node rb_node;
21 struct list_head node; 16 struct list_head node;
@@ -24,7 +19,6 @@ struct sym_entry {
24 int skip; 19 int skip;
25 u8 origin; 20 u8 origin;
26 struct map *map; 21 struct map *map;
27 struct sym_entry_source *src;
28 unsigned long count[0]; 22 unsigned long count[0];
29}; 23};
30 24
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 8d8a16895af7..1aa39658539c 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -60,7 +60,6 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
60} 60}
61 61
62static double objdump_line__calc_percent(struct objdump_line *self, 62static double objdump_line__calc_percent(struct objdump_line *self,
63 struct list_head *head,
64 struct symbol *sym, int evidx) 63 struct symbol *sym, int evidx)
65{ 64{
66 double percent = 0.0; 65 double percent = 0.0;
@@ -69,11 +68,12 @@ static double objdump_line__calc_percent(struct objdump_line *self,
69 int len = sym->end - sym->start; 68 int len = sym->end - sym->start;
70 unsigned int hits = 0; 69 unsigned int hits = 0;
71 struct annotation *notes = symbol__annotation(sym); 70 struct annotation *notes = symbol__annotation(sym);
72 struct source_line *src_line = notes->src_line; 71 struct source_line *src_line = notes->src->lines;
73 struct sym_hist *h = annotation__histogram(notes, evidx); 72 struct sym_hist *h = annotation__histogram(notes, evidx);
74 s64 offset = self->offset; 73 s64 offset = self->offset;
75 struct objdump_line *next = objdump__get_next_ip_line(head, self); 74 struct objdump_line *next;
76 75
76 next = objdump__get_next_ip_line(&notes->src->source, self);
77 while (offset < (s64)len && 77 while (offset < (s64)len &&
78 (next == NULL || offset < next->offset)) { 78 (next == NULL || offset < next->offset)) {
79 if (src_line) { 79 if (src_line) {
@@ -192,10 +192,10 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
192{ 192{
193 struct objdump_line *pos, *n; 193 struct objdump_line *pos, *n;
194 struct objdump_line_rb_node *rbpos; 194 struct objdump_line_rb_node *rbpos;
195 LIST_HEAD(head); 195 struct annotation *notes = symbol__annotation(sym);
196 struct annotate_browser browser = { 196 struct annotate_browser browser = {
197 .b = { 197 .b = {
198 .entries = &head, 198 .entries = &notes->src->source,
199 .refresh = ui_browser__list_head_refresh, 199 .refresh = ui_browser__list_head_refresh,
200 .seek = ui_browser__list_head_seek, 200 .seek = ui_browser__list_head_seek,
201 .write = annotate_browser__write, 201 .write = annotate_browser__write,
@@ -210,20 +210,20 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
210 if (map->dso->annotate_warned) 210 if (map->dso->annotate_warned)
211 return -1; 211 return -1;
212 212
213 if (symbol__annotate(sym, map, &head, sizeof(*rbpos)) < 0) { 213 if (symbol__annotate(sym, map, sizeof(*rbpos)) < 0) {
214 ui__error_window(ui_helpline__last_msg); 214 ui__error_window(ui_helpline__last_msg);
215 return -1; 215 return -1;
216 } 216 }
217 217
218 ui_helpline__push("Press <- or ESC to exit"); 218 ui_helpline__push("Press <- or ESC to exit");
219 219
220 list_for_each_entry(pos, &head, node) { 220 list_for_each_entry(pos, &notes->src->source, node) {
221 size_t line_len = strlen(pos->line); 221 size_t line_len = strlen(pos->line);
222 if (browser.b.width < line_len) 222 if (browser.b.width < line_len)
223 browser.b.width = line_len; 223 browser.b.width = line_len;
224 rbpos = objdump_line__rb(pos); 224 rbpos = objdump_line__rb(pos);
225 rbpos->idx = browser.b.nr_entries++; 225 rbpos->idx = browser.b.nr_entries++;
226 rbpos->percent = objdump_line__calc_percent(pos, &head, sym, evidx); 226 rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
227 if (rbpos->percent < 0.01) 227 if (rbpos->percent < 0.01)
228 continue; 228 continue;
229 objdump__insert_line(&browser.entries, rbpos); 229 objdump__insert_line(&browser.entries, rbpos);
@@ -238,7 +238,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx)
238 238
239 browser.b.width += 18; /* Percentage */ 239 browser.b.width += 18; /* Percentage */
240 ret = annotate_browser__run(&browser); 240 ret = annotate_browser__run(&browser);
241 list_for_each_entry_safe(pos, n, &head, node) { 241 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
242 list_del(&pos->node); 242 list_del(&pos->node);
243 objdump_line__free(pos); 243 objdump_line__free(pos);
244 } 244 }