diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-06-26 04:38:11 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-06-26 04:38:11 -0400 |
commit | 6eedf416429a32e0216f61b8b690d25577b2b91e (patch) | |
tree | cdd0474142283a269c2e05e31128d382418fab28 /tools | |
parent | df0d0da426d03fb7e6567feb38a48b1e0dd1891e (diff) | |
parent | a22e99cd74a31dee4b5241bd60a256c629c808da (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and refactorings from Arnaldo Carvalho de Melo:
Infrastructure changes:
- Reference count the cpu_map and thread_map classes. (Jiri Olsa)
- Set evsel->{cpus,threads} from the evlist, if not set,
allowing the generalization of some 'perf stat' functions that
previously were accessing private static evlist variable. (Jiri Olsa)
- Delete an unnecessary check before the calling
free_event_desc() (Markus Elfring)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-stat.c | 10 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/keep-tracking.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/mmap-basic.c | 4 | ||||
-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 | 4 | ||||
-rw-r--r-- | tools/perf/util/cpumap.c | 26 | ||||
-rw-r--r-- | tools/perf/util/cpumap.h | 6 | ||||
-rw-r--r-- | tools/perf/util/evlist.c | 35 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 2 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 12 | ||||
-rw-r--r-- | tools/perf/util/header.c | 3 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 5 | ||||
-rw-r--r-- | tools/perf/util/python.c | 4 | ||||
-rw-r--r-- | tools/perf/util/record.c | 4 | ||||
-rw-r--r-- | tools/perf/util/session.c | 2 | ||||
-rw-r--r-- | tools/perf/util/svghelper.c | 2 | ||||
-rw-r--r-- | tools/perf/util/thread_map.c | 32 | ||||
-rw-r--r-- | tools/perf/util/thread_map.h | 7 |
21 files changed, 129 insertions, 43 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index fcf99bdeb19e..3e1636cae76b 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -141,16 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a, | |||
141 | } | 141 | } |
142 | } | 142 | } |
143 | 143 | ||
144 | static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) | ||
145 | { | ||
146 | return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus; | ||
147 | } | ||
148 | |||
149 | static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) | ||
150 | { | ||
151 | return perf_evsel__cpus(evsel)->nr; | ||
152 | } | ||
153 | |||
154 | static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) | 144 | static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) |
155 | { | 145 | { |
156 | int i; | 146 | int i; |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 22f8a00446e1..39c784a100a9 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -545,8 +545,8 @@ out_err: | |||
545 | if (evlist) { | 545 | if (evlist) { |
546 | perf_evlist__delete(evlist); | 546 | perf_evlist__delete(evlist); |
547 | } else { | 547 | } else { |
548 | cpu_map__delete(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 5b171d1e338b..4d4b9837b630 100644 --- a/tools/perf/tests/keep-tracking.c +++ b/tools/perf/tests/keep-tracking.c | |||
@@ -144,8 +144,8 @@ out_err: | |||
144 | perf_evlist__disable(evlist); | 144 | perf_evlist__disable(evlist); |
145 | perf_evlist__delete(evlist); | 145 | perf_evlist__delete(evlist); |
146 | } else { | 146 | } else { |
147 | cpu_map__delete(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 5855cf471210..666b67a4df9d 100644 --- a/tools/perf/tests/mmap-basic.c +++ b/tools/perf/tests/mmap-basic.c | |||
@@ -140,8 +140,8 @@ out_delete_evlist: | |||
140 | cpus = NULL; | 140 | cpus = NULL; |
141 | threads = NULL; | 141 | threads = NULL; |
142 | out_free_cpus: | 142 | out_free_cpus: |
143 | cpu_map__delete(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 0d31403ea593..e698742d4fec 100644 --- a/tools/perf/tests/switch-tracking.c +++ b/tools/perf/tests/switch-tracking.c | |||
@@ -560,8 +560,8 @@ out: | |||
560 | perf_evlist__disable(evlist); | 560 | perf_evlist__disable(evlist); |
561 | perf_evlist__delete(evlist); | 561 | perf_evlist__delete(evlist); |
562 | } else { | 562 | } else { |
563 | cpu_map__delete(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/cpumap.c b/tools/perf/util/cpumap.c index c4e55b71010c..3667e2123e5b 100644 --- a/tools/perf/util/cpumap.c +++ b/tools/perf/util/cpumap.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <assert.h> | 5 | #include <assert.h> |
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include "asm/bug.h" | ||
8 | 9 | ||
9 | static struct cpu_map *cpu_map__default_new(void) | 10 | static struct cpu_map *cpu_map__default_new(void) |
10 | { | 11 | { |
@@ -22,6 +23,7 @@ static struct cpu_map *cpu_map__default_new(void) | |||
22 | cpus->map[i] = i; | 23 | cpus->map[i] = i; |
23 | 24 | ||
24 | cpus->nr = nr_cpus; | 25 | cpus->nr = nr_cpus; |
26 | atomic_set(&cpus->refcnt, 1); | ||
25 | } | 27 | } |
26 | 28 | ||
27 | return cpus; | 29 | return cpus; |
@@ -35,6 +37,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus) | |||
35 | if (cpus != NULL) { | 37 | if (cpus != NULL) { |
36 | cpus->nr = nr_cpus; | 38 | cpus->nr = nr_cpus; |
37 | memcpy(cpus->map, tmp_cpus, payload_size); | 39 | memcpy(cpus->map, tmp_cpus, payload_size); |
40 | atomic_set(&cpus->refcnt, 1); | ||
38 | } | 41 | } |
39 | 42 | ||
40 | return cpus; | 43 | return cpus; |
@@ -194,14 +197,32 @@ struct cpu_map *cpu_map__dummy_new(void) | |||
194 | if (cpus != NULL) { | 197 | if (cpus != NULL) { |
195 | cpus->nr = 1; | 198 | cpus->nr = 1; |
196 | cpus->map[0] = -1; | 199 | cpus->map[0] = -1; |
200 | atomic_set(&cpus->refcnt, 1); | ||
197 | } | 201 | } |
198 | 202 | ||
199 | return cpus; | 203 | return cpus; |
200 | } | 204 | } |
201 | 205 | ||
202 | void cpu_map__delete(struct cpu_map *map) | 206 | static void cpu_map__delete(struct cpu_map *map) |
203 | { | 207 | { |
204 | free(map); | 208 | if (map) { |
209 | WARN_ONCE(atomic_read(&map->refcnt) != 0, | ||
210 | "cpu_map refcnt unbalanced\n"); | ||
211 | free(map); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | struct cpu_map *cpu_map__get(struct cpu_map *map) | ||
216 | { | ||
217 | if (map) | ||
218 | atomic_inc(&map->refcnt); | ||
219 | return map; | ||
220 | } | ||
221 | |||
222 | void cpu_map__put(struct cpu_map *map) | ||
223 | { | ||
224 | if (map && atomic_dec_and_test(&map->refcnt)) | ||
225 | cpu_map__delete(map); | ||
205 | } | 226 | } |
206 | 227 | ||
207 | int cpu_map__get_socket(struct cpu_map *map, int idx) | 228 | int cpu_map__get_socket(struct cpu_map *map, int idx) |
@@ -263,6 +284,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, | |||
263 | /* ensure we process id in increasing order */ | 284 | /* ensure we process id in increasing order */ |
264 | qsort(c->map, c->nr, sizeof(int), cmp_ids); | 285 | qsort(c->map, c->nr, sizeof(int), cmp_ids); |
265 | 286 | ||
287 | atomic_set(&cpus->refcnt, 1); | ||
266 | *res = c; | 288 | *res = c; |
267 | return 0; | 289 | return 0; |
268 | } | 290 | } |
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h index 61a654849002..0af9cecb4c51 100644 --- a/tools/perf/util/cpumap.h +++ b/tools/perf/util/cpumap.h | |||
@@ -3,18 +3,19 @@ | |||
3 | 3 | ||
4 | #include <stdio.h> | 4 | #include <stdio.h> |
5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
6 | #include <linux/atomic.h> | ||
6 | 7 | ||
7 | #include "perf.h" | 8 | #include "perf.h" |
8 | #include "util/debug.h" | 9 | #include "util/debug.h" |
9 | 10 | ||
10 | struct cpu_map { | 11 | struct cpu_map { |
12 | atomic_t refcnt; | ||
11 | int nr; | 13 | int nr; |
12 | int map[]; | 14 | int map[]; |
13 | }; | 15 | }; |
14 | 16 | ||
15 | struct cpu_map *cpu_map__new(const char *cpu_list); | 17 | struct cpu_map *cpu_map__new(const char *cpu_list); |
16 | struct cpu_map *cpu_map__dummy_new(void); | 18 | struct cpu_map *cpu_map__dummy_new(void); |
17 | void cpu_map__delete(struct cpu_map *map); | ||
18 | struct cpu_map *cpu_map__read(FILE *file); | 19 | struct cpu_map *cpu_map__read(FILE *file); |
19 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); | 20 | size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); |
20 | int cpu_map__get_socket(struct cpu_map *map, int idx); | 21 | int cpu_map__get_socket(struct cpu_map *map, int idx); |
@@ -22,6 +23,9 @@ int cpu_map__get_core(struct cpu_map *map, int idx); | |||
22 | int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); | 23 | int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp); |
23 | int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); | 24 | int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep); |
24 | 25 | ||
26 | struct cpu_map *cpu_map__get(struct cpu_map *map); | ||
27 | void cpu_map__put(struct cpu_map *map); | ||
28 | |||
25 | static inline int cpu_map__socket(struct cpu_map *sock, int s) | 29 | static inline int cpu_map__socket(struct cpu_map *sock, int s) |
26 | { | 30 | { |
27 | if (!sock || s > sock->nr || s < 0) | 31 | if (!sock || s > sock->nr || s < 0) |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d29df901be3e..6cfdee68e763 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -114,8 +114,8 @@ void perf_evlist__delete(struct perf_evlist *evlist) | |||
114 | { | 114 | { |
115 | perf_evlist__munmap(evlist); | 115 | perf_evlist__munmap(evlist); |
116 | perf_evlist__close(evlist); | 116 | perf_evlist__close(evlist); |
117 | cpu_map__delete(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); |
@@ -1101,6 +1101,31 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages, | |||
1101 | return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false); | 1101 | return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false); |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | static int perf_evlist__propagate_maps(struct perf_evlist *evlist, | ||
1105 | struct target *target) | ||
1106 | { | ||
1107 | struct perf_evsel *evsel; | ||
1108 | |||
1109 | evlist__for_each(evlist, evsel) { | ||
1110 | /* | ||
1111 | * We already have cpus for evsel (via PMU sysfs) so | ||
1112 | * keep it, if there's no target cpu list defined. | ||
1113 | */ | ||
1114 | if (evsel->cpus && target->cpu_list) | ||
1115 | cpu_map__put(evsel->cpus); | ||
1116 | |||
1117 | if (!evsel->cpus || target->cpu_list) | ||
1118 | evsel->cpus = cpu_map__get(evlist->cpus); | ||
1119 | |||
1120 | evsel->threads = thread_map__get(evlist->threads); | ||
1121 | |||
1122 | if (!evsel->cpus || !evsel->threads) | ||
1123 | return -ENOMEM; | ||
1124 | } | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1104 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | 1129 | int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) |
1105 | { | 1130 | { |
1106 | evlist->threads = thread_map__new_str(target->pid, target->tid, | 1131 | evlist->threads = thread_map__new_str(target->pid, target->tid, |
@@ -1117,10 +1142,10 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) | |||
1117 | if (evlist->cpus == NULL) | 1142 | if (evlist->cpus == NULL) |
1118 | goto out_delete_threads; | 1143 | goto out_delete_threads; |
1119 | 1144 | ||
1120 | return 0; | 1145 | return perf_evlist__propagate_maps(evlist, target); |
1121 | 1146 | ||
1122 | out_delete_threads: | 1147 | out_delete_threads: |
1123 | thread_map__delete(evlist->threads); | 1148 | thread_map__put(evlist->threads); |
1124 | evlist->threads = NULL; | 1149 | evlist->threads = NULL; |
1125 | return -1; | 1150 | return -1; |
1126 | } | 1151 | } |
@@ -1353,7 +1378,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist) | |||
1353 | out: | 1378 | out: |
1354 | return err; | 1379 | return err; |
1355 | out_free_cpus: | 1380 | out_free_cpus: |
1356 | cpu_map__delete(evlist->cpus); | 1381 | cpu_map__put(evlist->cpus); |
1357 | evlist->cpus = NULL; | 1382 | evlist->cpus = NULL; |
1358 | goto out; | 1383 | goto out; |
1359 | } | 1384 | } |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1b56047af96b..1b2f480a3e82 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -885,6 +885,8 @@ void perf_evsel__exit(struct perf_evsel *evsel) | |||
885 | perf_evsel__free_fd(evsel); | 885 | perf_evsel__free_fd(evsel); |
886 | perf_evsel__free_id(evsel); | 886 | perf_evsel__free_id(evsel); |
887 | close_cgroup(evsel->cgrp); | 887 | close_cgroup(evsel->cgrp); |
888 | cpu_map__put(evsel->cpus); | ||
889 | thread_map__put(evsel->threads); | ||
888 | zfree(&evsel->group_name); | 890 | zfree(&evsel->group_name); |
889 | zfree(&evsel->name); | 891 | zfree(&evsel->name); |
890 | perf_evsel__object.fini(evsel); | 892 | perf_evsel__object.fini(evsel); |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index bb0579e8a10a..4dbf32d94dfb 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/types.h> | 8 | #include <linux/types.h> |
9 | #include "xyarray.h" | 9 | #include "xyarray.h" |
10 | #include "symbol.h" | 10 | #include "symbol.h" |
11 | #include "cpumap.h" | ||
11 | 12 | ||
12 | struct perf_counts_values { | 13 | struct perf_counts_values { |
13 | union { | 14 | union { |
@@ -82,6 +83,7 @@ struct perf_evsel { | |||
82 | struct cgroup_sel *cgrp; | 83 | struct cgroup_sel *cgrp; |
83 | void *handler; | 84 | void *handler; |
84 | struct cpu_map *cpus; | 85 | struct cpu_map *cpus; |
86 | struct thread_map *threads; | ||
85 | unsigned int sample_size; | 87 | unsigned int sample_size; |
86 | int id_pos; | 88 | int id_pos; |
87 | int is_pos; | 89 | int is_pos; |
@@ -113,6 +115,16 @@ struct thread_map; | |||
113 | struct perf_evlist; | 115 | struct perf_evlist; |
114 | struct record_opts; | 116 | struct record_opts; |
115 | 117 | ||
118 | static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel) | ||
119 | { | ||
120 | return evsel->cpus; | ||
121 | } | ||
122 | |||
123 | static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) | ||
124 | { | ||
125 | return perf_evsel__cpus(evsel)->nr; | ||
126 | } | ||
127 | |||
116 | void perf_counts_values__scale(struct perf_counts_values *count, | 128 | void perf_counts_values__scale(struct perf_counts_values *count, |
117 | bool scale, s8 *pscaled); | 129 | bool scale, s8 *pscaled); |
118 | 130 | ||
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 21a77e7a171e..03ace57a800c 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1063,8 +1063,7 @@ out: | |||
1063 | free(buf); | 1063 | free(buf); |
1064 | return events; | 1064 | return events; |
1065 | error: | 1065 | error: |
1066 | if (events) | 1066 | free_event_desc(events); |
1067 | free_event_desc(events); | ||
1068 | events = NULL; | 1067 | events = NULL; |
1069 | goto out; | 1068 | goto out; |
1070 | } | 1069 | } |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 2a4d1ec02846..09f8d2357108 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "parse-events-flex.h" | 17 | #include "parse-events-flex.h" |
18 | #include "pmu.h" | 18 | #include "pmu.h" |
19 | #include "thread_map.h" | 19 | #include "thread_map.h" |
20 | #include "cpumap.h" | ||
20 | #include "asm/bug.h" | 21 | #include "asm/bug.h" |
21 | 22 | ||
22 | #define MAX_NAME_LEN 100 | 23 | #define MAX_NAME_LEN 100 |
@@ -285,7 +286,9 @@ __add_event(struct list_head *list, int *idx, | |||
285 | if (!evsel) | 286 | if (!evsel) |
286 | return NULL; | 287 | return NULL; |
287 | 288 | ||
288 | evsel->cpus = cpus; | 289 | if (cpus) |
290 | evsel->cpus = cpu_map__get(cpus); | ||
291 | |||
289 | if (name) | 292 | if (name) |
290 | evsel->name = strdup(name); | 293 | evsel->name = strdup(name); |
291 | list_add_tail(&evsel->node, list); | 294 | list_add_tail(&evsel->node, list); |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index d906d0ad5d40..626422eda727 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -384,7 +384,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, | |||
384 | 384 | ||
385 | static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) | 385 | static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) |
386 | { | 386 | { |
387 | cpu_map__delete(pcpus->cpus); | 387 | cpu_map__put(pcpus->cpus); |
388 | pcpus->ob_type->tp_free((PyObject*)pcpus); | 388 | pcpus->ob_type->tp_free((PyObject*)pcpus); |
389 | } | 389 | } |
390 | 390 | ||
@@ -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/record.c b/tools/perf/util/record.c index d457c523a33d..1f7becbe5e18 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -64,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn) | |||
64 | if (!cpus) | 64 | if (!cpus) |
65 | return false; | 65 | return false; |
66 | cpu = cpus->map[0]; | 66 | cpu = cpus->map[0]; |
67 | cpu_map__delete(cpus); | 67 | cpu_map__put(cpus); |
68 | 68 | ||
69 | do { | 69 | do { |
70 | ret = perf_do_probe_api(fn, cpu, try[i++]); | 70 | ret = perf_do_probe_api(fn, cpu, try[i++]); |
@@ -226,7 +226,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) | |||
226 | struct cpu_map *cpus = cpu_map__new(NULL); | 226 | struct cpu_map *cpus = cpu_map__new(NULL); |
227 | 227 | ||
228 | cpu = cpus ? cpus->map[0] : 0; | 228 | cpu = cpus ? cpus->map[0] : 0; |
229 | cpu_map__delete(cpus); | 229 | cpu_map__put(cpus); |
230 | } else { | 230 | } else { |
231 | cpu = evlist->cpus->map[0]; | 231 | cpu = evlist->cpus->map[0]; |
232 | } | 232 | } |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index b5549b58bb2b..ed9dc2555ec7 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1895,7 +1895,7 @@ int perf_session__cpu_bitmap(struct perf_session *session, | |||
1895 | err = 0; | 1895 | err = 0; |
1896 | 1896 | ||
1897 | out_delete_map: | 1897 | out_delete_map: |
1898 | cpu_map__delete(map); | 1898 | cpu_map__put(map); |
1899 | return err; | 1899 | return err; |
1900 | } | 1900 | } |
1901 | 1901 | ||
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c index 283d3e73e2f2..eec6c1149f44 100644 --- a/tools/perf/util/svghelper.c +++ b/tools/perf/util/svghelper.c | |||
@@ -748,7 +748,7 @@ static int str_to_bitmap(char *s, cpumask_t *b) | |||
748 | set_bit(c, cpumask_bits(b)); | 748 | set_bit(c, cpumask_bits(b)); |
749 | } | 749 | } |
750 | 750 | ||
751 | cpu_map__delete(m); | 751 | cpu_map__put(m); |
752 | 752 | ||
753 | return ret; | 753 | return ret; |
754 | } | 754 | } |
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c index 8c3c3a0751bd..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 | ||
@@ -22,7 +23,7 @@ static int filter(const struct dirent *dir) | |||
22 | 23 | ||
23 | static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) | 24 | static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) |
24 | { | 25 | { |
25 | size_t size = sizeof(*map) + sizeof(pid_t) * nr; | 26 | size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; |
26 | 27 | ||
27 | return realloc(map, size); | 28 | return realloc(map, size); |
28 | } | 29 | } |
@@ -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) |