aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-02-08 10:27:39 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-02-08 12:03:36 -0500
commitce6f4fab4059cd72638a0cfa596a8ee2c79c1c8e (patch)
tree00416d7a54d9ef265b9358022e804217dcb5d870 /tools/perf
parente3087b80aa0bceda9863f33307460f3ba79f2b15 (diff)
perf annotate: Move locking to struct annotation
Since we'll need it when implementing the live annotate TUI browser. This also simplifies things a bit by having the list head for the source code to be in the dynamicly allocated part of struct annotation, that way we don't have to pass it around, it can be found from the struct symbol that is passed everywhere. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-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 }