Commit 95011c60 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

perf symbols: Support multiple symtabs in struct thread

Making the routines that were so far specific to the kernel maps
useful for all threads.

This is done by making the kernel maps be contained in a kernel
"thread".

This gets the kernel specific routines closer to the userspace
counterparts, which will help in reducing the boilerplate for
resolving a symbol, as will be demonstrated in the next patches.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1259346563-12568-9-git-send-email-acme@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 23ea4a3f
......@@ -167,7 +167,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
map ? map->dso->long_name : "<not found>");
} else if (event->header.misc & PERF_RECORD_MISC_USER) {
level = '.';
map = thread__find_map(thread, ip);
map = thread__find_map(thread, MAP__FUNCTION, ip);
if (map != NULL) {
ip = map->map_ip(map, ip);
sym = map__find_symbol(map, ip, symbol_filter);
......
......@@ -422,7 +422,7 @@ resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp)
if (!thread)
return NULL;
map = thread__find_map(thread, ip);
map = thread__find_map(thread, MAP__FUNCTION, ip);
if (map != NULL) {
/*
* We have to do this here as we may have a dso
......
......@@ -945,7 +945,7 @@ static void event__process_sample(const event_t *self, int counter)
if (thread == NULL)
return;
map = thread__find_map(thread, ip);
map = thread__find_map(thread, MAP__FUNCTION, ip);
if (map != NULL) {
ip = map->map_ip(map, ip);
sym = map__find_symbol(map, ip, symbol_filter);
......
This diff is collapsed.
......@@ -92,7 +92,7 @@ void dsos__fprintf(FILE *fp);
size_t dsos__fprintf_buildid(FILE *fp);
size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
size_t dso__fprintf(struct dso *self, FILE *fp);
size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
char dso__symtab_origin(const struct dso *self);
void dso__set_build_id(struct dso *self, void *build_id);
......
......@@ -9,17 +9,26 @@
static struct rb_root threads;
static struct thread *last_match;
void thread__init(struct thread *self, pid_t pid)
{
int i;
self->pid = pid;
self->comm = NULL;
for (i = 0; i < MAP__NR_TYPES; ++i) {
self->maps[i] = RB_ROOT;
INIT_LIST_HEAD(&self->removed_maps[i]);
}
}
static struct thread *thread__new(pid_t pid)
{
struct thread *self = zalloc(sizeof(*self));
if (self != NULL) {
self->pid = pid;
thread__init(self, pid);
self->comm = malloc(32);
if (self->comm)
snprintf(self->comm, 32, ":%d", self->pid);
self->maps = RB_ROOT;
INIT_LIST_HEAD(&self->removed_maps);
}
return self;
......@@ -44,24 +53,68 @@ int thread__comm_len(struct thread *self)
return self->comm_len;
}
static size_t thread__fprintf(struct thread *self, FILE *fp)
static const char *map_type__name[MAP__NR_TYPES] = {
[MAP__FUNCTION] = "Functions",
};
static size_t __thread__fprintf_maps(struct thread *self,
enum map_type type, FILE *fp)
{
size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
struct rb_node *nd;
struct map *pos;
size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
self->pid, self->comm);
for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) {
pos = rb_entry(nd, struct map, rb_node);
ret += map__fprintf(pos, fp);
for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
struct map *pos = rb_entry(nd, struct map, rb_node);
printed += fprintf(fp, "Map:");
printed += map__fprintf(pos, fp);
if (verbose > 1) {
printed += dso__fprintf(pos->dso, type, fp);
printed += fprintf(fp, "--\n");
}
}
ret = fprintf(fp, "Removed maps:\n");
return printed;
}
size_t thread__fprintf_maps(struct thread *self, FILE *fp)
{
size_t printed = 0, i;
for (i = 0; i < MAP__NR_TYPES; ++i)
printed += __thread__fprintf_maps(self, i, fp);
return printed;
}
list_for_each_entry(pos, &self->removed_maps, node)
ret += map__fprintf(pos, fp);
static size_t __thread__fprintf_removed_maps(struct thread *self,
enum map_type type, FILE *fp)
{
struct map *pos;
size_t printed = 0;
list_for_each_entry(pos, &self->removed_maps[type], 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;
}
return ret;
static size_t thread__fprintf_removed_maps(struct thread *self, FILE *fp)
{
size_t printed = 0, i;
for (i = 0; i < MAP__NR_TYPES; ++i)
printed += __thread__fprintf_removed_maps(self, i, fp);
return printed;
}
static size_t thread__fprintf(struct thread *self, FILE *fp)
{
size_t printed = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
printed += thread__fprintf_removed_maps(self, fp);
printed += fprintf(fp, "Removed maps:\n");
return printed + thread__fprintf_removed_maps(self, fp);
}
struct thread *threads__findnew(pid_t pid)
......@@ -117,7 +170,8 @@ struct thread *register_idle_thread(void)
static void thread__remove_overlappings(struct thread *self, struct map *map)
{
struct rb_node *next = rb_first(&self->maps);
struct rb_root *root = &self->maps[map->type];
struct rb_node *next = rb_first(root);
while (next) {
struct map *pos = rb_entry(next, struct map, rb_node);
......@@ -132,13 +186,13 @@ static void thread__remove_overlappings(struct thread *self, struct map *map)
map__fprintf(pos, stderr);
}
rb_erase(&pos->rb_node, &self->maps);
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);
list_add_tail(&pos->node, &self->removed_maps[map->type]);
}
}
......@@ -185,12 +239,26 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
void thread__insert_map(struct thread *self, struct map *map)
{
thread__remove_overlappings(self, map);
maps__insert(&self->maps, map);
maps__insert(&self->maps[map->type], map);
}
int thread__fork(struct thread *self, struct thread *parent)
static int thread__clone_maps(struct thread *self, struct thread *parent,
enum map_type type)
{
struct rb_node *nd;
for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
struct map *map = rb_entry(nd, struct map, rb_node);
struct map *new = map__clone(map);
if (new == NULL)
return -ENOMEM;
thread__insert_map(self, new);
}
return 0;
}
int thread__fork(struct thread *self, struct thread *parent)
{
int i;
if (self->comm)
free(self->comm);
......@@ -198,14 +266,9 @@ int thread__fork(struct thread *self, struct thread *parent)
if (!self->comm)
return -ENOMEM;
for (nd = rb_first(&parent->maps); nd; nd = rb_next(nd)) {
struct map *map = rb_entry(nd, struct map, rb_node);
struct map *new = map__clone(map);
if (!new)
for (i = 0; i < MAP__NR_TYPES; ++i)
if (thread__clone_maps(self, parent, i) < 0)
return -ENOMEM;
thread__insert_map(self, new);
}
return 0;
}
......
......@@ -7,20 +7,22 @@
struct thread {
struct rb_node rb_node;
struct rb_root maps;
struct list_head removed_maps;
struct rb_root maps[MAP__NR_TYPES];
struct list_head removed_maps[MAP__NR_TYPES];
pid_t pid;
char shortname[3];
char *comm;
int comm_len;
};
void thread__init(struct thread *self, pid_t pid);
int thread__set_comm(struct thread *self, const char *comm);
int thread__comm_len(struct thread *self);
struct thread *threads__findnew(pid_t pid);
struct thread *register_idle_thread(void);
void thread__insert_map(struct thread *self, struct map *map);
int thread__fork(struct thread *self, struct thread *parent);
size_t thread__fprintf_maps(struct thread *self, FILE *fp);
size_t threads__fprintf(FILE *fp);
void maps__insert(struct rb_root *maps, struct map *map);
......@@ -29,9 +31,14 @@ struct map *maps__find(struct rb_root *maps, u64 ip);
struct symbol *kernel_maps__find_function(const u64 ip, struct map **mapp,
symbol_filter_t filter);
static inline struct map *thread__find_map(struct thread *self, u64 ip)
static inline struct map *thread__find_map(struct thread *self,
enum map_type type, u64 ip)
{
return self ? maps__find(&self->maps, ip) : NULL;
return self ? maps__find(&self->maps[type], ip) : NULL;
}
static inline void __thread__insert_map(struct thread *self, struct map *map)
{
maps__insert(&self->maps[map->type], map);
}
#endif /* __PERF_THREAD_H */
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