diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-12-11 11:50:36 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-12 01:42:09 -0500 |
commit | 9958e1f0aee632c3665162c9c93cf8fde8006a94 (patch) | |
tree | ffd81c34d3ca8044c3fe0d670dc1786113624bbb /tools/perf/util | |
parent | 58e9f94138c1d9c47f6a63632ca7a78fc6dcc15f (diff) |
perf symbols: Rename kthreads to kmaps, using another abstraction for it
Using a struct thread instance just to hold the kernel space maps
(vmlinux + modules) is overkill and confuses people trying to
understand the perf symbols abstractions.
The kernel maps are really present in all threads, i.e. the kernel
is a library, not a separate thread.
So introduce the 'map_groups' abstraction and use it for the kernel
maps, now in the kmaps global variable.
It, in turn, will move, together with the threads list to the
perf_file abstraction, so that we can support multiple perf_file
instances, needed by perf diff.
Brainstormed-with: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Eduardo Habkost <ehabkost@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: <1260550239-5372-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/event.c | 11 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 73 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 4 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 62 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 39 |
5 files changed, 105 insertions, 84 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 4dcecafa85d..ba0de90cd3d 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -254,13 +254,14 @@ void thread__find_addr_location(struct thread *self, u8 cpumode, | |||
254 | struct addr_location *al, | 254 | struct addr_location *al, |
255 | symbol_filter_t filter) | 255 | symbol_filter_t filter) |
256 | { | 256 | { |
257 | struct thread *thread = al->thread = self; | 257 | struct map_groups *mg = &self->mg; |
258 | 258 | ||
259 | al->thread = self; | ||
259 | al->addr = addr; | 260 | al->addr = addr; |
260 | 261 | ||
261 | if (cpumode & PERF_RECORD_MISC_KERNEL) { | 262 | if (cpumode & PERF_RECORD_MISC_KERNEL) { |
262 | al->level = 'k'; | 263 | al->level = 'k'; |
263 | thread = kthread; | 264 | mg = kmaps; |
264 | } else if (cpumode & PERF_RECORD_MISC_USER) | 265 | } else if (cpumode & PERF_RECORD_MISC_USER) |
265 | al->level = '.'; | 266 | al->level = '.'; |
266 | else { | 267 | else { |
@@ -270,7 +271,7 @@ void thread__find_addr_location(struct thread *self, u8 cpumode, | |||
270 | return; | 271 | return; |
271 | } | 272 | } |
272 | try_again: | 273 | try_again: |
273 | al->map = thread__find_map(thread, type, al->addr); | 274 | al->map = map_groups__find(mg, type, al->addr); |
274 | if (al->map == NULL) { | 275 | if (al->map == NULL) { |
275 | /* | 276 | /* |
276 | * If this is outside of all known maps, and is a negative | 277 | * If this is outside of all known maps, and is a negative |
@@ -281,8 +282,8 @@ try_again: | |||
281 | * "[vdso]" dso, but for now lets use the old trick of looking | 282 | * "[vdso]" dso, but for now lets use the old trick of looking |
282 | * in the whole kernel symbol list. | 283 | * in the whole kernel symbol list. |
283 | */ | 284 | */ |
284 | if ((long long)al->addr < 0 && thread != kthread) { | 285 | if ((long long)al->addr < 0 && mg != kmaps) { |
285 | thread = kthread; | 286 | mg = kmaps; |
286 | goto try_again; | 287 | goto try_again; |
287 | } | 288 | } |
288 | al->sym = NULL; | 289 | al->sym = NULL; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e7508ad3450..93620234294 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -29,11 +29,11 @@ enum dso_origin { | |||
29 | }; | 29 | }; |
30 | 30 | ||
31 | static void dsos__add(struct list_head *head, struct dso *dso); | 31 | static void dsos__add(struct list_head *head, struct dso *dso); |
32 | static struct map *thread__find_map_by_name(struct thread *self, char *name); | 32 | static struct map *map_groups__find_by_name(struct map_groups *self, char *name); |
33 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 33 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
34 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); | 34 | struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); |
35 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 35 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
36 | struct thread *thread, symbol_filter_t filter); | 36 | struct map_groups *mg, symbol_filter_t filter); |
37 | unsigned int symbol__priv_size; | 37 | unsigned int symbol__priv_size; |
38 | static int vmlinux_path__nr_entries; | 38 | static int vmlinux_path__nr_entries; |
39 | static char **vmlinux_path; | 39 | static char **vmlinux_path; |
@@ -43,8 +43,8 @@ static struct symbol_conf symbol_conf__defaults = { | |||
43 | .try_vmlinux_path = true, | 43 | .try_vmlinux_path = true, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static struct thread kthread_mem; | 46 | static struct map_groups kmaps_mem; |
47 | struct thread *kthread = &kthread_mem; | 47 | struct map_groups *kmaps = &kmaps_mem; |
48 | 48 | ||
49 | bool dso__loaded(const struct dso *self, enum map_type type) | 49 | bool dso__loaded(const struct dso *self, enum map_type type) |
50 | { | 50 | { |
@@ -79,7 +79,7 @@ static void symbols__fixup_end(struct rb_root *self) | |||
79 | curr->end = roundup(curr->start, 4096); | 79 | curr->end = roundup(curr->start, 4096); |
80 | } | 80 | } |
81 | 81 | ||
82 | static void __thread__fixup_maps_end(struct thread *self, enum map_type type) | 82 | static void __map_groups__fixup_end(struct map_groups *self, enum map_type type) |
83 | { | 83 | { |
84 | struct map *prev, *curr; | 84 | struct map *prev, *curr; |
85 | struct rb_node *nd, *prevnd = rb_first(&self->maps[type]); | 85 | struct rb_node *nd, *prevnd = rb_first(&self->maps[type]); |
@@ -102,11 +102,11 @@ static void __thread__fixup_maps_end(struct thread *self, enum map_type type) | |||
102 | curr->end = ~0UL; | 102 | curr->end = ~0UL; |
103 | } | 103 | } |
104 | 104 | ||
105 | static void thread__fixup_maps_end(struct thread *self) | 105 | static void map_groups__fixup_end(struct map_groups *self) |
106 | { | 106 | { |
107 | int i; | 107 | int i; |
108 | for (i = 0; i < MAP__NR_TYPES; ++i) | 108 | for (i = 0; i < MAP__NR_TYPES; ++i) |
109 | __thread__fixup_maps_end(self, i); | 109 | __map_groups__fixup_end(self, i); |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct symbol *symbol__new(u64 start, u64 len, const char *name) | 112 | static struct symbol *symbol__new(u64 start, u64 len, const char *name) |
@@ -364,8 +364,8 @@ out_failure: | |||
364 | * kernel range is broken in several maps, named [kernel].N, as we don't have | 364 | * kernel range is broken in several maps, named [kernel].N, as we don't have |
365 | * the original ELF section names vmlinux have. | 365 | * the original ELF section names vmlinux have. |
366 | */ | 366 | */ |
367 | static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread *thread, | 367 | static int dso__split_kallsyms(struct dso *self, struct map *map, |
368 | symbol_filter_t filter) | 368 | struct map_groups *mg, symbol_filter_t filter) |
369 | { | 369 | { |
370 | struct map *curr_map = map; | 370 | struct map *curr_map = map; |
371 | struct symbol *pos; | 371 | struct symbol *pos; |
@@ -382,13 +382,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread | |||
382 | 382 | ||
383 | module = strchr(pos->name, '\t'); | 383 | module = strchr(pos->name, '\t'); |
384 | if (module) { | 384 | if (module) { |
385 | if (!thread->use_modules) | 385 | if (!mg->use_modules) |
386 | goto discard_symbol; | 386 | goto discard_symbol; |
387 | 387 | ||
388 | *module++ = '\0'; | 388 | *module++ = '\0'; |
389 | 389 | ||
390 | if (strcmp(self->name, module)) { | 390 | if (strcmp(self->name, module)) { |
391 | curr_map = thread__find_map_by_name(thread, module); | 391 | curr_map = map_groups__find_by_name(mg, module); |
392 | if (curr_map == NULL) { | 392 | if (curr_map == NULL) { |
393 | pr_debug("/proc/{kallsyms,modules} " | 393 | pr_debug("/proc/{kallsyms,modules} " |
394 | "inconsistency!\n"); | 394 | "inconsistency!\n"); |
@@ -419,7 +419,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread | |||
419 | } | 419 | } |
420 | 420 | ||
421 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; | 421 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; |
422 | __thread__insert_map(thread, curr_map); | 422 | map_groups__insert(mg, curr_map); |
423 | ++kernel_range; | 423 | ++kernel_range; |
424 | } | 424 | } |
425 | 425 | ||
@@ -440,7 +440,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
440 | 440 | ||
441 | 441 | ||
442 | static int dso__load_kallsyms(struct dso *self, struct map *map, | 442 | static int dso__load_kallsyms(struct dso *self, struct map *map, |
443 | struct thread *thread, symbol_filter_t filter) | 443 | struct map_groups *mg, symbol_filter_t filter) |
444 | { | 444 | { |
445 | if (dso__load_all_kallsyms(self, map) < 0) | 445 | if (dso__load_all_kallsyms(self, map) < 0) |
446 | return -1; | 446 | return -1; |
@@ -448,13 +448,13 @@ static int dso__load_kallsyms(struct dso *self, struct map *map, | |||
448 | symbols__fixup_end(&self->symbols[map->type]); | 448 | symbols__fixup_end(&self->symbols[map->type]); |
449 | self->origin = DSO__ORIG_KERNEL; | 449 | self->origin = DSO__ORIG_KERNEL; |
450 | 450 | ||
451 | return dso__split_kallsyms(self, map, thread, filter); | 451 | return dso__split_kallsyms(self, map, mg, filter); |
452 | } | 452 | } |
453 | 453 | ||
454 | size_t kernel_maps__fprintf(FILE *fp) | 454 | size_t kernel_maps__fprintf(FILE *fp) |
455 | { | 455 | { |
456 | size_t printed = fprintf(fp, "Kernel maps:\n"); | 456 | size_t printed = fprintf(fp, "Kernel maps:\n"); |
457 | printed += thread__fprintf_maps(kthread, fp); | 457 | printed += map_groups__fprintf_maps(kmaps, fp); |
458 | return printed + fprintf(fp, "END kernel maps\n"); | 458 | return printed + fprintf(fp, "END kernel maps\n"); |
459 | } | 459 | } |
460 | 460 | ||
@@ -745,7 +745,7 @@ out: | |||
745 | } | 745 | } |
746 | 746 | ||
747 | static int dso__load_sym(struct dso *self, struct map *map, | 747 | static int dso__load_sym(struct dso *self, struct map *map, |
748 | struct thread *thread, const char *name, int fd, | 748 | struct map_groups *mg, const char *name, int fd, |
749 | symbol_filter_t filter, int kernel, int kmodule) | 749 | symbol_filter_t filter, int kernel, int kmodule) |
750 | { | 750 | { |
751 | struct map *curr_map = map; | 751 | struct map *curr_map = map; |
@@ -849,7 +849,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
849 | snprintf(dso_name, sizeof(dso_name), | 849 | snprintf(dso_name, sizeof(dso_name), |
850 | "%s%s", self->short_name, section_name); | 850 | "%s%s", self->short_name, section_name); |
851 | 851 | ||
852 | curr_map = thread__find_map_by_name(thread, dso_name); | 852 | curr_map = map_groups__find_by_name(mg, dso_name); |
853 | if (curr_map == NULL) { | 853 | if (curr_map == NULL) { |
854 | u64 start = sym.st_value; | 854 | u64 start = sym.st_value; |
855 | 855 | ||
@@ -868,7 +868,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
868 | curr_map->map_ip = identity__map_ip; | 868 | curr_map->map_ip = identity__map_ip; |
869 | curr_map->unmap_ip = identity__map_ip; | 869 | curr_map->unmap_ip = identity__map_ip; |
870 | curr_dso->origin = DSO__ORIG_KERNEL; | 870 | curr_dso->origin = DSO__ORIG_KERNEL; |
871 | __thread__insert_map(kthread, curr_map); | 871 | map_groups__insert(kmaps, curr_map); |
872 | dsos__add(&dsos__kernel, curr_dso); | 872 | dsos__add(&dsos__kernel, curr_dso); |
873 | } else | 873 | } else |
874 | curr_dso = curr_map->dso; | 874 | curr_dso = curr_map->dso; |
@@ -1094,7 +1094,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1094 | dso__set_loaded(self, map->type); | 1094 | dso__set_loaded(self, map->type); |
1095 | 1095 | ||
1096 | if (self->kernel) | 1096 | if (self->kernel) |
1097 | return dso__load_kernel_sym(self, map, kthread, filter); | 1097 | return dso__load_kernel_sym(self, map, kmaps, filter); |
1098 | 1098 | ||
1099 | name = malloc(size); | 1099 | name = malloc(size); |
1100 | if (!name) | 1100 | if (!name) |
@@ -1180,7 +1180,7 @@ out: | |||
1180 | return ret; | 1180 | return ret; |
1181 | } | 1181 | } |
1182 | 1182 | ||
1183 | static struct map *thread__find_map_by_name(struct thread *self, char *name) | 1183 | static struct map *map_groups__find_by_name(struct map_groups *self, char *name) |
1184 | { | 1184 | { |
1185 | struct rb_node *nd; | 1185 | struct rb_node *nd; |
1186 | 1186 | ||
@@ -1228,7 +1228,7 @@ static int dsos__set_modules_path_dir(char *dirname) | |||
1228 | (int)(dot - dent->d_name), dent->d_name); | 1228 | (int)(dot - dent->d_name), dent->d_name); |
1229 | 1229 | ||
1230 | strxfrchar(dso_name, '-', '_'); | 1230 | strxfrchar(dso_name, '-', '_'); |
1231 | map = thread__find_map_by_name(kthread, dso_name); | 1231 | map = map_groups__find_by_name(kmaps, dso_name); |
1232 | if (map == NULL) | 1232 | if (map == NULL) |
1233 | continue; | 1233 | continue; |
1234 | 1234 | ||
@@ -1281,7 +1281,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
1281 | return self; | 1281 | return self; |
1282 | } | 1282 | } |
1283 | 1283 | ||
1284 | static int thread__create_module_maps(struct thread *self) | 1284 | static int map_groups__create_module_maps(struct map_groups *self) |
1285 | { | 1285 | { |
1286 | char *line = NULL; | 1286 | char *line = NULL; |
1287 | size_t n; | 1287 | size_t n; |
@@ -1338,7 +1338,7 @@ static int thread__create_module_maps(struct thread *self) | |||
1338 | dso->has_build_id = true; | 1338 | dso->has_build_id = true; |
1339 | 1339 | ||
1340 | dso->origin = DSO__ORIG_KMODULE; | 1340 | dso->origin = DSO__ORIG_KMODULE; |
1341 | __thread__insert_map(self, map); | 1341 | map_groups__insert(self, map); |
1342 | dsos__add(&dsos__kernel, dso); | 1342 | dsos__add(&dsos__kernel, dso); |
1343 | } | 1343 | } |
1344 | 1344 | ||
@@ -1353,7 +1353,8 @@ out_failure: | |||
1353 | return -1; | 1353 | return -1; |
1354 | } | 1354 | } |
1355 | 1355 | ||
1356 | static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *thread, | 1356 | static int dso__load_vmlinux(struct dso *self, struct map *map, |
1357 | struct map_groups *mg, | ||
1357 | const char *vmlinux, symbol_filter_t filter) | 1358 | const char *vmlinux, symbol_filter_t filter) |
1358 | { | 1359 | { |
1359 | int err = -1, fd; | 1360 | int err = -1, fd; |
@@ -1387,14 +1388,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *t | |||
1387 | return -1; | 1388 | return -1; |
1388 | 1389 | ||
1389 | dso__set_loaded(self, map->type); | 1390 | dso__set_loaded(self, map->type); |
1390 | err = dso__load_sym(self, map, thread, self->long_name, fd, filter, 1, 0); | 1391 | err = dso__load_sym(self, map, mg, self->long_name, fd, filter, 1, 0); |
1391 | close(fd); | 1392 | close(fd); |
1392 | 1393 | ||
1393 | return err; | 1394 | return err; |
1394 | } | 1395 | } |
1395 | 1396 | ||
1396 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 1397 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
1397 | struct thread *thread, symbol_filter_t filter) | 1398 | struct map_groups *mg, symbol_filter_t filter) |
1398 | { | 1399 | { |
1399 | int err; | 1400 | int err; |
1400 | bool is_kallsyms; | 1401 | bool is_kallsyms; |
@@ -1404,7 +1405,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1404 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | 1405 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", |
1405 | vmlinux_path__nr_entries); | 1406 | vmlinux_path__nr_entries); |
1406 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | 1407 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { |
1407 | err = dso__load_vmlinux(self, map, thread, | 1408 | err = dso__load_vmlinux(self, map, mg, |
1408 | vmlinux_path[i], filter); | 1409 | vmlinux_path[i], filter); |
1409 | if (err > 0) { | 1410 | if (err > 0) { |
1410 | pr_debug("Using %s for symbols\n", | 1411 | pr_debug("Using %s for symbols\n", |
@@ -1420,12 +1421,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1420 | if (is_kallsyms) | 1421 | if (is_kallsyms) |
1421 | goto do_kallsyms; | 1422 | goto do_kallsyms; |
1422 | 1423 | ||
1423 | err = dso__load_vmlinux(self, map, thread, self->long_name, filter); | 1424 | err = dso__load_vmlinux(self, map, mg, self->long_name, filter); |
1424 | if (err <= 0) { | 1425 | if (err <= 0) { |
1425 | pr_info("The file %s cannot be used, " | 1426 | pr_info("The file %s cannot be used, " |
1426 | "trying to use /proc/kallsyms...", self->long_name); | 1427 | "trying to use /proc/kallsyms...", self->long_name); |
1427 | do_kallsyms: | 1428 | do_kallsyms: |
1428 | err = dso__load_kallsyms(self, map, thread, filter); | 1429 | err = dso__load_kallsyms(self, map, mg, filter); |
1429 | if (err > 0 && !is_kallsyms) | 1430 | if (err > 0 && !is_kallsyms) |
1430 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); | 1431 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); |
1431 | } | 1432 | } |
@@ -1508,7 +1509,7 @@ size_t dsos__fprintf_buildid(FILE *fp) | |||
1508 | __dsos__fprintf_buildid(&dsos__user, fp)); | 1509 | __dsos__fprintf_buildid(&dsos__user, fp)); |
1509 | } | 1510 | } |
1510 | 1511 | ||
1511 | static int thread__create_kernel_map(struct thread *self, const char *vmlinux) | 1512 | static int map_groups__create_kernel_map(struct map_groups *self, const char *vmlinux) |
1512 | { | 1513 | { |
1513 | struct map *kmap; | 1514 | struct map *kmap; |
1514 | struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]"); | 1515 | struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]"); |
@@ -1533,7 +1534,7 @@ static int thread__create_kernel_map(struct thread *self, const char *vmlinux) | |||
1533 | sizeof(kernel->build_id)) == 0) | 1534 | sizeof(kernel->build_id)) == 0) |
1534 | kernel->has_build_id = true; | 1535 | kernel->has_build_id = true; |
1535 | 1536 | ||
1536 | __thread__insert_map(self, kmap); | 1537 | map_groups__insert(self, kmap); |
1537 | dsos__add(&dsos__kernel, kernel); | 1538 | dsos__add(&dsos__kernel, kernel); |
1538 | dsos__add(&dsos__user, vdso); | 1539 | dsos__add(&dsos__user, vdso); |
1539 | 1540 | ||
@@ -1607,23 +1608,23 @@ int symbol__init(struct symbol_conf *conf) | |||
1607 | 1608 | ||
1608 | elf_version(EV_CURRENT); | 1609 | elf_version(EV_CURRENT); |
1609 | symbol__priv_size = pconf->priv_size; | 1610 | symbol__priv_size = pconf->priv_size; |
1610 | thread__init(kthread, 0); | 1611 | map_groups__init(kmaps); |
1611 | 1612 | ||
1612 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) | 1613 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) |
1613 | return -1; | 1614 | return -1; |
1614 | 1615 | ||
1615 | if (thread__create_kernel_map(kthread, pconf->vmlinux_name) < 0) { | 1616 | if (map_groups__create_kernel_map(kmaps, pconf->vmlinux_name) < 0) { |
1616 | vmlinux_path__exit(); | 1617 | vmlinux_path__exit(); |
1617 | return -1; | 1618 | return -1; |
1618 | } | 1619 | } |
1619 | 1620 | ||
1620 | kthread->use_modules = pconf->use_modules; | 1621 | kmaps->use_modules = pconf->use_modules; |
1621 | if (pconf->use_modules && thread__create_module_maps(kthread) < 0) | 1622 | if (pconf->use_modules && map_groups__create_module_maps(kmaps) < 0) |
1622 | pr_debug("Failed to load list of modules in use, " | 1623 | pr_debug("Failed to load list of modules in use, " |
1623 | "continuing...\n"); | 1624 | "continuing...\n"); |
1624 | /* | 1625 | /* |
1625 | * Now that we have all the maps created, just set the ->end of them: | 1626 | * Now that we have all the maps created, just set the ->end of them: |
1626 | */ | 1627 | */ |
1627 | thread__fixup_maps_end(kthread); | 1628 | map_groups__fixup_end(kmaps); |
1628 | return 0; | 1629 | return 0; |
1629 | } | 1630 | } |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 17003efa0b3..6e1da1ea631 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -113,8 +113,8 @@ size_t kernel_maps__fprintf(FILE *fp); | |||
113 | 113 | ||
114 | int symbol__init(struct symbol_conf *conf); | 114 | int symbol__init(struct symbol_conf *conf); |
115 | 115 | ||
116 | struct thread; | 116 | struct map_groups; |
117 | struct thread *kthread; | 117 | struct map_groups *kmaps; |
118 | extern struct list_head dsos__user, dsos__kernel; | 118 | extern struct list_head dsos__user, dsos__kernel; |
119 | extern struct dso *vdso; | 119 | extern struct dso *vdso; |
120 | #endif /* __PERF_SYMBOL */ | 120 | #endif /* __PERF_SYMBOL */ |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 603f5610861..a1285129c83 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -9,11 +9,9 @@ | |||
9 | static struct rb_root threads; | 9 | static struct rb_root threads; |
10 | static struct thread *last_match; | 10 | static struct thread *last_match; |
11 | 11 | ||
12 | void thread__init(struct thread *self, pid_t pid) | 12 | void map_groups__init(struct map_groups *self) |
13 | { | 13 | { |
14 | int i; | 14 | int i; |
15 | self->pid = pid; | ||
16 | self->comm = NULL; | ||
17 | for (i = 0; i < MAP__NR_TYPES; ++i) { | 15 | for (i = 0; i < MAP__NR_TYPES; ++i) { |
18 | self->maps[i] = RB_ROOT; | 16 | self->maps[i] = RB_ROOT; |
19 | INIT_LIST_HEAD(&self->removed_maps[i]); | 17 | INIT_LIST_HEAD(&self->removed_maps[i]); |
@@ -25,7 +23,8 @@ static struct thread *thread__new(pid_t pid) | |||
25 | struct thread *self = zalloc(sizeof(*self)); | 23 | struct thread *self = zalloc(sizeof(*self)); |
26 | 24 | ||
27 | if (self != NULL) { | 25 | if (self != NULL) { |
28 | thread__init(self, pid); | 26 | map_groups__init(&self->mg); |
27 | self->pid = pid; | ||
29 | self->comm = malloc(32); | 28 | self->comm = malloc(32); |
30 | if (self->comm) | 29 | if (self->comm) |
31 | snprintf(self->comm, 32, ":%d", self->pid); | 30 | snprintf(self->comm, 32, ":%d", self->pid); |
@@ -57,8 +56,8 @@ static const char *map_type__name[MAP__NR_TYPES] = { | |||
57 | [MAP__FUNCTION] = "Functions", | 56 | [MAP__FUNCTION] = "Functions", |
58 | }; | 57 | }; |
59 | 58 | ||
60 | static size_t __thread__fprintf_maps(struct thread *self, | 59 | static size_t __map_groups__fprintf_maps(struct map_groups *self, |
61 | enum map_type type, FILE *fp) | 60 | enum map_type type, FILE *fp) |
62 | { | 61 | { |
63 | size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); | 62 | size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); |
64 | struct rb_node *nd; | 63 | struct rb_node *nd; |
@@ -76,16 +75,16 @@ static size_t __thread__fprintf_maps(struct thread *self, | |||
76 | return printed; | 75 | return printed; |
77 | } | 76 | } |
78 | 77 | ||
79 | size_t thread__fprintf_maps(struct thread *self, FILE *fp) | 78 | size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp) |
80 | { | 79 | { |
81 | size_t printed = 0, i; | 80 | size_t printed = 0, i; |
82 | for (i = 0; i < MAP__NR_TYPES; ++i) | 81 | for (i = 0; i < MAP__NR_TYPES; ++i) |
83 | printed += __thread__fprintf_maps(self, i, fp); | 82 | printed += __map_groups__fprintf_maps(self, i, fp); |
84 | return printed; | 83 | return printed; |
85 | } | 84 | } |
86 | 85 | ||
87 | static size_t __thread__fprintf_removed_maps(struct thread *self, | 86 | static size_t __map_groups__fprintf_removed_maps(struct map_groups *self, |
88 | enum map_type type, FILE *fp) | 87 | enum map_type type, FILE *fp) |
89 | { | 88 | { |
90 | struct map *pos; | 89 | struct map *pos; |
91 | size_t printed = 0; | 90 | size_t printed = 0; |
@@ -101,20 +100,25 @@ static size_t __thread__fprintf_removed_maps(struct thread *self, | |||
101 | return printed; | 100 | return printed; |
102 | } | 101 | } |
103 | 102 | ||
104 | static size_t thread__fprintf_removed_maps(struct thread *self, FILE *fp) | 103 | static size_t map_groups__fprintf_removed_maps(struct map_groups *self, FILE *fp) |
105 | { | 104 | { |
106 | size_t printed = 0, i; | 105 | size_t printed = 0, i; |
107 | for (i = 0; i < MAP__NR_TYPES; ++i) | 106 | for (i = 0; i < MAP__NR_TYPES; ++i) |
108 | printed += __thread__fprintf_removed_maps(self, i, fp); | 107 | printed += __map_groups__fprintf_removed_maps(self, i, fp); |
109 | return printed; | 108 | return printed; |
110 | } | 109 | } |
111 | 110 | ||
112 | static size_t thread__fprintf(struct thread *self, FILE *fp) | 111 | static size_t map_groups__fprintf(struct map_groups *self, FILE *fp) |
113 | { | 112 | { |
114 | size_t printed = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); | 113 | size_t printed = map_groups__fprintf_maps(self, fp); |
115 | printed += thread__fprintf_removed_maps(self, fp); | ||
116 | printed += fprintf(fp, "Removed maps:\n"); | 114 | printed += fprintf(fp, "Removed maps:\n"); |
117 | return printed + thread__fprintf_removed_maps(self, fp); | 115 | return printed + map_groups__fprintf_removed_maps(self, fp); |
116 | } | ||
117 | |||
118 | static size_t thread__fprintf(struct thread *self, FILE *fp) | ||
119 | { | ||
120 | return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + | ||
121 | map_groups__fprintf(&self->mg, fp); | ||
118 | } | 122 | } |
119 | 123 | ||
120 | struct thread *threads__findnew(pid_t pid) | 124 | struct thread *threads__findnew(pid_t pid) |
@@ -168,7 +172,8 @@ struct thread *register_idle_thread(void) | |||
168 | return thread; | 172 | return thread; |
169 | } | 173 | } |
170 | 174 | ||
171 | static void thread__remove_overlappings(struct thread *self, struct map *map) | 175 | static void map_groups__remove_overlappings(struct map_groups *self, |
176 | struct map *map) | ||
172 | { | 177 | { |
173 | struct rb_root *root = &self->maps[map->type]; | 178 | struct rb_root *root = &self->maps[map->type]; |
174 | struct rb_node *next = rb_first(root); | 179 | struct rb_node *next = rb_first(root); |
@@ -238,12 +243,15 @@ struct map *maps__find(struct rb_root *maps, u64 ip) | |||
238 | 243 | ||
239 | void thread__insert_map(struct thread *self, struct map *map) | 244 | void thread__insert_map(struct thread *self, struct map *map) |
240 | { | 245 | { |
241 | thread__remove_overlappings(self, map); | 246 | map_groups__remove_overlappings(&self->mg, map); |
242 | maps__insert(&self->maps[map->type], map); | 247 | map_groups__insert(&self->mg, map); |
243 | } | 248 | } |
244 | 249 | ||
245 | static int thread__clone_maps(struct thread *self, struct thread *parent, | 250 | /* |
246 | enum map_type type) | 251 | * XXX This should not really _copy_ te maps, but refcount them. |
252 | */ | ||
253 | static int map_groups__clone(struct map_groups *self, | ||
254 | struct map_groups *parent, enum map_type type) | ||
247 | { | 255 | { |
248 | struct rb_node *nd; | 256 | struct rb_node *nd; |
249 | for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { | 257 | for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) { |
@@ -251,7 +259,7 @@ static int thread__clone_maps(struct thread *self, struct thread *parent, | |||
251 | struct map *new = map__clone(map); | 259 | struct map *new = map__clone(map); |
252 | if (new == NULL) | 260 | if (new == NULL) |
253 | return -ENOMEM; | 261 | return -ENOMEM; |
254 | thread__insert_map(self, new); | 262 | map_groups__insert(self, new); |
255 | } | 263 | } |
256 | return 0; | 264 | return 0; |
257 | } | 265 | } |
@@ -267,7 +275,7 @@ int thread__fork(struct thread *self, struct thread *parent) | |||
267 | return -ENOMEM; | 275 | return -ENOMEM; |
268 | 276 | ||
269 | for (i = 0; i < MAP__NR_TYPES; ++i) | 277 | for (i = 0; i < MAP__NR_TYPES; ++i) |
270 | if (thread__clone_maps(self, parent, i) < 0) | 278 | if (map_groups__clone(&self->mg, &parent->mg, i) < 0) |
271 | return -ENOMEM; | 279 | return -ENOMEM; |
272 | return 0; | 280 | return 0; |
273 | } | 281 | } |
@@ -286,11 +294,11 @@ size_t threads__fprintf(FILE *fp) | |||
286 | return ret; | 294 | return ret; |
287 | } | 295 | } |
288 | 296 | ||
289 | struct symbol *thread__find_symbol(struct thread *self, | 297 | struct symbol *map_groups__find_symbol(struct map_groups *self, |
290 | enum map_type type, u64 addr, | 298 | enum map_type type, u64 addr, |
291 | symbol_filter_t filter) | 299 | symbol_filter_t filter) |
292 | { | 300 | { |
293 | struct map *map = thread__find_map(self, type, addr); | 301 | struct map *map = map_groups__find(self, type, addr); |
294 | 302 | ||
295 | if (map != NULL) | 303 | if (map != NULL) |
296 | return map__find_symbol(map, map->map_ip(map, addr), filter); | 304 | return map__find_symbol(map, map->map_ip(map, addr), filter); |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 686d6e914d9..a6333f3716a 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -5,52 +5,63 @@ | |||
5 | #include <unistd.h> | 5 | #include <unistd.h> |
6 | #include "symbol.h" | 6 | #include "symbol.h" |
7 | 7 | ||
8 | struct thread { | 8 | struct map_groups { |
9 | struct rb_node rb_node; | ||
10 | struct rb_root maps[MAP__NR_TYPES]; | 9 | struct rb_root maps[MAP__NR_TYPES]; |
11 | struct list_head removed_maps[MAP__NR_TYPES]; | 10 | struct list_head removed_maps[MAP__NR_TYPES]; |
12 | pid_t pid; | ||
13 | bool use_modules; | 11 | bool use_modules; |
12 | }; | ||
13 | |||
14 | struct thread { | ||
15 | struct rb_node rb_node; | ||
16 | struct map_groups mg; | ||
17 | pid_t pid; | ||
14 | char shortname[3]; | 18 | char shortname[3]; |
15 | char *comm; | 19 | char *comm; |
16 | int comm_len; | 20 | int comm_len; |
17 | }; | 21 | }; |
18 | 22 | ||
19 | void thread__init(struct thread *self, pid_t pid); | 23 | void map_groups__init(struct map_groups *self); |
20 | int thread__set_comm(struct thread *self, const char *comm); | 24 | int thread__set_comm(struct thread *self, const char *comm); |
21 | int thread__comm_len(struct thread *self); | 25 | int thread__comm_len(struct thread *self); |
22 | struct thread *threads__findnew(pid_t pid); | 26 | struct thread *threads__findnew(pid_t pid); |
23 | struct thread *register_idle_thread(void); | 27 | struct thread *register_idle_thread(void); |
24 | void thread__insert_map(struct thread *self, struct map *map); | 28 | void thread__insert_map(struct thread *self, struct map *map); |
25 | int thread__fork(struct thread *self, struct thread *parent); | 29 | int thread__fork(struct thread *self, struct thread *parent); |
26 | size_t thread__fprintf_maps(struct thread *self, FILE *fp); | 30 | size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp); |
27 | size_t threads__fprintf(FILE *fp); | 31 | size_t threads__fprintf(FILE *fp); |
28 | 32 | ||
29 | void maps__insert(struct rb_root *maps, struct map *map); | 33 | void maps__insert(struct rb_root *maps, struct map *map); |
30 | struct map *maps__find(struct rb_root *maps, u64 addr); | 34 | struct map *maps__find(struct rb_root *maps, u64 addr); |
31 | 35 | ||
32 | static inline struct map *thread__find_map(struct thread *self, | 36 | static inline void map_groups__insert(struct map_groups *self, struct map *map) |
37 | { | ||
38 | maps__insert(&self->maps[map->type], map); | ||
39 | } | ||
40 | |||
41 | static inline struct map *map_groups__find(struct map_groups *self, | ||
33 | enum map_type type, u64 addr) | 42 | enum map_type type, u64 addr) |
34 | { | 43 | { |
35 | return self ? maps__find(&self->maps[type], addr) : NULL; | 44 | return maps__find(&self->maps[type], addr); |
36 | } | 45 | } |
37 | 46 | ||
38 | static inline void __thread__insert_map(struct thread *self, struct map *map) | 47 | static inline struct map *thread__find_map(struct thread *self, |
48 | enum map_type type, u64 addr) | ||
39 | { | 49 | { |
40 | maps__insert(&self->maps[map->type], map); | 50 | return self ? map_groups__find(&self->mg, type, addr) : NULL; |
41 | } | 51 | } |
42 | 52 | ||
43 | void thread__find_addr_location(struct thread *self, u8 cpumode, | 53 | void thread__find_addr_location(struct thread *self, u8 cpumode, |
44 | enum map_type type, u64 addr, | 54 | enum map_type type, u64 addr, |
45 | struct addr_location *al, | 55 | struct addr_location *al, |
46 | symbol_filter_t filter); | 56 | symbol_filter_t filter); |
47 | struct symbol *thread__find_symbol(struct thread *self, | 57 | struct symbol *map_groups__find_symbol(struct map_groups *self, |
48 | enum map_type type, u64 addr, | 58 | enum map_type type, u64 addr, |
49 | symbol_filter_t filter); | 59 | symbol_filter_t filter); |
50 | 60 | ||
51 | static inline struct symbol * | 61 | static inline struct symbol * |
52 | thread__find_function(struct thread *self, u64 addr, symbol_filter_t filter) | 62 | map_groups__find_function(struct map_groups *self, u64 addr, |
63 | symbol_filter_t filter) | ||
53 | { | 64 | { |
54 | return thread__find_symbol(self, MAP__FUNCTION, addr, filter); | 65 | return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter); |
55 | } | 66 | } |
56 | #endif /* __PERF_THREAD_H */ | 67 | #endif /* __PERF_THREAD_H */ |