diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 6bf845758ae3..0c0e61cce577 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -759,7 +759,6 @@ void machine__destroy_kernel_maps(struct machine *machine) kmap->ref_reloc_sym = NULL; } - map__delete(machine->vmlinux_maps[type]); machine->vmlinux_maps[type] = NULL; } } @@ -1247,6 +1246,7 @@ int machine__process_mmap2_event(struct machine *machine, thread__insert_map(thread, map); thread__put(thread); + map__put(map); return 0; out_problem_map: @@ -1297,6 +1297,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event thread__insert_map(thread, map); thread__put(thread); + map__put(map); return 0; out_problem_map: diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 4d3a92d5dff3..af572322586d 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -139,6 +139,7 @@ void map__init(struct map *map, enum map_type type, map->groups = NULL; map->referenced = false; map->erange_warned = false; + atomic_set(&map->refcnt, 1); } struct map *map__new(struct machine *machine, u64 start, u64 len, @@ -229,6 +230,12 @@ void map__delete(struct map *map) free(map); } +void map__put(struct map *map) +{ + if (map && atomic_dec_and_test(&map->refcnt)) + map__delete(map); +} + void map__fixup_start(struct map *map) { struct rb_root *symbols = &map->dso->symbols[map->type]; @@ -448,7 +455,7 @@ static void __maps__purge(struct maps *maps) next = rb_next(&pos->rb_node); rb_erase_init(&pos->rb_node, root); - map__delete(pos); + map__put(pos); } } @@ -458,7 +465,7 @@ static void __maps__purge_removed_maps(struct maps *maps) list_for_each_entry_safe(pos, n, &maps->removed_maps, node) { list_del_init(&pos->node); - map__delete(pos); + map__put(pos); } } @@ -682,7 +689,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp if (before == NULL) { err = -ENOMEM; - goto move_map; + goto put_map; } before->end = map->start; @@ -696,7 +703,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp if (after == NULL) { err = -ENOMEM; - goto move_map; + goto put_map; } after->start = map->end; @@ -704,14 +711,14 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp if (verbose >= 2) map__fprintf(after, fp); } -move_map: +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__delete(pos); + map__put(pos); if (err) goto out; @@ -772,6 +779,7 @@ static void __maps__insert(struct maps *maps, struct map *map) rb_link_node(&map->rb_node, parent, p); rb_insert_color(&map->rb_node, &maps->entries); + map__get(map); } void maps__insert(struct maps *maps, struct map *map) @@ -784,6 +792,7 @@ void maps__insert(struct maps *maps, struct map *map) static void __maps__remove(struct maps *maps, struct map *map) { rb_erase_init(&map->rb_node, &maps->entries); + map__put(map); } void maps__remove(struct maps *maps, struct map *map) diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 6796f2785649..b8df09d94aca 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h @@ -52,6 +52,7 @@ struct map { struct dso *dso; struct map_groups *groups; + atomic_t refcnt; }; struct kmap { @@ -150,6 +151,16 @@ struct map *map__new(struct machine *machine, u64 start, u64 len, struct map *map__new2(u64 start, struct dso *dso, enum map_type type); void map__delete(struct map *map); struct map *map__clone(struct map *map); + +static inline struct map *map__get(struct map *map) +{ + if (map) + atomic_inc(&map->refcnt); + return map; +} + +void map__put(struct map *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); diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 32471d0839d1..b0b8a8080009 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -195,7 +195,7 @@ static void put_target_map(struct map *map, bool user) { if (map && user) { /* Only the user map needs to be released */ - map__delete(map); + map__put(map); } } @@ -1791,7 +1791,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, out: if (map && !is_kprobe) { - map__delete(map); + map__put(map); } return ret; @@ -2884,7 +2884,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, dso__fprintf_symbols_by_name(map->dso, map->type, stdout); end: if (user) { - map__delete(map); + map__put(map); } exit_symbol_maps(); diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 9d526a5312b1..fa10116a12ab 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -972,8 +972,10 @@ int dso__load_sym(struct dso *dso, struct map *map, map->unmap_ip = map__unmap_ip; /* Ensure maps are correctly ordered */ if (kmaps) { + map__get(map); map_groups__remove(kmaps, map); map_groups__insert(kmaps, map); + map__put(map); } } diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 743a9b360e3d..a3e80d6ad70a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1180,13 +1180,16 @@ static int dso__load_kcore(struct dso *dso, struct map *map, map->pgoff = new_map->pgoff; map->map_ip = new_map->map_ip; map->unmap_ip = new_map->unmap_ip; - map__delete(new_map); /* Ensure maps are correctly ordered */ + map__get(map); map_groups__remove(kmaps, map); map_groups__insert(kmaps, map); + map__put(map); } else { map_groups__insert(kmaps, new_map); } + + map__put(new_map); } /* @@ -1212,7 +1215,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map, while (!list_empty(&md.maps)) { map = list_entry(md.maps.next, struct map, node); list_del_init(&map->node); - map__delete(map); + map__put(map); } close(fd); return -EINVAL;