Commit 43d7383b authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
parents 69e77a8b 0a1eae39
...@@ -93,6 +93,8 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) ...@@ -93,6 +93,8 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
if (self != NULL) { if (self != NULL) {
*self = *template; *self = *template;
self->nr_events = 1; self->nr_events = 1;
if (self->ms.map)
self->ms.map->referenced = true;
if (symbol_conf.use_callchain) if (symbol_conf.use_callchain)
callchain_init(self->callchain); callchain_init(self->callchain);
} }
......
...@@ -29,6 +29,7 @@ void map__init(struct map *self, enum map_type type, ...@@ -29,6 +29,7 @@ void map__init(struct map *self, enum map_type type,
self->unmap_ip = map__unmap_ip; self->unmap_ip = map__unmap_ip;
RB_CLEAR_NODE(&self->rb_node); RB_CLEAR_NODE(&self->rb_node);
self->groups = NULL; self->groups = NULL;
self->referenced = false;
} }
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
...@@ -387,6 +388,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, ...@@ -387,6 +388,7 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
{ {
struct rb_root *root = &self->maps[map->type]; struct rb_root *root = &self->maps[map->type];
struct rb_node *next = rb_first(root); struct rb_node *next = rb_first(root);
int err = 0;
while (next) { while (next) {
struct map *pos = rb_entry(next, struct map, rb_node); struct map *pos = rb_entry(next, struct map, rb_node);
...@@ -402,12 +404,6 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, ...@@ -402,12 +404,6 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
} }
rb_erase(&pos->rb_node, root); rb_erase(&pos->rb_node, root);
/*
* We may have references to this map, for instance in some
* hist_entry instances, so just move them to a separate
* list.
*/
list_add_tail(&pos->node, &self->removed_maps[map->type]);
/* /*
* Now check if we need to create new maps for areas not * Now check if we need to create new maps for areas not
* overlapped by the new map: * overlapped by the new map:
...@@ -415,8 +411,10 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, ...@@ -415,8 +411,10 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
if (map->start > pos->start) { if (map->start > pos->start) {
struct map *before = map__clone(pos); struct map *before = map__clone(pos);
if (before == NULL) if (before == NULL) {
return -ENOMEM; err = -ENOMEM;
goto move_map;
}
before->end = map->start - 1; before->end = map->start - 1;
map_groups__insert(self, before); map_groups__insert(self, before);
...@@ -427,14 +425,27 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, ...@@ -427,14 +425,27 @@ int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
if (map->end < pos->end) { if (map->end < pos->end) {
struct map *after = map__clone(pos); struct map *after = map__clone(pos);
if (after == NULL) if (after == NULL) {
return -ENOMEM; err = -ENOMEM;
goto move_map;
}
after->start = map->end + 1; after->start = map->end + 1;
map_groups__insert(self, after); map_groups__insert(self, after);
if (verbose >= 2) if (verbose >= 2)
map__fprintf(after, fp); map__fprintf(after, fp);
} }
move_map:
/*
* If we have references, just move them to a separate list.
*/
if (pos->referenced)
list_add_tail(&pos->node, &self->removed_maps[map->type]);
else
map__delete(pos);
if (err)
return err;
} }
return 0; return 0;
...@@ -506,6 +517,11 @@ void maps__insert(struct rb_root *maps, struct map *map) ...@@ -506,6 +517,11 @@ void maps__insert(struct rb_root *maps, struct map *map)
rb_insert_color(&map->rb_node, maps); rb_insert_color(&map->rb_node, maps);
} }
void maps__remove(struct rb_root *self, struct map *map)
{
rb_erase(&map->rb_node, self);
}
struct map *maps__find(struct rb_root *maps, u64 ip) struct map *maps__find(struct rb_root *maps, u64 ip)
{ {
struct rb_node **p = &maps->rb_node; struct rb_node **p = &maps->rb_node;
...@@ -551,13 +567,6 @@ static void dsos__delete(struct list_head *self) ...@@ -551,13 +567,6 @@ static void dsos__delete(struct list_head *self)
void machine__exit(struct machine *self) void machine__exit(struct machine *self)
{ {
struct kmap *kmap = map__kmap(self->vmlinux_maps[MAP__FUNCTION]);
if (kmap->ref_reloc_sym) {
free((char *)kmap->ref_reloc_sym->name);
free(kmap->ref_reloc_sym);
}
map_groups__exit(&self->kmaps); map_groups__exit(&self->kmaps);
dsos__delete(&self->user_dsos); dsos__delete(&self->user_dsos);
dsos__delete(&self->kernel_dsos); dsos__delete(&self->kernel_dsos);
...@@ -565,6 +574,12 @@ void machine__exit(struct machine *self) ...@@ -565,6 +574,12 @@ void machine__exit(struct machine *self)
self->root_dir = NULL; self->root_dir = NULL;
} }
void machine__delete(struct machine *self)
{
machine__exit(self);
free(self);
}
struct machine *machines__add(struct rb_root *self, pid_t pid, struct machine *machines__add(struct rb_root *self, pid_t pid,
const char *root_dir) const char *root_dir)
{ {
......
...@@ -29,7 +29,8 @@ struct map { ...@@ -29,7 +29,8 @@ struct map {
}; };
u64 start; u64 start;
u64 end; u64 end;
enum map_type type; u8 /* enum map_type */ type;
bool referenced;
u32 priv; u32 priv;
u64 pgoff; u64 pgoff;
...@@ -125,6 +126,7 @@ void map__reloc_vmlinux(struct map *self); ...@@ -125,6 +126,7 @@ void map__reloc_vmlinux(struct map *self);
size_t __map_groups__fprintf_maps(struct map_groups *self, size_t __map_groups__fprintf_maps(struct map_groups *self,
enum map_type type, int verbose, FILE *fp); enum map_type type, int verbose, FILE *fp);
void maps__insert(struct rb_root *maps, struct map *map); void maps__insert(struct rb_root *maps, struct map *map);
void maps__remove(struct rb_root *self, struct map *map);
struct map *maps__find(struct rb_root *maps, u64 addr); struct map *maps__find(struct rb_root *maps, u64 addr);
void map_groups__init(struct map_groups *self); void map_groups__init(struct map_groups *self);
void map_groups__exit(struct map_groups *self); void map_groups__exit(struct map_groups *self);
...@@ -144,6 +146,7 @@ struct machine *machines__findnew(struct rb_root *self, pid_t pid); ...@@ -144,6 +146,7 @@ struct machine *machines__findnew(struct rb_root *self, pid_t pid);
char *machine__mmap_name(struct machine *self, char *bf, size_t size); char *machine__mmap_name(struct machine *self, char *bf, size_t size);
int machine__init(struct machine *self, const char *root_dir, pid_t pid); int machine__init(struct machine *self, const char *root_dir, pid_t pid);
void machine__exit(struct machine *self); void machine__exit(struct machine *self);
void machine__delete(struct machine *self);
/* /*
* Default guest kernel is defined by parameter --guestkallsyms * Default guest kernel is defined by parameter --guestkallsyms
...@@ -165,6 +168,11 @@ static inline void map_groups__insert(struct map_groups *self, struct map *map) ...@@ -165,6 +168,11 @@ static inline void map_groups__insert(struct map_groups *self, struct map *map)
map->groups = self; map->groups = self;
} }
static inline void map_groups__remove(struct map_groups *self, struct map *map)
{
maps__remove(&self->maps[map->type], map);
}
static inline struct map *map_groups__find(struct map_groups *self, static inline struct map *map_groups__find(struct map_groups *self,
enum map_type type, u64 addr) enum map_type type, u64 addr)
{ {
......
...@@ -79,6 +79,12 @@ int perf_session__create_kernel_maps(struct perf_session *self) ...@@ -79,6 +79,12 @@ int perf_session__create_kernel_maps(struct perf_session *self)
return ret; return ret;
} }
static void perf_session__destroy_kernel_maps(struct perf_session *self)
{
machine__destroy_kernel_maps(&self->host_machine);
machines__destroy_guest_kernel_maps(&self->machines);
}
struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe)
{ {
size_t len = filename ? strlen(filename) + 1 : 0; size_t len = filename ? strlen(filename) + 1 : 0;
...@@ -150,6 +156,7 @@ static void perf_session__delete_threads(struct perf_session *self) ...@@ -150,6 +156,7 @@ static void perf_session__delete_threads(struct perf_session *self)
void perf_session__delete(struct perf_session *self) void perf_session__delete(struct perf_session *self)
{ {
perf_header__exit(&self->header); perf_header__exit(&self->header);
perf_session__destroy_kernel_maps(self);
perf_session__delete_dead_threads(self); perf_session__delete_dead_threads(self);
perf_session__delete_threads(self); perf_session__delete_threads(self);
machine__exit(&self->host_machine); machine__exit(&self->host_machine);
...@@ -159,6 +166,7 @@ void perf_session__delete(struct perf_session *self) ...@@ -159,6 +166,7 @@ void perf_session__delete(struct perf_session *self)
void perf_session__remove_thread(struct perf_session *self, struct thread *th) void perf_session__remove_thread(struct perf_session *self, struct thread *th)
{ {
self->last_match = NULL;
rb_erase(&th->rb_node, &self->threads); rb_erase(&th->rb_node, &self->threads);
/* /*
* We may have references to this thread, for instance in some hist_entry * We may have references to this thread, for instance in some hist_entry
......
...@@ -2107,6 +2107,36 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel) ...@@ -2107,6 +2107,36 @@ int __machine__create_kernel_maps(struct machine *self, struct dso *kernel)
return 0; return 0;
} }
void machine__destroy_kernel_maps(struct machine *self)
{
enum map_type type;
for (type = 0; type < MAP__NR_TYPES; ++type) {
struct kmap *kmap;
if (self->vmlinux_maps[type] == NULL)
continue;
kmap = map__kmap(self->vmlinux_maps[type]);
map_groups__remove(&self->kmaps, self->vmlinux_maps[type]);
if (kmap->ref_reloc_sym) {
/*
* ref_reloc_sym is shared among all maps, so free just
* on one of them.
*/
if (type == MAP__FUNCTION) {
free((char *)kmap->ref_reloc_sym->name);
kmap->ref_reloc_sym->name = NULL;
free(kmap->ref_reloc_sym);
}
kmap->ref_reloc_sym = NULL;
}
map__delete(self->vmlinux_maps[type]);
self->vmlinux_maps[type] = NULL;
}
}
int machine__create_kernel_maps(struct machine *self) int machine__create_kernel_maps(struct machine *self)
{ {
struct dso *kernel = machine__create_kernel(self); struct dso *kernel = machine__create_kernel(self);
...@@ -2351,6 +2381,19 @@ int machines__create_guest_kernel_maps(struct rb_root *self) ...@@ -2351,6 +2381,19 @@ int machines__create_guest_kernel_maps(struct rb_root *self)
return ret; return ret;
} }
void machines__destroy_guest_kernel_maps(struct rb_root *self)
{
struct rb_node *next = rb_first(self);
while (next) {
struct machine *pos = rb_entry(next, struct machine, rb_node);
next = rb_next(&pos->rb_node);
rb_erase(&pos->rb_node, self);
machine__delete(pos);
}
}
int machine__load_kallsyms(struct machine *self, const char *filename, int machine__load_kallsyms(struct machine *self, const char *filename,
enum map_type type, symbol_filter_t filter) enum map_type type, symbol_filter_t filter)
{ {
......
...@@ -212,11 +212,13 @@ int kallsyms__parse(const char *filename, void *arg, ...@@ -212,11 +212,13 @@ int kallsyms__parse(const char *filename, void *arg,
int (*process_symbol)(void *arg, const char *name, int (*process_symbol)(void *arg, const char *name,
char type, u64 start)); char type, u64 start));
void machine__destroy_kernel_maps(struct machine *self);
int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);
int machine__create_kernel_maps(struct machine *self); int machine__create_kernel_maps(struct machine *self);
int machines__create_kernel_maps(struct rb_root *self, pid_t pid); int machines__create_kernel_maps(struct rb_root *self, pid_t pid);
int machines__create_guest_kernel_maps(struct rb_root *self); int machines__create_guest_kernel_maps(struct rb_root *self);
void machines__destroy_guest_kernel_maps(struct rb_root *self);
int symbol__init(void); int symbol__init(void);
void symbol__exit(void); void symbol__exit(void);
......
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