From 5c24b67aae72f54c5d2a6898be4bae9726df63bb Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Mon, 15 Jun 2015 23:29:51 -0300 Subject: [PATCH] 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 Cc: Borislav Petkov Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-oym7lfhcc7ss6xpz44h7nbxs@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/hist.c | 37 ++++++++++++++++----------- tools/perf/util/map.c | 58 ++---------------------------------------- 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, memset(&he->stat, 0, sizeof(he->stat)); } - if (he->ms.map) - he->ms.map->referenced = true; + map__get(he->ms.map); if (he->branch_info) { /* @@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, */ he->branch_info = malloc(sizeof(*he->branch_info)); if (he->branch_info == NULL) { + map__zput(he->ms.map); free(he->stat_acc); free(he); return NULL; @@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, memcpy(he->branch_info, template->branch_info, sizeof(*he->branch_info)); - if (he->branch_info->from.map) - he->branch_info->from.map->referenced = true; - if (he->branch_info->to.map) - he->branch_info->to.map->referenced = true; + map__get(he->branch_info->from.map); + map__get(he->branch_info->to.map); } if (he->mem_info) { - if (he->mem_info->iaddr.map) - he->mem_info->iaddr.map->referenced = true; - if (he->mem_info->daddr.map) - he->mem_info->daddr.map->referenced = true; + map__get(he->mem_info->iaddr.map); + map__get(he->mem_info->daddr.map); } if (symbol_conf.use_callchain) @@ -407,9 +403,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, * the history counter to increment. */ if (he->ms.map != entry->ms.map) { - he->ms.map = entry->ms.map; - if (he->ms.map) - he->ms.map->referenced = true; + map__put(he->ms.map); + he->ms.map = map__get(entry->ms.map); } goto out; } @@ -933,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) void hist_entry__delete(struct hist_entry *he) { thread__zput(he->thread); - zfree(&he->branch_info); - zfree(&he->mem_info); + map__zput(he->ms.map); + + if (he->branch_info) { + map__zput(he->branch_info->from.map); + map__zput(he->branch_info->to.map); + zfree(&he->branch_info); + } + + if (he->mem_info) { + map__zput(he->mem_info->iaddr.map); + map__zput(he->mem_info->daddr.map); + zfree(&he->mem_info); + } + zfree(&he->stat_acc); free_srcline(he->srcline); 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, map->unmap_ip = map__unmap_ip; RB_CLEAR_NODE(&map->rb_node); map->groups = NULL; - map->referenced = false; map->erange_warned = false; atomic_set(&map->refcnt, 1); } @@ -439,7 +438,6 @@ static void maps__init(struct maps *maps) { maps->entries = RB_ROOT; pthread_rwlock_init(&maps->lock, NULL); - INIT_LIST_HEAD(&maps->removed_maps); } void map_groups__init(struct map_groups *mg, struct machine *machine) @@ -466,21 +464,10 @@ static void __maps__purge(struct maps *maps) } } -static void __maps__purge_removed_maps(struct maps *maps) -{ - struct map *pos, *n; - - list_for_each_entry_safe(pos, n, &maps->removed_maps, node) { - list_del_init(&pos->node); - map__put(pos); - } -} - static void maps__exit(struct maps *maps) { pthread_rwlock_wrlock(&maps->lock); __maps__purge(maps); - __maps__purge_removed_maps(maps); pthread_rwlock_unlock(&maps->lock); } @@ -499,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg) for (i = 0; i < MAP__NR_TYPES; ++i) { if (maps__first(&mg->maps[i])) return false; - if (!list_empty(&mg->maps[i].removed_maps)) - return false; } return true; @@ -621,7 +606,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, return printed += maps__fprintf(&mg->maps[type], fp); } -static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp) +size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) { size_t printed = 0, i; 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) return printed; } -static size_t __map_groups__fprintf_removed_maps(struct map_groups *mg, - enum map_type type, FILE *fp) -{ - struct map *pos; - size_t printed = 0; - - list_for_each_entry(pos, &mg->maps[type].removed_maps, node) { - printed += fprintf(fp, "Map:"); - printed += map__fprintf(pos, fp); - if (verbose > 1) { - printed += dso__fprintf(pos->dso, type, fp); - printed += fprintf(fp, "--\n"); - } - } - return printed; -} - -static size_t map_groups__fprintf_removed_maps(struct map_groups *mg, - FILE *fp) -{ - size_t printed = 0, i; - for (i = 0; i < MAP__NR_TYPES; ++i) - printed += __map_groups__fprintf_removed_maps(mg, i, fp); - return printed; -} - -size_t map_groups__fprintf(struct map_groups *mg, FILE *fp) -{ - size_t printed = map_groups__fprintf_maps(mg, fp); - printed += fprintf(fp, "Removed maps:\n"); - return printed + map_groups__fprintf_removed_maps(mg, fp); -} - static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) { struct rb_root *root; @@ -719,13 +671,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp map__fprintf(after, fp); } put_map: - /* - * If we have references, just move them to a separate list. - */ - if (pos->referenced) - list_add_tail(&pos->node, &maps->removed_maps); - else - map__put(pos); + map__put(pos); if (err) 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 { u64 start; u64 end; u8 /* enum map_type */ type; - bool referenced; bool erange_warned; u32 priv; u32 prot; @@ -63,7 +62,6 @@ struct kmap { struct maps { struct rb_root entries; pthread_rwlock_t lock; - struct list_head removed_maps; }; struct map_groups { @@ -161,6 +159,14 @@ static inline struct map *map__get(struct map *map) void map__put(struct map *map); +static inline void __map__zput(struct map **map) +{ + map__put(*map); + *map = NULL; +} + +#define map__zput(map) __map__zput(&map) + int map__overlap(struct map *l, struct map *r); size_t map__fprintf(struct map *map, FILE *fp); size_t map__fprintf_dsoname(struct map *map, FILE *fp); -- 2.20.1