diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-06-15 22:29:51 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-06-16 09:34:38 -0400 |
commit | 5c24b67aae72f54c5d2a6898be4bae9726df63bb (patch) | |
tree | 14cf53530c0b85b7e1cb5599c62be9a059ab978b | |
parent | 35a23ff928b066b00a826d0a9ed9411b8ab479ef (diff) |
perf tools: Replace map->referenced & maps->removed_maps with map->refcnt
Use just reference counts, so that when no more hist_entry instances
references a map and the thread instance goes away by processing a
PERF_RECORD_EXIT, we can delete the maps.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-oym7lfhcc7ss6xpz44h7nbxs@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/hist.c | 37 | ||||
-rw-r--r-- | tools/perf/util/map.c | 58 | ||||
-rw-r--r-- | tools/perf/util/map.h | 10 |
3 files changed, 32 insertions, 73 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f53d017c7c22..6f28d53d4e46 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -313,8 +313,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, | |||
313 | memset(&he->stat, 0, sizeof(he->stat)); | 313 | memset(&he->stat, 0, sizeof(he->stat)); |
314 | } | 314 | } |
315 | 315 | ||
316 | if (he->ms.map) | 316 | map__get(he->ms.map); |
317 | he->ms.map->referenced = true; | ||
318 | 317 | ||
319 | if (he->branch_info) { | 318 | if (he->branch_info) { |
320 | /* | 319 | /* |
@@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, | |||
324 | */ | 323 | */ |
325 | he->branch_info = malloc(sizeof(*he->branch_info)); | 324 | he->branch_info = malloc(sizeof(*he->branch_info)); |
326 | if (he->branch_info == NULL) { | 325 | if (he->branch_info == NULL) { |
326 | map__zput(he->ms.map); | ||
327 | free(he->stat_acc); | 327 | free(he->stat_acc); |
328 | free(he); | 328 | free(he); |
329 | return NULL; | 329 | return NULL; |
@@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, | |||
332 | memcpy(he->branch_info, template->branch_info, | 332 | memcpy(he->branch_info, template->branch_info, |
333 | sizeof(*he->branch_info)); | 333 | sizeof(*he->branch_info)); |
334 | 334 | ||
335 | if (he->branch_info->from.map) | 335 | map__get(he->branch_info->from.map); |
336 | he->branch_info->from.map->referenced = true; | 336 | map__get(he->branch_info->to.map); |
337 | if (he->branch_info->to.map) | ||
338 | he->branch_info->to.map->referenced = true; | ||
339 | } | 337 | } |
340 | 338 | ||
341 | if (he->mem_info) { | 339 | if (he->mem_info) { |
342 | if (he->mem_info->iaddr.map) | 340 | map__get(he->mem_info->iaddr.map); |
343 | he->mem_info->iaddr.map->referenced = true; | 341 | map__get(he->mem_info->daddr.map); |
344 | if (he->mem_info->daddr.map) | ||
345 | he->mem_info->daddr.map->referenced = true; | ||
346 | } | 342 | } |
347 | 343 | ||
348 | if (symbol_conf.use_callchain) | 344 | if (symbol_conf.use_callchain) |
@@ -407,9 +403,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, | |||
407 | * the history counter to increment. | 403 | * the history counter to increment. |
408 | */ | 404 | */ |
409 | if (he->ms.map != entry->ms.map) { | 405 | if (he->ms.map != entry->ms.map) { |
410 | he->ms.map = entry->ms.map; | 406 | map__put(he->ms.map); |
411 | if (he->ms.map) | 407 | he->ms.map = map__get(entry->ms.map); |
412 | he->ms.map->referenced = true; | ||
413 | } | 408 | } |
414 | goto out; | 409 | goto out; |
415 | } | 410 | } |
@@ -933,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) | |||
933 | void hist_entry__delete(struct hist_entry *he) | 928 | void hist_entry__delete(struct hist_entry *he) |
934 | { | 929 | { |
935 | thread__zput(he->thread); | 930 | thread__zput(he->thread); |
936 | zfree(&he->branch_info); | 931 | map__zput(he->ms.map); |
937 | zfree(&he->mem_info); | 932 | |
933 | if (he->branch_info) { | ||
934 | map__zput(he->branch_info->from.map); | ||
935 | map__zput(he->branch_info->to.map); | ||
936 | zfree(&he->branch_info); | ||
937 | } | ||
938 | |||
939 | if (he->mem_info) { | ||
940 | map__zput(he->mem_info->iaddr.map); | ||
941 | map__zput(he->mem_info->daddr.map); | ||
942 | zfree(&he->mem_info); | ||
943 | } | ||
944 | |||
938 | zfree(&he->stat_acc); | 945 | zfree(&he->stat_acc); |
939 | free_srcline(he->srcline); | 946 | free_srcline(he->srcline); |
940 | free_callchain(he->callchain); | 947 | free_callchain(he->callchain); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 1241ab989cf5..b5a5e9c02437 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -137,7 +137,6 @@ void map__init(struct map *map, enum map_type type, | |||
137 | map->unmap_ip = map__unmap_ip; | 137 | map->unmap_ip = map__unmap_ip; |
138 | RB_CLEAR_NODE(&map->rb_node); | 138 | RB_CLEAR_NODE(&map->rb_node); |
139 | map->groups = NULL; | 139 | map->groups = NULL; |
140 | map->referenced = false; | ||
141 | map->erange_warned = false; | 140 | map->erange_warned = false; |
142 | atomic_set(&map->refcnt, 1); | 141 | atomic_set(&map->refcnt, 1); |
143 | } | 142 | } |
@@ -439,7 +438,6 @@ static void maps__init(struct maps *maps) | |||
439 | { | 438 | { |
440 | maps->entries = RB_ROOT; | 439 | maps->entries = RB_ROOT; |
441 | pthread_rwlock_init(&maps->lock, NULL); | 440 | pthread_rwlock_init(&maps->lock, NULL); |
442 | INIT_LIST_HEAD(&maps->removed_maps); | ||
443 | } | 441 | } |
444 | 442 | ||
445 | void map_groups__init(struct map_groups *mg, struct machine *machine) | 443 | void map_groups__init(struct map_groups *mg, struct machine *machine) |
@@ -466,21 +464,10 @@ static void __maps__purge(struct maps *maps) | |||
466 | } | 464 | } |
467 | } | 465 | } |
468 | 466 | ||
469 | static void __maps__purge_removed_maps(struct maps *maps) | ||
470 | { | ||
471 | struct map *pos, *n; | ||
472 | |||
473 | list_for_each_entry_safe(pos, n, &maps->removed_maps, node) { | ||
474 | list_del_init(&pos->node); | ||
475 | map__put(pos); | ||
476 | } | ||
477 | } | ||
478 | |||
479 | static void maps__exit(struct maps *maps) | 467 | static void maps__exit(struct maps *maps) |
480 | { | 468 | { |
481 | pthread_rwlock_wrlock(&maps->lock); | 469 | pthread_rwlock_wrlock(&maps->lock); |
482 | __maps__purge(maps); | 470 | __maps__purge(maps); |
483 | __maps__purge_removed_maps(maps); | ||
484 | pthread_rwlock_unlock(&maps->lock); | 471 | pthread_rwlock_unlock(&maps->lock); |
485 | } | 472 | } |
486 | 473 | ||
@@ -499,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg) | |||
499 | for (i = 0; i < MAP__NR_TYPES; ++i) { | 486 | for (i = 0; i < MAP__NR_TYPES; ++i) { |
500 | if (maps__first(&mg->maps[i])) | 487 | if (maps__first(&mg->maps[i])) |
501 | return false; | 488 | return false; |
502 | if (!list_empty(&mg->maps[i].removed_maps)) | ||
503 | return false; | ||
504 | } | 489 | } |
505 | 490 | ||
506 | return true; | 491 | return true; |
@@ -621,7 +606,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, | |||
621 | return printed += maps__fprintf(&mg->maps[type], fp); | 606 | return printed += maps__fprintf(&mg->maps[type], fp); |
622 | } | 607 | } |
623 | 608 | ||
624 | static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) | 609 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) |
625 | { | 610 | { |
626 | size_t printed = 0, i; | 611 | size_t printed = 0, i; |
627 | for (i = 0; i < MAP__NR_TYPES; ++i) | 612 | for (i = 0; i < MAP__NR_TYPES; ++i) |
@@ -629,39 +614,6 @@ static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) | |||
629 | return printed; | 614 | return printed; |
630 | } | 615 | } |
631 | 616 | ||
632 | static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, | ||
633 | enum map_type type, FILE *fp) | ||
634 | { | ||
635 | struct map *pos; | ||
636 | size_t printed = 0; | ||
637 | |||
638 | list_for_each_entry(pos, &mg->maps[type].removed_maps, node) { | ||
639 | printed += fprintf(fp, "Map:"); | ||
640 | printed += map__fprintf(pos, fp); | ||
641 | if (verbose > 1) { | ||
642 | printed += dso__fprintf(pos->dso, type, fp); | ||
643 | printed += fprintf(fp, "--\n"); | ||
644 | } | ||
645 | } | ||
646 | return printed; | ||
647 | } | ||
648 | |||
649 | static size_t map_groups__fprintf_removed_maps(struct map_groups *mg, | ||
650 | FILE *fp) | ||
651 | { | ||
652 | size_t printed = 0, i; | ||
653 | for (i = 0; i < MAP__NR_TYPES; ++i) | ||
654 | printed += __map_groups__fprintf_removed_maps(mg, i, fp); | ||
655 | return printed; | ||
656 | } | ||
657 | |||
658 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) | ||
659 | { | ||
660 | size_t printed = map_groups__fprintf_maps(mg, fp); | ||
661 | printed += fprintf(fp, "Removed maps:\n"); | ||
662 | return printed + map_groups__fprintf_removed_maps(mg, fp); | ||
663 | } | ||
664 | |||
665 | static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) | 617 | static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) |
666 | { | 618 | { |
667 | struct rb_root *root; | 619 | struct rb_root *root; |
@@ -719,13 +671,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp | |||
719 | map__fprintf(after, fp); | 671 | map__fprintf(after, fp); |
720 | } | 672 | } |
721 | put_map: | 673 | put_map: |
722 | /* | 674 | map__put(pos); |
723 | * If we have references, just move them to a separate list. | ||
724 | */ | ||
725 | if (pos->referenced) | ||
726 | list_add_tail(&pos->node, &maps->removed_maps); | ||
727 | else | ||
728 | map__put(pos); | ||
729 | 675 | ||
730 | if (err) | 676 | if (err) |
731 | goto out; | 677 | goto out; |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index b8df09d94aca..d73e687b224e 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -34,7 +34,6 @@ struct map { | |||
34 | u64 start; | 34 | u64 start; |
35 | u64 end; | 35 | u64 end; |
36 | u8 /* enum map_type */ type; | 36 | u8 /* enum map_type */ type; |
37 | bool referenced; | ||
38 | bool erange_warned; | 37 | bool erange_warned; |
39 | u32 priv; | 38 | u32 priv; |
40 | u32 prot; | 39 | u32 prot; |
@@ -63,7 +62,6 @@ struct kmap { | |||
63 | struct maps { | 62 | struct maps { |
64 | struct rb_root entries; | 63 | struct rb_root entries; |
65 | pthread_rwlock_t lock; | 64 | pthread_rwlock_t lock; |
66 | struct list_head removed_maps; | ||
67 | }; | 65 | }; |
68 | 66 | ||
69 | struct map_groups { | 67 | struct map_groups { |
@@ -161,6 +159,14 @@ static inline struct map *map__get(struct map *map) | |||
161 | 159 | ||
162 | void map__put(struct map *map); | 160 | void map__put(struct map *map); |
163 | 161 | ||
162 | static inline void __map__zput(struct map **map) | ||
163 | { | ||
164 | map__put(*map); | ||
165 | *map = NULL; | ||
166 | } | ||
167 | |||
168 | #define map__zput(map) __map__zput(&map) | ||
169 | |||
164 | int map__overlap(struct map *l, struct map *r); | 170 | int map__overlap(struct map *l, struct map *r); |
165 | size_t map__fprintf(struct map *map, FILE *fp); | 171 | size_t map__fprintf(struct map *map, FILE *fp); |
166 | size_t map__fprintf_dsoname(struct map *map, FILE *fp); | 172 | size_t map__fprintf_dsoname(struct map *map, FILE *fp); |