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.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 35a23ff9
...@@ -313,8 +313,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, ...@@ -313,8 +313,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
memset(&he->stat, 0, sizeof(he->stat)); memset(&he->stat, 0, sizeof(he->stat));
} }
if (he->ms.map) map__get(he->ms.map);
he->ms.map->referenced = true;
if (he->branch_info) { if (he->branch_info) {
/* /*
...@@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, ...@@ -324,6 +323,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
*/ */
he->branch_info = malloc(sizeof(*he->branch_info)); he->branch_info = malloc(sizeof(*he->branch_info));
if (he->branch_info == NULL) { if (he->branch_info == NULL) {
map__zput(he->ms.map);
free(he->stat_acc); free(he->stat_acc);
free(he); free(he);
return NULL; return NULL;
...@@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template, ...@@ -332,17 +332,13 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
memcpy(he->branch_info, template->branch_info, memcpy(he->branch_info, template->branch_info,
sizeof(*he->branch_info)); sizeof(*he->branch_info));
if (he->branch_info->from.map) map__get(he->branch_info->from.map);
he->branch_info->from.map->referenced = true; map__get(he->branch_info->to.map);
if (he->branch_info->to.map)
he->branch_info->to.map->referenced = true;
} }
if (he->mem_info) { if (he->mem_info) {
if (he->mem_info->iaddr.map) map__get(he->mem_info->iaddr.map);
he->mem_info->iaddr.map->referenced = true; map__get(he->mem_info->daddr.map);
if (he->mem_info->daddr.map)
he->mem_info->daddr.map->referenced = true;
} }
if (symbol_conf.use_callchain) if (symbol_conf.use_callchain)
...@@ -407,9 +403,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, ...@@ -407,9 +403,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
* the history counter to increment. * the history counter to increment.
*/ */
if (he->ms.map != entry->ms.map) { if (he->ms.map != entry->ms.map) {
he->ms.map = entry->ms.map; map__put(he->ms.map);
if (he->ms.map) he->ms.map = map__get(entry->ms.map);
he->ms.map->referenced = true;
} }
goto out; goto out;
} }
...@@ -933,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right) ...@@ -933,8 +928,20 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
void hist_entry__delete(struct hist_entry *he) void hist_entry__delete(struct hist_entry *he)
{ {
thread__zput(he->thread); thread__zput(he->thread);
zfree(&he->branch_info); map__zput(he->ms.map);
zfree(&he->mem_info);
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); zfree(&he->stat_acc);
free_srcline(he->srcline); free_srcline(he->srcline);
free_callchain(he->callchain); free_callchain(he->callchain);
......
...@@ -137,7 +137,6 @@ void map__init(struct map *map, enum map_type type, ...@@ -137,7 +137,6 @@ void map__init(struct map *map, enum map_type type,
map->unmap_ip = map__unmap_ip; map->unmap_ip = map__unmap_ip;
RB_CLEAR_NODE(&map->rb_node); RB_CLEAR_NODE(&map->rb_node);
map->groups = NULL; map->groups = NULL;
map->referenced = false;
map->erange_warned = false; map->erange_warned = false;
atomic_set(&map->refcnt, 1); atomic_set(&map->refcnt, 1);
} }
...@@ -439,7 +438,6 @@ static void maps__init(struct maps *maps) ...@@ -439,7 +438,6 @@ static void maps__init(struct maps *maps)
{ {
maps->entries = RB_ROOT; maps->entries = RB_ROOT;
pthread_rwlock_init(&maps->lock, NULL); pthread_rwlock_init(&maps->lock, NULL);
INIT_LIST_HEAD(&maps->removed_maps);
} }
void map_groups__init(struct map_groups *mg, struct machine *machine) void map_groups__init(struct map_groups *mg, struct machine *machine)
...@@ -466,21 +464,10 @@ static void __maps__purge(struct maps *maps) ...@@ -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) static void maps__exit(struct maps *maps)
{ {
pthread_rwlock_wrlock(&maps->lock); pthread_rwlock_wrlock(&maps->lock);
__maps__purge(maps); __maps__purge(maps);
__maps__purge_removed_maps(maps);
pthread_rwlock_unlock(&maps->lock); pthread_rwlock_unlock(&maps->lock);
} }
...@@ -499,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg) ...@@ -499,8 +486,6 @@ bool map_groups__empty(struct map_groups *mg)
for (i = 0; i < MAP__NR_TYPES; ++i) { for (i = 0; i < MAP__NR_TYPES; ++i) {
if (maps__first(&mg->maps[i])) if (maps__first(&mg->maps[i]))
return false; return false;
if (!list_empty(&mg->maps[i].removed_maps))
return false;
} }
return true; return true;
...@@ -621,7 +606,7 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg, enum map_type type, ...@@ -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); 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; size_t printed = 0, i;
for (i = 0; i < MAP__NR_TYPES; ++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) ...@@ -629,39 +614,6 @@ static size_t map_groups__fprintf_maps(struct map_groups *mg, FILE *fp)
return printed; 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) static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
{ {
struct rb_root *root; struct rb_root *root;
...@@ -719,13 +671,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp ...@@ -719,13 +671,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
map__fprintf(after, fp); map__fprintf(after, fp);
} }
put_map: put_map:
/* map__put(pos);
* 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);
if (err) if (err)
goto out; goto out;
......
...@@ -34,7 +34,6 @@ struct map { ...@@ -34,7 +34,6 @@ struct map {
u64 start; u64 start;
u64 end; u64 end;
u8 /* enum map_type */ type; u8 /* enum map_type */ type;
bool referenced;
bool erange_warned; bool erange_warned;
u32 priv; u32 priv;
u32 prot; u32 prot;
...@@ -63,7 +62,6 @@ struct kmap { ...@@ -63,7 +62,6 @@ struct kmap {
struct maps { struct maps {
struct rb_root entries; struct rb_root entries;
pthread_rwlock_t lock; pthread_rwlock_t lock;
struct list_head removed_maps;
}; };
struct map_groups { struct map_groups {
...@@ -161,6 +159,14 @@ static inline struct map *map__get(struct map *map) ...@@ -161,6 +159,14 @@ static inline struct map *map__get(struct map *map)
void map__put(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); int map__overlap(struct map *l, struct map *r);
size_t map__fprintf(struct map *map, FILE *fp); size_t map__fprintf(struct map *map, FILE *fp);
size_t map__fprintf_dsoname(struct map *map, FILE *fp); size_t map__fprintf_dsoname(struct map *map, FILE *fp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment