aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2015-06-01 14:40:01 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-06-08 09:31:40 -0400
commite88078442232f3bbcb4ff1d24b3f9ab3dca472b9 (patch)
treed755616b5eb4d95607e4d75f36f221b9e7de4972 /tools
parent9f2de31542f1ac38a15117f90ee6b8449951d86e (diff)
perf tools: Protect accesses the dso rbtrees/lists with a rw lock
To allow concurrent access, next step: refcount struct dso instances, so that we can ditch unused them when the last map pointing to it goes away. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Link: http://lkml.kernel.org/n/tip-yk1k08etpd2aoe3tnrf0oizn@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/dso.c52
-rw-r--r--tools/perf/util/dso.h10
-rw-r--r--tools/perf/util/machine.c27
-rw-r--r--tools/perf/util/vdso.c53
4 files changed, 95 insertions, 47 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 5ec9e892c89b..ff0204ac4321 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -889,8 +889,8 @@ struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
889 * Either one of the dso or name parameter must be non-NULL or the 889 * Either one of the dso or name parameter must be non-NULL or the
890 * function will not work. 890 * function will not work.
891 */ 891 */
892static struct dso *dso__findlink_by_longname(struct rb_root *root, 892static struct dso *__dso__findlink_by_longname(struct rb_root *root,
893 struct dso *dso, const char *name) 893 struct dso *dso, const char *name)
894{ 894{
895 struct rb_node **p = &root->rb_node; 895 struct rb_node **p = &root->rb_node;
896 struct rb_node *parent = NULL; 896 struct rb_node *parent = NULL;
@@ -937,10 +937,10 @@ static struct dso *dso__findlink_by_longname(struct rb_root *root,
937 return NULL; 937 return NULL;
938} 938}
939 939
940static inline struct dso * 940static inline struct dso *__dso__find_by_longname(struct rb_root *root,
941dso__find_by_longname(const struct rb_root *root, const char *name) 941 const char *name)
942{ 942{
943 return dso__findlink_by_longname((struct rb_root *)root, NULL, name); 943 return __dso__findlink_by_longname(root, NULL, name);
944} 944}
945 945
946void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated) 946void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
@@ -1149,14 +1149,20 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1149 return have_build_id; 1149 return have_build_id;
1150} 1150}
1151 1151
1152void dsos__add(struct dsos *dsos, struct dso *dso) 1152void __dsos__add(struct dsos *dsos, struct dso *dso)
1153{ 1153{
1154 list_add_tail(&dso->node, &dsos->head); 1154 list_add_tail(&dso->node, &dsos->head);
1155 dso__findlink_by_longname(&dsos->root, dso, NULL); 1155 __dso__findlink_by_longname(&dsos->root, dso, NULL);
1156}
1157
1158void dsos__add(struct dsos *dsos, struct dso *dso)
1159{
1160 pthread_rwlock_wrlock(&dsos->lock);
1161 __dsos__add(dsos, dso);
1162 pthread_rwlock_unlock(&dsos->lock);
1156} 1163}
1157 1164
1158struct dso *dsos__find(const struct dsos *dsos, const char *name, 1165struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1159 bool cmp_short)
1160{ 1166{
1161 struct dso *pos; 1167 struct dso *pos;
1162 1168
@@ -1166,15 +1172,24 @@ struct dso *dsos__find(const struct dsos *dsos, const char *name,
1166 return pos; 1172 return pos;
1167 return NULL; 1173 return NULL;
1168 } 1174 }
1169 return dso__find_by_longname(&dsos->root, name); 1175 return __dso__find_by_longname(&dsos->root, name);
1170} 1176}
1171 1177
1172struct dso *dsos__addnew(struct dsos *dsos, const char *name) 1178struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1179{
1180 struct dso *dso;
1181 pthread_rwlock_rdlock(&dsos->lock);
1182 dso = __dsos__find(dsos, name, cmp_short);
1183 pthread_rwlock_unlock(&dsos->lock);
1184 return dso;
1185}
1186
1187struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
1173{ 1188{
1174 struct dso *dso = dso__new(name); 1189 struct dso *dso = dso__new(name);
1175 1190
1176 if (dso != NULL) { 1191 if (dso != NULL) {
1177 dsos__add(dsos, dso); 1192 __dsos__add(dsos, dso);
1178 dso__set_basename(dso); 1193 dso__set_basename(dso);
1179 } 1194 }
1180 return dso; 1195 return dso;
@@ -1182,9 +1197,18 @@ struct dso *dsos__addnew(struct dsos *dsos, const char *name)
1182 1197
1183struct dso *__dsos__findnew(struct dsos *dsos, const char *name) 1198struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1184{ 1199{
1185 struct dso *dso = dsos__find(dsos, name, false); 1200 struct dso *dso = __dsos__find(dsos, name, false);
1201
1202 return dso ? dso : __dsos__addnew(dsos, name);
1203}
1186 1204
1187 return dso ? dso : dsos__addnew(dsos, name); 1205struct dso *dsos__findnew(struct dsos *dsos, const char *name)
1206{
1207 struct dso *dso;
1208 pthread_rwlock_wrlock(&dsos->lock);
1209 dso = __dsos__findnew(dsos, name);
1210 pthread_rwlock_unlock(&dsos->lock);
1211 return dso;
1188} 1212}
1189 1213
1190size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 1214size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index ba2d90ed881f..c16ab5d849c3 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -4,6 +4,7 @@
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include <pthread.h>
7#include <linux/types.h> 8#include <linux/types.h>
8#include <linux/bitops.h> 9#include <linux/bitops.h>
9#include "map.h" 10#include "map.h"
@@ -124,6 +125,7 @@ struct dso_cache {
124struct dsos { 125struct dsos {
125 struct list_head head; 126 struct list_head head;
126 struct rb_root root; /* rbtree root sorted by long name */ 127 struct rb_root root; /* rbtree root sorted by long name */
128 pthread_rwlock_t lock;
127}; 129};
128 130
129struct auxtrace_cache; 131struct auxtrace_cache;
@@ -297,11 +299,13 @@ struct map *dso__new_map(const char *name);
297struct dso *machine__findnew_kernel(struct machine *machine, const char *name, 299struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
298 const char *short_name, int dso_type); 300 const char *short_name, int dso_type);
299 301
302void __dsos__add(struct dsos *dsos, struct dso *dso);
300void dsos__add(struct dsos *dsos, struct dso *dso); 303void dsos__add(struct dsos *dsos, struct dso *dso);
301struct dso *dsos__addnew(struct dsos *dsos, const char *name); 304struct dso *__dsos__addnew(struct dsos *dsos, const char *name);
302struct dso *dsos__find(const struct dsos *dsos, const char *name, 305struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
303 bool cmp_short); 306struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short);
304struct dso *__dsos__findnew(struct dsos *dsos, const char *name); 307struct dso *__dsos__findnew(struct dsos *dsos, const char *name);
308struct dso *dsos__findnew(struct dsos *dsos, const char *name);
305bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 309bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
306 310
307size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, 311size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index dfd419797e6e..0cf56d6f073a 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -20,6 +20,7 @@ static void dsos__init(struct dsos *dsos)
20{ 20{
21 INIT_LIST_HEAD(&dsos->head); 21 INIT_LIST_HEAD(&dsos->head);
22 dsos->root = RB_ROOT; 22 dsos->root = RB_ROOT;
23 pthread_rwlock_init(&dsos->lock, NULL);
23} 24}
24 25
25int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 26int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
@@ -81,15 +82,21 @@ out_delete:
81 return NULL; 82 return NULL;
82} 83}
83 84
84static void dsos__delete(struct dsos *dsos) 85static void dsos__exit(struct dsos *dsos)
85{ 86{
86 struct dso *pos, *n; 87 struct dso *pos, *n;
87 88
89 pthread_rwlock_wrlock(&dsos->lock);
90
88 list_for_each_entry_safe(pos, n, &dsos->head, node) { 91 list_for_each_entry_safe(pos, n, &dsos->head, node) {
89 RB_CLEAR_NODE(&pos->rb_node); 92 RB_CLEAR_NODE(&pos->rb_node);
90 list_del(&pos->node); 93 list_del(&pos->node);
91 dso__delete(pos); 94 dso__delete(pos);
92 } 95 }
96
97 pthread_rwlock_unlock(&dsos->lock);
98
99 pthread_rwlock_destroy(&dsos->lock);
93} 100}
94 101
95void machine__delete_threads(struct machine *machine) 102void machine__delete_threads(struct machine *machine)
@@ -110,7 +117,7 @@ void machine__delete_threads(struct machine *machine)
110void machine__exit(struct machine *machine) 117void machine__exit(struct machine *machine)
111{ 118{
112 map_groups__exit(&machine->kmaps); 119 map_groups__exit(&machine->kmaps);
113 dsos__delete(&machine->dsos); 120 dsos__exit(&machine->dsos);
114 machine__exit_vdso(machine); 121 machine__exit_vdso(machine);
115 zfree(&machine->root_dir); 122 zfree(&machine->root_dir);
116 zfree(&machine->current_tid); 123 zfree(&machine->current_tid);
@@ -496,11 +503,13 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
496{ 503{
497 struct dso *dso; 504 struct dso *dso;
498 505
499 dso = dsos__find(&machine->dsos, m->name, true); 506 pthread_rwlock_wrlock(&machine->dsos.lock);
507
508 dso = __dsos__find(&machine->dsos, m->name, true);
500 if (!dso) { 509 if (!dso) {
501 dso = dsos__addnew(&machine->dsos, m->name); 510 dso = __dsos__addnew(&machine->dsos, m->name);
502 if (dso == NULL) 511 if (dso == NULL)
503 return NULL; 512 goto out_unlock;
504 513
505 if (machine__is_host(machine)) 514 if (machine__is_host(machine))
506 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; 515 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
@@ -515,6 +524,8 @@ static struct dso *machine__findnew_module_dso(struct machine *machine,
515 dso__set_long_name(dso, strdup(filename), true); 524 dso__set_long_name(dso, strdup(filename), true);
516 } 525 }
517 526
527out_unlock:
528 pthread_rwlock_unlock(&machine->dsos.lock);
518 return dso; 529 return dso;
519} 530}
520 531
@@ -1156,6 +1167,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1156 struct dso *kernel = NULL; 1167 struct dso *kernel = NULL;
1157 struct dso *dso; 1168 struct dso *dso;
1158 1169
1170 pthread_rwlock_rdlock(&machine->dsos.lock);
1171
1159 list_for_each_entry(dso, &machine->dsos.head, node) { 1172 list_for_each_entry(dso, &machine->dsos.head, node) {
1160 1173
1161 /* 1174 /*
@@ -1184,6 +1197,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1184 break; 1197 break;
1185 } 1198 }
1186 1199
1200 pthread_rwlock_unlock(&machine->dsos.lock);
1201
1187 if (kernel == NULL) 1202 if (kernel == NULL)
1188 kernel = machine__findnew_dso(machine, kmmap_prefix); 1203 kernel = machine__findnew_dso(machine, kmmap_prefix);
1189 if (kernel == NULL) 1204 if (kernel == NULL)
@@ -1948,5 +1963,5 @@ int machine__get_kernel_start(struct machine *machine)
1948 1963
1949struct dso *machine__findnew_dso(struct machine *machine, const char *filename) 1964struct dso *machine__findnew_dso(struct machine *machine, const char *filename)
1950{ 1965{
1951 return __dsos__findnew(&machine->dsos, filename); 1966 return dsos__findnew(&machine->dsos, filename);
1952} 1967}
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 2e8f6886ca72..c646c74c34f8 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -120,14 +120,14 @@ void machine__exit_vdso(struct machine *machine)
120 zfree(&machine->vdso_info); 120 zfree(&machine->vdso_info);
121} 121}
122 122
123static struct dso *machine__addnew_vdso(struct machine *machine, const char *short_name, 123static struct dso *__machine__addnew_vdso(struct machine *machine, const char *short_name,
124 const char *long_name) 124 const char *long_name)
125{ 125{
126 struct dso *dso; 126 struct dso *dso;
127 127
128 dso = dso__new(short_name); 128 dso = dso__new(short_name);
129 if (dso != NULL) { 129 if (dso != NULL) {
130 dsos__add(&machine->dsos, dso); 130 __dsos__add(&machine->dsos, dso);
131 dso__set_long_name(dso, long_name, false); 131 dso__set_long_name(dso, long_name, false);
132 } 132 }
133 133
@@ -230,27 +230,31 @@ static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
230 return vdso_file->temp_file_name; 230 return vdso_file->temp_file_name;
231} 231}
232 232
233static struct dso *vdso__findnew_compat(struct machine *machine, 233static struct dso *__machine__findnew_compat(struct machine *machine,
234 struct vdso_file *vdso_file) 234 struct vdso_file *vdso_file)
235{ 235{
236 const char *file_name; 236 const char *file_name;
237 struct dso *dso; 237 struct dso *dso;
238 238
239 dso = dsos__find(&machine->dsos, vdso_file->dso_name, true); 239 pthread_rwlock_wrlock(&machine->dsos.lock);
240 dso = __dsos__find(&machine->dsos, vdso_file->dso_name, true);
240 if (dso) 241 if (dso)
241 return dso; 242 goto out_unlock;
242 243
243 file_name = vdso__get_compat_file(vdso_file); 244 file_name = vdso__get_compat_file(vdso_file);
244 if (!file_name) 245 if (!file_name)
245 return NULL; 246 goto out_unlock;
246 247
247 return machine__addnew_vdso(machine, vdso_file->dso_name, file_name); 248 dso = __machine__addnew_vdso(machine, vdso_file->dso_name, file_name);
249out_unlock:
250 pthread_rwlock_unlock(&machine->dsos.lock);
251 return dso;
248} 252}
249 253
250static int machine__findnew_vdso_compat(struct machine *machine, 254static int __machine__findnew_vdso_compat(struct machine *machine,
251 struct thread *thread, 255 struct thread *thread,
252 struct vdso_info *vdso_info, 256 struct vdso_info *vdso_info,
253 struct dso **dso) 257 struct dso **dso)
254{ 258{
255 enum dso_type dso_type; 259 enum dso_type dso_type;
256 260
@@ -267,10 +271,10 @@ static int machine__findnew_vdso_compat(struct machine *machine,
267 271
268 switch (dso_type) { 272 switch (dso_type) {
269 case DSO__TYPE_32BIT: 273 case DSO__TYPE_32BIT:
270 *dso = vdso__findnew_compat(machine, &vdso_info->vdso32); 274 *dso = __machine__findnew_compat(machine, &vdso_info->vdso32);
271 return 1; 275 return 1;
272 case DSO__TYPE_X32BIT: 276 case DSO__TYPE_X32BIT:
273 *dso = vdso__findnew_compat(machine, &vdso_info->vdsox32); 277 *dso = __machine__findnew_compat(machine, &vdso_info->vdsox32);
274 return 1; 278 return 1;
275 case DSO__TYPE_UNKNOWN: 279 case DSO__TYPE_UNKNOWN:
276 case DSO__TYPE_64BIT: 280 case DSO__TYPE_64BIT:
@@ -285,31 +289,32 @@ struct dso *machine__findnew_vdso(struct machine *machine,
285 struct thread *thread __maybe_unused) 289 struct thread *thread __maybe_unused)
286{ 290{
287 struct vdso_info *vdso_info; 291 struct vdso_info *vdso_info;
288 struct dso *dso; 292 struct dso *dso = NULL;
289 293
294 pthread_rwlock_wrlock(&machine->dsos.lock);
290 if (!machine->vdso_info) 295 if (!machine->vdso_info)
291 machine->vdso_info = vdso_info__new(); 296 machine->vdso_info = vdso_info__new();
292 297
293 vdso_info = machine->vdso_info; 298 vdso_info = machine->vdso_info;
294 if (!vdso_info) 299 if (!vdso_info)
295 return NULL; 300 goto out_unlock;
296 301
297#if BITS_PER_LONG == 64 302#if BITS_PER_LONG == 64
298 if (machine__findnew_vdso_compat(machine, thread, vdso_info, &dso)) 303 if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
299 return dso; 304 goto out_unlock;
300#endif 305#endif
301 306
302 dso = dsos__find(&machine->dsos, DSO__NAME_VDSO, true); 307 dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
303 if (!dso) { 308 if (!dso) {
304 char *file; 309 char *file;
305 310
306 file = get_file(&vdso_info->vdso); 311 file = get_file(&vdso_info->vdso);
307 if (!file) 312 if (file)
308 return NULL; 313 dso = __machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
309
310 dso = machine__addnew_vdso(machine, DSO__NAME_VDSO, file);
311 } 314 }
312 315
316out_unlock:
317 pthread_rwlock_unlock(&machine->dsos.lock);
313 return dso; 318 return dso;
314} 319}
315 320