diff options
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r-- | tools/perf/util/annotate.c | 85 |
1 files changed, 49 insertions, 36 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 6db435167d7..c777bdaf91d 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 | ||
18 | int symbol__alloc_hist(struct symbol *sym, int nevents) | 19 | int 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(¬es->lock, NULL); | ||
23 | return 0; | ||
24 | } | ||
21 | 25 | ||
22 | notes->sizeof_sym_hist = (sizeof(*notes->histograms) + | 26 | int 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(¬es->src->source); | ||
38 | return 0; | ||
27 | } | 39 | } |
28 | 40 | ||
29 | void symbol__annotate_zero_histograms(struct symbol *sym) | 41 | void 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(¬es->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(¬es->lock); | ||
36 | } | 50 | } |
37 | 51 | ||
38 | int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | 52 | int 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 | ||
98 | static int objdump_line__print(struct objdump_line *oline, | 112 | static 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(¬es->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 | ||
169 | static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, FILE *file, | 184 | static 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(¬es->src->source, objdump_line); |
226 | 242 | ||
227 | return 0; | 243 | return 0; |
228 | } | 244 | } |
229 | 245 | ||
230 | int symbol__annotate(struct symbol *sym, struct map *map, | 246 | int 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 | |||
330 | static void symbol__free_source_line(struct symbol *sym, int len) | 345 | static 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 | ||
439 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 454 | int 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, ¬es->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 | ||
491 | void symbol__annotate_decay_histogram(struct symbol *sym, | 506 | void 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, ¬es->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 | } |