diff options
author | Jiri Olsa <jolsa@kernel.org> | 2016-07-04 08:16:23 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-07-04 19:27:25 -0400 |
commit | 6c502584438bda63fc1a67606854fb0b300465cd (patch) | |
tree | 670c04d2c278b314f4698922f6778aa73c6e963d /tools | |
parent | a2873325ffb21cecca8032673eb698cb4d778dc6 (diff) |
perf unwind: Call unwind__prepare_access for forked thread
Currently we call unwind__prepare_access for map event. In case we
report fork event the thread inherits its parent's maps and
unwind__prepare_access is never called for the thread.
This causes unwind__get_entries seeing uninitialized
unwind_libunwind_ops and thus returning no callchain.
Adding unwind__prepare_access calls for fork even processing.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1467634583-29147-5-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/map.c | 9 | ||||
-rw-r--r-- | tools/perf/util/map.h | 2 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 37 |
3 files changed, 44 insertions, 4 deletions
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index b19bcd3b7128..b39b12a1208d 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "debug.h" | 15 | #include "debug.h" |
16 | #include "machine.h" | 16 | #include "machine.h" |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include "unwind.h" | ||
18 | 19 | ||
19 | static void __maps__insert(struct maps *maps, struct map *map); | 20 | static void __maps__insert(struct maps *maps, struct map *map); |
20 | 21 | ||
@@ -744,9 +745,10 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, | |||
744 | /* | 745 | /* |
745 | * XXX This should not really _copy_ te maps, but refcount them. | 746 | * XXX This should not really _copy_ te maps, but refcount them. |
746 | */ | 747 | */ |
747 | int map_groups__clone(struct map_groups *mg, | 748 | int map_groups__clone(struct thread *thread, |
748 | struct map_groups *parent, enum map_type type) | 749 | struct map_groups *parent, enum map_type type) |
749 | { | 750 | { |
751 | struct map_groups *mg = thread->mg; | ||
750 | int err = -ENOMEM; | 752 | int err = -ENOMEM; |
751 | struct map *map; | 753 | struct map *map; |
752 | struct maps *maps = &parent->maps[type]; | 754 | struct maps *maps = &parent->maps[type]; |
@@ -757,6 +759,11 @@ int map_groups__clone(struct map_groups *mg, | |||
757 | struct map *new = map__clone(map); | 759 | struct map *new = map__clone(map); |
758 | if (new == NULL) | 760 | if (new == NULL) |
759 | goto out_unlock; | 761 | goto out_unlock; |
762 | |||
763 | err = unwind__prepare_access(thread, new, NULL); | ||
764 | if (err) | ||
765 | goto out_unlock; | ||
766 | |||
760 | map_groups__insert(mg, new); | 767 | map_groups__insert(mg, new); |
761 | map__put(new); | 768 | map__put(new); |
762 | } | 769 | } |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 7309d64ce39e..d83396ceecba 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -194,7 +194,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, | |||
194 | struct map **mapp, symbol_filter_t filter); | 194 | struct map **mapp, symbol_filter_t filter); |
195 | void map_groups__init(struct map_groups *mg, struct machine *machine); | 195 | void map_groups__init(struct map_groups *mg, struct machine *machine); |
196 | void map_groups__exit(struct map_groups *mg); | 196 | void map_groups__exit(struct map_groups *mg); |
197 | int map_groups__clone(struct map_groups *mg, | 197 | int map_groups__clone(struct thread *thread, |
198 | struct map_groups *parent, enum map_type type); | 198 | struct map_groups *parent, enum map_type type); |
199 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); | 199 | size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); |
200 | 200 | ||
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 2439b122a4e4..8b10a55410a2 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -212,6 +212,39 @@ int thread__insert_map(struct thread *thread, struct map *map) | |||
212 | return 0; | 212 | return 0; |
213 | } | 213 | } |
214 | 214 | ||
215 | static int __thread__prepare_access(struct thread *thread) | ||
216 | { | ||
217 | bool initialized = false; | ||
218 | int i, err = 0; | ||
219 | |||
220 | for (i = 0; i < MAP__NR_TYPES; ++i) { | ||
221 | struct maps *maps = &thread->mg->maps[i]; | ||
222 | struct map *map; | ||
223 | |||
224 | pthread_rwlock_rdlock(&maps->lock); | ||
225 | |||
226 | for (map = maps__first(maps); map; map = map__next(map)) { | ||
227 | err = unwind__prepare_access(thread, map, &initialized); | ||
228 | if (err || initialized) | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | pthread_rwlock_unlock(&maps->lock); | ||
233 | } | ||
234 | |||
235 | return err; | ||
236 | } | ||
237 | |||
238 | static int thread__prepare_access(struct thread *thread) | ||
239 | { | ||
240 | int err = 0; | ||
241 | |||
242 | if (symbol_conf.use_callchain) | ||
243 | err = __thread__prepare_access(thread); | ||
244 | |||
245 | return err; | ||
246 | } | ||
247 | |||
215 | static int thread__clone_map_groups(struct thread *thread, | 248 | static int thread__clone_map_groups(struct thread *thread, |
216 | struct thread *parent) | 249 | struct thread *parent) |
217 | { | 250 | { |
@@ -219,7 +252,7 @@ static int thread__clone_map_groups(struct thread *thread, | |||
219 | 252 | ||
220 | /* This is new thread, we share map groups for process. */ | 253 | /* This is new thread, we share map groups for process. */ |
221 | if (thread->pid_ == parent->pid_) | 254 | if (thread->pid_ == parent->pid_) |
222 | return 0; | 255 | return thread__prepare_access(thread); |
223 | 256 | ||
224 | if (thread->mg == parent->mg) { | 257 | if (thread->mg == parent->mg) { |
225 | pr_debug("broken map groups on thread %d/%d parent %d/%d\n", | 258 | pr_debug("broken map groups on thread %d/%d parent %d/%d\n", |
@@ -229,7 +262,7 @@ static int thread__clone_map_groups(struct thread *thread, | |||
229 | 262 | ||
230 | /* But this one is new process, copy maps. */ | 263 | /* But this one is new process, copy maps. */ |
231 | for (i = 0; i < MAP__NR_TYPES; ++i) | 264 | for (i = 0; i < MAP__NR_TYPES; ++i) |
232 | if (map_groups__clone(thread->mg, parent->mg, i) < 0) | 265 | if (map_groups__clone(thread, parent->mg, i) < 0) |
233 | return -ENOMEM; | 266 | return -ENOMEM; |
234 | 267 | ||
235 | return 0; | 268 | return 0; |