perf symbols: Protect dso symbol loading using a mutex

Add mutex to protect it from concurrent dso__load().

Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1431909055-21442-26-git-send-email-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Namhyung Kim 2015-05-18 09:30:40 +09:00 committed by Arnaldo Carvalho de Melo
parent 9c9f5a2f19
commit 4a936edc31
3 changed files with 27 additions and 10 deletions

View File

@ -936,6 +936,7 @@ struct dso *dso__new(const char *name)
RB_CLEAR_NODE(&dso->rb_node); RB_CLEAR_NODE(&dso->rb_node);
INIT_LIST_HEAD(&dso->node); INIT_LIST_HEAD(&dso->node);
INIT_LIST_HEAD(&dso->data.open_entry); INIT_LIST_HEAD(&dso->data.open_entry);
pthread_mutex_init(&dso->lock, NULL);
} }
return dso; return dso;
@ -966,6 +967,7 @@ void dso__delete(struct dso *dso)
dso_cache__free(&dso->data.cache); dso_cache__free(&dso->data.cache);
dso__free_a2l(dso); dso__free_a2l(dso);
zfree(&dso->symsrc_filename); zfree(&dso->symsrc_filename);
pthread_mutex_destroy(&dso->lock);
free(dso); free(dso);
} }

View File

@ -129,6 +129,7 @@ struct dsos {
struct auxtrace_cache; struct auxtrace_cache;
struct dso { struct dso {
pthread_mutex_t lock;
struct list_head node; struct list_head node;
struct rb_node rb_node; /* rbtree node sorted by long name */ struct rb_node rb_node; /* rbtree node sorted by long name */
struct rb_root symbols[MAP__NR_TYPES]; struct rb_root symbols[MAP__NR_TYPES];

View File

@ -1383,12 +1383,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
struct symsrc *syms_ss = NULL, *runtime_ss = NULL; struct symsrc *syms_ss = NULL, *runtime_ss = NULL;
bool kmod; bool kmod;
dso__set_loaded(dso, map->type); pthread_mutex_lock(&dso->lock);
if (dso->kernel == DSO_TYPE_KERNEL) /* check again under the dso->lock */
return dso__load_kernel_sym(dso, map, filter); if (dso__loaded(dso, map->type)) {
else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) ret = 1;
return dso__load_guest_kernel_sym(dso, map, filter); goto out;
}
if (dso->kernel) {
if (dso->kernel == DSO_TYPE_KERNEL)
ret = dso__load_kernel_sym(dso, map, filter);
else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
ret = dso__load_guest_kernel_sym(dso, map, filter);
goto out;
}
if (map->groups && map->groups->machine) if (map->groups && map->groups->machine)
machine = map->groups->machine; machine = map->groups->machine;
@ -1401,18 +1411,18 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
struct stat st; struct stat st;
if (lstat(dso->name, &st) < 0) if (lstat(dso->name, &st) < 0)
return -1; goto out;
if (st.st_uid && (st.st_uid != geteuid())) { if (st.st_uid && (st.st_uid != geteuid())) {
pr_warning("File %s not owned by current user or root, " pr_warning("File %s not owned by current user or root, "
"ignoring it.\n", dso->name); "ignoring it.\n", dso->name);
return -1; goto out;
} }
ret = dso__load_perf_map(dso, map, filter); ret = dso__load_perf_map(dso, map, filter);
dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
DSO_BINARY_TYPE__NOT_FOUND; DSO_BINARY_TYPE__NOT_FOUND;
return ret; goto out;
} }
if (machine) if (machine)
@ -1420,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
name = malloc(PATH_MAX); name = malloc(PATH_MAX);
if (!name) if (!name)
return -1; goto out;
kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE || kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP || dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
@ -1501,7 +1511,11 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
out_free: out_free:
free(name); free(name);
if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) if (ret < 0 && strstr(dso->name, " (deleted)") != NULL)
return 0; ret = 0;
out:
dso__set_loaded(dso, map->type);
pthread_mutex_unlock(&dso->lock);
return ret; return ret;
} }