perf symbols: Protect dso symbol loading using a mutex
authorNamhyung Kim <namhyung@kernel.org>
Mon, 18 May 2015 00:30:40 +0000 (09:30 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 18 May 2015 13:17:36 +0000 (10:17 -0300)
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>
tools/perf/util/dso.c
tools/perf/util/dso.h
tools/perf/util/symbol.c

index 13d9ae0..482d602 100644 (file)
@@ -936,6 +936,7 @@ struct dso *dso__new(const char *name)
                RB_CLEAR_NODE(&dso->rb_node);
                INIT_LIST_HEAD(&dso->node);
                INIT_LIST_HEAD(&dso->data.open_entry);
+               pthread_mutex_init(&dso->lock, NULL);
        }
 
        return dso;
@@ -966,6 +967,7 @@ void dso__delete(struct dso *dso)
        dso_cache__free(&dso->data.cache);
        dso__free_a2l(dso);
        zfree(&dso->symsrc_filename);
+       pthread_mutex_destroy(&dso->lock);
        free(dso);
 }
 
index 3d79c74..b26ec3a 100644 (file)
@@ -129,6 +129,7 @@ struct dsos {
 struct auxtrace_cache;
 
 struct dso {
+       pthread_mutex_t  lock;
        struct list_head node;
        struct rb_node   rb_node;       /* rbtree node sorted by long name */
        struct rb_root   symbols[MAP__NR_TYPES];
index 45ba48a..9ef8b89 100644 (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;
        bool kmod;
 
-       dso__set_loaded(dso, map->type);
+       pthread_mutex_lock(&dso->lock);
+
+       /* check again under the dso->lock */
+       if (dso__loaded(dso, map->type)) {
+               ret = 1;
+               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);
 
-       if (dso->kernel == DSO_TYPE_KERNEL)
-               return dso__load_kernel_sym(dso, map, filter);
-       else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
-               return dso__load_guest_kernel_sym(dso, map, filter);
+               goto out;
+       }
 
        if (map->groups && 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;
 
                if (lstat(dso->name, &st) < 0)
-                       return -1;
+                       goto out;
 
                if (st.st_uid && (st.st_uid != geteuid())) {
                        pr_warning("File %s not owned by current user or root, "
                                "ignoring it.\n", dso->name);
-                       return -1;
+                       goto out;
                }
 
                ret = dso__load_perf_map(dso, map, filter);
                dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
                                             DSO_BINARY_TYPE__NOT_FOUND;
-               return ret;
+               goto out;
        }
 
        if (machine)
@@ -1420,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
 
        name = malloc(PATH_MAX);
        if (!name)
-               return -1;
+               goto out;
 
        kmod = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
                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:
        free(name);
        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;
 }