diff options
author | Jiri Olsa <jolsa@kernel.org> | 2015-06-22 18:36:05 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-06-25 14:15:50 -0400 |
commit | 186fbb7432f4a740b4fbaf4145375442210110bb (patch) | |
tree | dbe98386a183e60d849c11f12c1396abd4baa05e | |
parent | f30a79b012e5d9b3887f6a59293d9ef3ca0e2c3e (diff) |
perf tools: Add reference counting for thread_map object
Adding reference counting for thread_map object, so it could be easily
shared among other objects.
Using thread_map__put instead thread_map__delete and making
thread_map__delete static.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1435012588-9007-5-git-send-email-jolsa@kernel.org
[ Adjustments to move it ahead of the "comm" patches ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/tests/code-reading.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/keep-tracking.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/mmap-basic.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/mmap-thread-lookup.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/openat-syscall-all-cpus.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/openat-syscall.c | 2 | ||||
-rw-r--r-- | tools/perf/tests/switch-tracking.c | 2 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 4 | ||||
-rw-r--r-- | tools/perf/util/python.c | 2 | ||||
-rw-r--r-- | tools/perf/util/thread_map.c | 30 | ||||
-rw-r--r-- | tools/perf/util/thread_map.h | 7 |
11 files changed, 43 insertions, 14 deletions
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 6b3250f54240..39c784a100a9 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -546,7 +546,7 @@ out_err: | |||
546 | perf_evlist__delete(evlist); | 546 | perf_evlist__delete(evlist); |
547 | } else { | 547 | } else { |
548 | cpu_map__put(cpus); | 548 | cpu_map__put(cpus); |
549 | thread_map__delete(threads); | 549 | thread_map__put(threads); |
550 | } | 550 | } |
551 | machines__destroy_kernel_maps(&machines); | 551 | machines__destroy_kernel_maps(&machines); |
552 | machine__delete_threads(machine); | 552 | machine__delete_threads(machine); |
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c index a330235cefc0..4d4b9837b630 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c | |||
@@ -145,7 +145,7 @@ out_err: | |||
145 | perf_evlist__delete(evlist); | 145 | perf_evlist__delete(evlist); |
146 | } else { | 146 | } else { |
147 | cpu_map__put(cpus); | 147 | cpu_map__put(cpus); |
148 | thread_map__delete(threads); | 148 | thread_map__put(threads); |
149 | } | 149 | } |
150 | 150 | ||
151 | return err; | 151 | return err; |
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c index 5a9ef5833452..666b67a4df9d 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c | |||
@@ -142,6 +142,6 @@ out_delete_evlist: | |||
142 | out_free_cpus: | 142 | out_free_cpus: |
143 | cpu_map__put(cpus); | 143 | cpu_map__put(cpus); |
144 | out_free_threads: | 144 | out_free_threads: |
145 | thread_map__delete(threads); | 145 | thread_map__put(threads); |
146 | return err; | 146 | return err; |
147 | } | 147 | } |
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c index 7f48efa7e295..145050e2e544 100644 --- a/tools/perf/tests/mmap-thread-lookup.c +++ b/tools/perf/tests/mmap-thread-lookup.c | |||
@@ -143,7 +143,7 @@ static int synth_process(struct machine *machine) | |||
143 | perf_event__process, | 143 | perf_event__process, |
144 | machine, 0, 500); | 144 | machine, 0, 500); |
145 | 145 | ||
146 | thread_map__delete(map); | 146 | thread_map__put(map); |
147 | return err; | 147 | return err; |
148 | } | 148 | } |
149 | 149 | ||
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c index 9a7a116e09b8..b8d552b13950 100644 --- a/tools/perf/tests/openat-syscall-all-cpus.c +++ b/tools/perf/tests/openat-syscall-all-cpus.c | |||
@@ -111,6 +111,6 @@ out_close_fd: | |||
111 | out_evsel_delete: | 111 | out_evsel_delete: |
112 | perf_evsel__delete(evsel); | 112 | perf_evsel__delete(evsel); |
113 | out_thread_map_delete: | 113 | out_thread_map_delete: |
114 | thread_map__delete(threads); | 114 | thread_map__put(threads); |
115 | return err; | 115 | return err; |
116 | } | 116 | } |
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c index 9f9491bb8e48..bdfa1f446681 100644 --- a/tools/perf/tests/openat-syscall.c +++ b/tools/perf/tests/openat-syscall.c | |||
@@ -56,6 +56,6 @@ out_close_fd: | |||
56 | out_evsel_delete: | 56 | out_evsel_delete: |
57 | perf_evsel__delete(evsel); | 57 | perf_evsel__delete(evsel); |
58 | out_thread_map_delete: | 58 | out_thread_map_delete: |
59 | thread_map__delete(threads); | 59 | thread_map__put(threads); |
60 | return err; | 60 | return err; |
61 | } | 61 | } |
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c index 1b06122beb76..e698742d4fec 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c | |||
@@ -561,7 +561,7 @@ out: | |||
561 | perf_evlist__delete(evlist); | 561 | perf_evlist__delete(evlist); |
562 | } else { | 562 | } else { |
563 | cpu_map__put(cpus); | 563 | cpu_map__put(cpus); |
564 | thread_map__delete(threads); | 564 | thread_map__put(threads); |
565 | } | 565 | } |
566 | 566 | ||
567 | return err; | 567 | return err; |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 59498f7b3e9b..a8d18a3d2164 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist) | |||
115 | perf_evlist__munmap(evlist); | 115 | perf_evlist__munmap(evlist); |
116 | perf_evlist__close(evlist); | 116 | perf_evlist__close(evlist); |
117 | cpu_map__put(evlist->cpus); | 117 | cpu_map__put(evlist->cpus); |
118 | thread_map__delete(evlist->threads); | 118 | thread_map__put(evlist->threads); |
119 | evlist->cpus = NULL; | 119 | evlist->cpus = NULL; |
120 | evlist->threads = NULL; | 120 | evlist->threads = NULL; |
121 | perf_evlist__purge(evlist); | 121 | perf_evlist__purge(evlist); |
@@ -1120,7 +1120,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | |||
1120 | return 0; | 1120 | return 0; |
1121 | 1121 | ||
1122 | out_delete_threads: | 1122 | out_delete_threads: |
1123 | thread_map__delete(evlist->threads); | 1123 | thread_map__put(evlist->threads); |
1124 | evlist->threads = NULL; | 1124 | evlist->threads = NULL; |
1125 | return -1; | 1125 | return -1; |
1126 | } | 1126 | } |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index b106d56df240..626422eda727 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -453,7 +453,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, | |||
453 | 453 | ||
454 | static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) | 454 | static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) |
455 | { | 455 | { |
456 | thread_map__delete(pthreads->threads); | 456 | thread_map__put(pthreads->threads); |
457 | pthreads->ob_type->tp_free((PyObject*)pthreads); | 457 | pthreads->ob_type->tp_free((PyObject*)pthreads); |
458 | } | 458 | } |
459 | 459 | ||
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 920136dd8c2e..368cc58c6892 100644 --- a/tools/perf/util/thread_map.c +++ b/tools/perf/util/thread_map.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <unistd.h> | 8 | #include <unistd.h> |
9 | #include "strlist.h" | 9 | #include "strlist.h" |
10 | #include <string.h> | 10 | #include <string.h> |
11 | #include "asm/bug.h" | ||
11 | #include "thread_map.h" | 12 | #include "thread_map.h" |
12 | #include "util.h" | 13 | #include "util.h" |
13 | 14 | ||
@@ -47,6 +48,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) | |||
47 | for (i = 0; i < items; i++) | 48 | for (i = 0; i < items; i++) |
48 | thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); | 49 | thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); |
49 | threads->nr = items; | 50 | threads->nr = items; |
51 | atomic_set(&threads->refcnt, 1); | ||
50 | } | 52 | } |
51 | 53 | ||
52 | for (i=0; i<items; i++) | 54 | for (i=0; i<items; i++) |
@@ -63,6 +65,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid) | |||
63 | if (threads != NULL) { | 65 | if (threads != NULL) { |
64 | thread_map__set_pid(threads, 0, tid); | 66 | thread_map__set_pid(threads, 0, tid); |
65 | threads->nr = 1; | 67 | threads->nr = 1; |
68 | atomic_set(&threads->refcnt, 1); | ||
66 | } | 69 | } |
67 | 70 | ||
68 | return threads; | 71 | return threads; |
@@ -84,6 +87,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) | |||
84 | goto out_free_threads; | 87 | goto out_free_threads; |
85 | 88 | ||
86 | threads->nr = 0; | 89 | threads->nr = 0; |
90 | atomic_set(&threads->refcnt, 1); | ||
87 | 91 | ||
88 | while (!readdir_r(proc, &dirent, &next) && next) { | 92 | while (!readdir_r(proc, &dirent, &next) && next) { |
89 | char *end; | 93 | char *end; |
@@ -212,6 +216,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) | |||
212 | 216 | ||
213 | out: | 217 | out: |
214 | strlist__delete(slist); | 218 | strlist__delete(slist); |
219 | if (threads) | ||
220 | atomic_set(&threads->refcnt, 1); | ||
215 | return threads; | 221 | return threads; |
216 | 222 | ||
217 | out_free_namelist: | 223 | out_free_namelist: |
@@ -231,6 +237,7 @@ struct thread_map *thread_map__new_dummy(void) | |||
231 | if (threads != NULL) { | 237 | if (threads != NULL) { |
232 | thread_map__set_pid(threads, 0, -1); | 238 | thread_map__set_pid(threads, 0, -1); |
233 | threads->nr = 1; | 239 | threads->nr = 1; |
240 | atomic_set(&threads->refcnt, 1); | ||
234 | } | 241 | } |
235 | return threads; | 242 | return threads; |
236 | } | 243 | } |
@@ -273,6 +280,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) | |||
273 | threads->nr = ntasks; | 280 | threads->nr = ntasks; |
274 | } | 281 | } |
275 | out: | 282 | out: |
283 | if (threads) | ||
284 | atomic_set(&threads->refcnt, 1); | ||
276 | return threads; | 285 | return threads; |
277 | 286 | ||
278 | out_free_threads: | 287 | out_free_threads: |
@@ -292,9 +301,26 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid, | |||
292 | return thread_map__new_by_tid_str(tid); | 301 | return thread_map__new_by_tid_str(tid); |
293 | } | 302 | } |
294 | 303 | ||
295 | void thread_map__delete(struct thread_map *threads) | 304 | static void thread_map__delete(struct thread_map *threads) |
296 | { | 305 | { |
297 | free(threads); | 306 | if (threads) { |
307 | WARN_ONCE(atomic_read(&threads->refcnt) != 0, | ||
308 | "thread map refcnt unbalanced\n"); | ||
309 | free(threads); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | struct thread_map *thread_map__get(struct thread_map *map) | ||
314 | { | ||
315 | if (map) | ||
316 | atomic_inc(&map->refcnt); | ||
317 | return map; | ||
318 | } | ||
319 | |||
320 | void thread_map__put(struct thread_map *map) | ||
321 | { | ||
322 | if (map && atomic_dec_and_test(&map->refcnt)) | ||
323 | thread_map__delete(map); | ||
298 | } | 324 | } |
299 | 325 | ||
300 | size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) | 326 | size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) |
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h index b9f40679f589..6b0cd2dc006b 100644 --- a/tools/perf/util/thread_map.h +++ b/tools/perf/util/thread_map.h | |||
@@ -3,12 +3,14 @@ | |||
3 | 3 | ||
4 | #include <sys/types.h> | 4 | #include <sys/types.h> |
5 | #include <stdio.h> | 5 | #include <stdio.h> |
6 | #include <linux/atomic.h> | ||
6 | 7 | ||
7 | struct thread_map_data { | 8 | struct thread_map_data { |
8 | pid_t pid; | 9 | pid_t pid; |
9 | }; | 10 | }; |
10 | 11 | ||
11 | struct thread_map { | 12 | struct thread_map { |
13 | atomic_t refcnt; | ||
12 | int nr; | 14 | int nr; |
13 | struct thread_map_data map[]; | 15 | struct thread_map_data map[]; |
14 | }; | 16 | }; |
@@ -19,11 +21,12 @@ struct thread_map *thread_map__new_by_tid(pid_t tid); | |||
19 | struct thread_map *thread_map__new_by_uid(uid_t uid); | 21 | struct thread_map *thread_map__new_by_uid(uid_t uid); |
20 | struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); | 22 | struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); |
21 | 23 | ||
24 | struct thread_map *thread_map__get(struct thread_map *map); | ||
25 | void thread_map__put(struct thread_map *map); | ||
26 | |||
22 | struct thread_map *thread_map__new_str(const char *pid, | 27 | struct thread_map *thread_map__new_str(const char *pid, |
23 | const char *tid, uid_t uid); | 28 | const char *tid, uid_t uid); |
24 | 29 | ||
25 | void thread_map__delete(struct thread_map *threads); | ||
26 | |||
27 | size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); | 30 | size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); |
28 | 31 | ||
29 | static inline int thread_map__nr(struct thread_map *threads) | 32 | static inline int thread_map__nr(struct thread_map *threads) |