Skip to content

Commit

Permalink
perf tools: Reference count struct map
Browse files Browse the repository at this point in the history
We have pointers to struct map instances in several places, like in the
hist_entry instances, so we need a way to know when we can destroy them,
otherwise we may either keep leaking them or end up referencing deleted
instances.

Start fixing it by reference counting them.

This patch puts the reference count for struct map in place, replacing
direct map__delete() calls with map__put() ones and then grabbing a
reference count when adding it to the maps struct where maps for a
struct thread are kept.

Next we'll grab reference counts when setting pointers to struct map
instances, in places like in the hist_entry code.

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-wi19xczk0t2a41r1i2chuio5@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Arnaldo Carvalho de Melo committed May 27, 2015
1 parent facf3f0 commit 84c2caf
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 12 deletions.
3 changes: 2 additions & 1 deletion tools/perf/util/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
21 changes: 15 additions & 6 deletions tools/perf/util/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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;
Expand All @@ -696,22 +703,22 @@ 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;
__maps__insert(maps, after);
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;
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
11 changes: 11 additions & 0 deletions tools/perf/util/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct map {

struct dso *dso;
struct map_groups *groups;
atomic_t refcnt;
};

struct kmap {
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions tools/perf/util/probe-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();

Expand Down
2 changes: 2 additions & 0 deletions tools/perf/util/symbol-elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
7 changes: 5 additions & 2 deletions tools/perf/util/symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand All @@ -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;
Expand Down

0 comments on commit 84c2caf

Please sign in to comment.