Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753345AbZK0S3p (ORCPT ); Fri, 27 Nov 2009 13:29:45 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753310AbZK0S3o (ORCPT ); Fri, 27 Nov 2009 13:29:44 -0500 Received: from bombadil.infradead.org ([18.85.46.34]:42058 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753119AbZK0S3j (ORCPT ); Fri, 27 Nov 2009 13:29:39 -0500 From: Arnaldo Carvalho de Melo To: Ingo Molnar Cc: linux-kernel@vger.kernel.org, Arnaldo Carvalho de Melo , =?utf-8?q?Fr=C3=A9d=C3=A9ric=20Weisbecker?= , Mike Galbraith , Peter Zijlstra , Paul Mackerras Subject: [PATCH 09/12] perf symbols: Support multiple symtabs in struct thread Date: Fri, 27 Nov 2009 16:29:20 -0200 Message-Id: <1259346563-12568-9-git-send-email-acme@infradead.org> X-Mailer: git-send-email 1.6.2.5 In-Reply-To: <1259346563-12568-8-git-send-email-acme@infradead.org> References: <1259346563-12568-1-git-send-email-acme@infradead.org> <1259346563-12568-2-git-send-email-acme@infradead.org> <1259346563-12568-3-git-send-email-acme@infradead.org> <1259346563-12568-4-git-send-email-acme@infradead.org> <1259346563-12568-5-git-send-email-acme@infradead.org> <1259346563-12568-6-git-send-email-acme@infradead.org> <1259346563-12568-7-git-send-email-acme@infradead.org> <1259346563-12568-8-git-send-email-acme@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org See http://www.infradead.org/rpr.html Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 24014 Lines: 737 From: Arnaldo Carvalho de Melo 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. Cc: Frédéric Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 2 +- tools/perf/builtin-top.c | 2 +- tools/perf/util/symbol.c | 157 +++++++++++++++-------------------------- tools/perf/util/symbol.h | 2 +- tools/perf/util/thread.c | 115 +++++++++++++++++++++++------- tools/perf/util/thread.h | 15 +++- 7 files changed, 162 insertions(+), 133 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index c32e760..3ebd70b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -167,7 +167,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head) map ? map->dso->long_name : ""); } 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); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 400bef9..9bd20c2 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -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 diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index abe78bb..bf6730c 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -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); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 581db4c..b6a2941 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -29,12 +29,11 @@ enum dso_origin { }; static void dsos__add(struct list_head *head, struct dso *dso); -static struct map *kernel_maps__find_by_dso_name(const char *name); +static struct map *thread__find_map_by_name(struct thread *self, char *name); static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); -static void kernel_maps__insert(struct map *map); struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); static int dso__load_kernel_sym(struct dso *self, struct map *map, - symbol_filter_t filter); + struct thread *thread, symbol_filter_t filter); unsigned int symbol__priv_size; static int vmlinux_path__nr_entries; static char **vmlinux_path; @@ -44,7 +43,7 @@ static struct symbol_conf symbol_conf__defaults = { .try_vmlinux_path = true, }; -static struct rb_root kernel_maps[MAP__NR_TYPES]; +static struct thread kthread_mem, *kthread = &kthread_mem; bool dso__loaded(const struct dso *self, enum map_type type) { @@ -79,10 +78,10 @@ static void symbols__fixup_end(struct rb_root *self) curr->end = roundup(curr->start, 4096); } -static void __kernel_maps__fixup_end(struct rb_root *root) +static void __thread__fixup_maps_end(struct thread *self, enum map_type type) { struct map *prev, *curr; - struct rb_node *nd, *prevnd = rb_first(root); + struct rb_node *nd, *prevnd = rb_first(&self->maps[type]); if (prevnd == NULL) return; @@ -102,11 +101,11 @@ static void __kernel_maps__fixup_end(struct rb_root *root) curr->end = ~0UL; } -static void kernel_maps__fixup_end(void) +static void thread__fixup_maps_end(struct thread *self) { int i; for (i = 0; i < MAP__NR_TYPES; ++i) - __kernel_maps__fixup_end(&kernel_maps[i]); + __thread__fixup_maps_end(self, i); } static struct symbol *symbol__new(u64 start, u64 len, const char *name) @@ -274,25 +273,16 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp) return fprintf(fp, "%s", sbuild_id); } -static const char * map_type__name[MAP__NR_TYPES] = { - [MAP__FUNCTION] = "Functions", -}; - -size_t dso__fprintf(struct dso *self, FILE *fp) +size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp) { - int i; struct rb_node *nd; size_t ret = fprintf(fp, "dso: %s (", self->short_name); ret += dso__fprintf_buildid(self, fp); ret += fprintf(fp, ")\n"); - for (i = 0; i < MAP__NR_TYPES; ++i) { - ret += fprintf(fp, "%s:\n", map_type__name[i]); - - for (nd = rb_first(&self->symbols[i]); nd; nd = rb_next(nd)) { - struct symbol *pos = rb_entry(nd, struct symbol, rb_node); - ret += symbol__fprintf(pos, fp); - } + for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) { + struct symbol *pos = rb_entry(nd, struct symbol, rb_node); + ret += symbol__fprintf(pos, fp); } return ret; @@ -373,7 +363,7 @@ out_failure: * kernel range is broken in several maps, named [kernel].N, as we don't have * the original ELF section names vmlinux have. */ -static int dso__split_kallsyms(struct dso *self, struct map *map, +static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread *thread, symbol_filter_t filter) { struct map *curr_map = map; @@ -394,10 +384,10 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, *module++ = '\0'; if (strcmp(self->name, module)) { - curr_map = kernel_maps__find_by_dso_name(module); + curr_map = thread__find_map_by_name(thread, module); if (curr_map == NULL) { - pr_err("/proc/{kallsyms,modules} " - "inconsistency!\n"); + pr_debug("/proc/{kallsyms,modules} " + "inconsistency!\n"); return -1; } } @@ -425,7 +415,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, } curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; - kernel_maps__insert(curr_map); + __thread__insert_map(thread, curr_map); ++kernel_range; } @@ -446,7 +436,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, static int dso__load_kallsyms(struct dso *self, struct map *map, - symbol_filter_t filter) + struct thread *thread, symbol_filter_t filter) { if (dso__load_all_kallsyms(self, map) < 0) return -1; @@ -454,35 +444,13 @@ static int dso__load_kallsyms(struct dso *self, struct map *map, symbols__fixup_end(&self->symbols[map->type]); self->origin = DSO__ORIG_KERNEL; - return dso__split_kallsyms(self, map, filter); -} - -static size_t __kernel_maps__fprintf(enum map_type type, FILE *fp) -{ - size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); - struct rb_node *nd; - - for (nd = rb_first(&kernel_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, fp); - printed += fprintf(fp, "--\n"); - } - } - - return printed; + return dso__split_kallsyms(self, map, thread, filter); } size_t kernel_maps__fprintf(FILE *fp) { size_t printed = fprintf(fp, "Kernel maps:\n"); - int i; - for (i = 0; i < MAP__NR_TYPES; ++i) - printed += __kernel_maps__fprintf(i, fp); - + printed += thread__fprintf_maps(kthread, fp); return printed + fprintf(fp, "END kernel maps\n"); } @@ -772,9 +740,9 @@ out: return 0; } -static int dso__load_sym(struct dso *self, struct map *map, const char *name, - int fd, symbol_filter_t filter, int kernel, - int kmodule) +static int dso__load_sym(struct dso *self, struct map *map, + struct thread *thread, const char *name, int fd, + symbol_filter_t filter, int kernel, int kmodule) { struct map *curr_map = map; struct dso *curr_dso = self; @@ -877,7 +845,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, snprintf(dso_name, sizeof(dso_name), "%s%s", self->short_name, section_name); - curr_map = kernel_maps__find_by_dso_name(dso_name); + curr_map = thread__find_map_by_name(thread, dso_name); if (curr_map == NULL) { u64 start = sym.st_value; @@ -896,7 +864,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, curr_map->map_ip = identity__map_ip; curr_map->unmap_ip = identity__map_ip; curr_dso->origin = DSO__ORIG_KERNEL; - kernel_maps__insert(curr_map); + __thread__insert_map(kthread, curr_map); dsos__add(&dsos__kernel, curr_dso); } else curr_dso = curr_map->dso; @@ -1121,7 +1089,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) dso__set_loaded(self, map->type); if (self->kernel) - return dso__load_kernel_sym(self, map, filter); + return dso__load_kernel_sym(self, map, kthread, filter); name = malloc(size); if (!name) @@ -1186,7 +1154,7 @@ compare_build_id: fd = open(name, O_RDONLY); } while (fd < 0); - ret = dso__load_sym(self, map, name, fd, filter, 0, 0); + ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0); close(fd); /* @@ -1207,16 +1175,11 @@ out: return ret; } -static void kernel_maps__insert(struct map *map) -{ - maps__insert(&kernel_maps[map->type], map); -} - -static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type, - struct map **mapp, - symbol_filter_t filter) +static struct symbol *thread__find_symbol(struct thread *self, u64 ip, + enum map_type type, struct map **mapp, + symbol_filter_t filter) { - struct map *map = maps__find(&kernel_maps[type], ip); + struct map *map = thread__find_map(self, type, ip); if (mapp) *mapp = map; @@ -1224,9 +1187,7 @@ static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type, if (map) { ip = map->map_ip(map, ip); return map__find_symbol(map, ip, filter); - } else - WARN_ONCE(RB_EMPTY_ROOT(&kernel_maps[type]), - "Empty kernel_maps, was symbol__init() called?\n"); + } return NULL; } @@ -1234,14 +1195,14 @@ static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type, struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp, symbol_filter_t filter) { - return kernel_maps__find_symbol(ip, MAP__FUNCTION, mapp, filter); + return thread__find_symbol(kthread, ip, MAP__FUNCTION, mapp, filter); } -static struct map *kernel_maps__find_by_dso_name(const char *name) +static struct map *thread__find_map_by_name(struct thread *self, char *name) { struct rb_node *nd; - for (nd = rb_first(&kernel_maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { + for (nd = rb_first(&self->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { struct map *map = rb_entry(nd, struct map, rb_node); if (map->dso && strcmp(map->dso->name, name) == 0) @@ -1285,7 +1246,7 @@ static int dsos__set_modules_path_dir(char *dirname) (int)(dot - dent->d_name), dent->d_name); strxfrchar(dso_name, '-', '_'); - map = kernel_maps__find_by_dso_name(dso_name); + map = thread__find_map_by_name(kthread, dso_name); if (map == NULL) continue; @@ -1338,7 +1299,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) return self; } -static int kernel_maps__create_module_maps(void) +static int thread__create_module_maps(struct thread *self) { char *line = NULL; size_t n; @@ -1395,7 +1356,7 @@ static int kernel_maps__create_module_maps(void) dso->has_build_id = true; dso->origin = DSO__ORIG_KMODULE; - kernel_maps__insert(map); + __thread__insert_map(self, map); dsos__add(&dsos__kernel, dso); } @@ -1410,7 +1371,7 @@ out_failure: return -1; } -static int dso__load_vmlinux(struct dso *self, struct map *map, +static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *thread, const char *vmlinux, symbol_filter_t filter) { int err = -1, fd; @@ -1444,15 +1405,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, return -1; dso__set_loaded(self, map->type); - err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0); - + err = dso__load_sym(self, map, thread, self->long_name, fd, filter, 1, 0); close(fd); return err; } static int dso__load_kernel_sym(struct dso *self, struct map *map, - symbol_filter_t filter) + struct thread *thread, symbol_filter_t filter) { int err; bool is_kallsyms; @@ -1462,8 +1422,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, pr_debug("Looking at the vmlinux_path (%d entries long)\n", vmlinux_path__nr_entries); for (i = 0; i < vmlinux_path__nr_entries; ++i) { - err = dso__load_vmlinux(self, map, vmlinux_path[i], - filter); + err = dso__load_vmlinux(self, map, thread, + vmlinux_path[i], filter); if (err > 0) { pr_debug("Using %s for symbols\n", vmlinux_path[i]); @@ -1478,12 +1438,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, if (is_kallsyms) goto do_kallsyms; - err = dso__load_vmlinux(self, map, self->long_name, filter); + err = dso__load_vmlinux(self, map, thread, self->long_name, filter); if (err <= 0) { pr_info("The file %s cannot be used, " "trying to use /proc/kallsyms...", self->long_name); do_kallsyms: - err = dso__load_kallsyms(self, map, filter); + err = dso__load_kallsyms(self, map, thread, filter); if (err > 0 && !is_kallsyms) dso__set_long_name(self, strdup("[kernel.kallsyms]")); } @@ -1535,8 +1495,11 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp) { struct dso *pos; - list_for_each_entry(pos, head, node) - dso__fprintf(pos, fp); + list_for_each_entry(pos, head, node) { + int i; + for (i = 0; i < MAP__NR_TYPES; ++i) + dso__fprintf(pos, i, fp); + } } void dsos__fprintf(FILE *fp) @@ -1563,10 +1526,10 @@ size_t dsos__fprintf_buildid(FILE *fp) __dsos__fprintf_buildid(&dsos__user, fp)); } -static int kernel_maps__create_kernel_map(const struct symbol_conf *conf) +static int thread__create_kernel_map(struct thread *self, const char *vmlinux) { struct map *kmap; - struct dso *kernel = dso__new(conf->vmlinux_name ?: "[kernel.kallsyms]"); + struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]"); if (kernel == NULL) return -1; @@ -1588,7 +1551,7 @@ static int kernel_maps__create_kernel_map(const struct symbol_conf *conf) sizeof(kernel->build_id)) == 0) kernel->has_build_id = true; - kernel_maps__insert(kmap); + __thread__insert_map(self, kmap); dsos__add(&dsos__kernel, kernel); dsos__add(&dsos__user, vdso); @@ -1656,32 +1619,28 @@ out_fail: return -1; } -static int kernel_maps__init(const struct symbol_conf *conf) +int symbol__init(struct symbol_conf *conf) { const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults; + elf_version(EV_CURRENT); symbol__priv_size = pconf->priv_size; + thread__init(kthread, 0); if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) return -1; - if (kernel_maps__create_kernel_map(pconf) < 0) { + if (thread__create_kernel_map(kthread, pconf->vmlinux_name) < 0) { vmlinux_path__exit(); return -1; } - if (pconf->use_modules && kernel_maps__create_module_maps() < 0) + if (pconf->use_modules && thread__create_module_maps(kthread) < 0) pr_debug("Failed to load list of modules in use, " "continuing...\n"); /* * Now that we have all the maps created, just set the ->end of them: */ - kernel_maps__fixup_end(); + thread__fixup_maps_end(kthread); return 0; } - -int symbol__init(struct symbol_conf *conf) -{ - elf_version(EV_CURRENT); - return kernel_maps__init(conf); -} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 8934814..3f9e4a4 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -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); diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 1796625..2229f82 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -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; } diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 54580bb..3bdd9b2 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h @@ -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 */ -- 1.6.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/