Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
186fbb74 f30a79b0

+43 -14
+1 -1
tools/perf/tests/code-reading.c
··· 546 546 perf_evlist__delete(evlist); 547 547 } else { 548 548 cpu_map__put(cpus); 549 - thread_map__delete(threads); 549 + thread_map__put(threads); 550 550 } 551 551 machines__destroy_kernel_maps(&machines); 552 552 machine__delete_threads(machine);
+1 -1
tools/perf/tests/keep-tracking.c
··· 145 145 perf_evlist__delete(evlist); 146 146 } else { 147 147 cpu_map__put(cpus); 148 - thread_map__delete(threads); 148 + thread_map__put(threads); 149 149 } 150 150 151 151 return err;
+1 -1
tools/perf/tests/mmap-basic.c
··· 142 142 out_free_cpus: 143 143 cpu_map__put(cpus); 144 144 out_free_threads: 145 - thread_map__delete(threads); 145 + thread_map__put(threads); 146 146 return err; 147 147 }
+1 -1
tools/perf/tests/mmap-thread-lookup.c
··· 143 143 perf_event__process, 144 144 machine, 0, 500); 145 145 146 - thread_map__delete(map); 146 + thread_map__put(map); 147 147 return err; 148 148 } 149 149
+1 -1
tools/perf/tests/openat-syscall-all-cpus.c
··· 111 111 out_evsel_delete: 112 112 perf_evsel__delete(evsel); 113 113 out_thread_map_delete: 114 - thread_map__delete(threads); 114 + thread_map__put(threads); 115 115 return err; 116 116 }
+1 -1
tools/perf/tests/openat-syscall.c
··· 56 56 out_evsel_delete: 57 57 perf_evsel__delete(evsel); 58 58 out_thread_map_delete: 59 - thread_map__delete(threads); 59 + thread_map__put(threads); 60 60 return err; 61 61 }
+1 -1
tools/perf/tests/switch-tracking.c
··· 561 561 perf_evlist__delete(evlist); 562 562 } else { 563 563 cpu_map__put(cpus); 564 - thread_map__delete(threads); 564 + thread_map__put(threads); 565 565 } 566 566 567 567 return err;
+2 -2
tools/perf/util/evlist.c
··· 115 115 perf_evlist__munmap(evlist); 116 116 perf_evlist__close(evlist); 117 117 cpu_map__put(evlist->cpus); 118 - thread_map__delete(evlist->threads); 118 + thread_map__put(evlist->threads); 119 119 evlist->cpus = NULL; 120 120 evlist->threads = NULL; 121 121 perf_evlist__purge(evlist); ··· 1120 1120 return 0; 1121 1121 1122 1122 out_delete_threads: 1123 - thread_map__delete(evlist->threads); 1123 + thread_map__put(evlist->threads); 1124 1124 evlist->threads = NULL; 1125 1125 return -1; 1126 1126 }
+1 -1
tools/perf/util/python.c
··· 453 453 454 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 457 pthreads->ob_type->tp_free((PyObject*)pthreads); 458 458 } 459 459
+28 -2
tools/perf/util/thread_map.c
··· 8 8 #include <unistd.h> 9 9 #include "strlist.h" 10 10 #include <string.h> 11 + #include "asm/bug.h" 11 12 #include "thread_map.h" 12 13 #include "util.h" 13 14 ··· 48 47 for (i = 0; i < items; i++) 49 48 thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); 50 49 threads->nr = items; 50 + atomic_set(&threads->refcnt, 1); 51 51 } 52 52 53 53 for (i=0; i<items; i++) ··· 65 63 if (threads != NULL) { 66 64 thread_map__set_pid(threads, 0, tid); 67 65 threads->nr = 1; 66 + atomic_set(&threads->refcnt, 1); 68 67 } 69 68 70 69 return threads; ··· 87 84 goto out_free_threads; 88 85 89 86 threads->nr = 0; 87 + atomic_set(&threads->refcnt, 1); 90 88 91 89 while (!readdir_r(proc, &dirent, &next) && next) { 92 90 char *end; ··· 216 212 217 213 out: 218 214 strlist__delete(slist); 215 + if (threads) 216 + atomic_set(&threads->refcnt, 1); 219 217 return threads; 220 218 221 219 out_free_namelist: ··· 237 231 if (threads != NULL) { 238 232 thread_map__set_pid(threads, 0, -1); 239 233 threads->nr = 1; 234 + atomic_set(&threads->refcnt, 1); 240 235 } 241 236 return threads; 242 237 } ··· 280 273 threads->nr = ntasks; 281 274 } 282 275 out: 276 + if (threads) 277 + atomic_set(&threads->refcnt, 1); 283 278 return threads; 284 279 285 280 out_free_threads: ··· 301 292 return thread_map__new_by_tid_str(tid); 302 293 } 303 294 304 - void thread_map__delete(struct thread_map *threads) 295 + static void thread_map__delete(struct thread_map *threads) 305 296 { 306 - free(threads); 297 + if (threads) { 298 + WARN_ONCE(atomic_read(&threads->refcnt) != 0, 299 + "thread map refcnt unbalanced\n"); 300 + free(threads); 301 + } 302 + } 303 + 304 + struct thread_map *thread_map__get(struct thread_map *map) 305 + { 306 + if (map) 307 + atomic_inc(&map->refcnt); 308 + return map; 309 + } 310 + 311 + void thread_map__put(struct thread_map *map) 312 + { 313 + if (map && atomic_dec_and_test(&map->refcnt)) 314 + thread_map__delete(map); 307 315 } 308 316 309 317 size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
+5 -2
tools/perf/util/thread_map.h
··· 3 3 4 4 #include <sys/types.h> 5 5 #include <stdio.h> 6 + #include <linux/atomic.h> 6 7 7 8 struct thread_map_data { 8 9 pid_t pid; 9 10 }; 10 11 11 12 struct thread_map { 13 + atomic_t refcnt; 12 14 int nr; 13 15 struct thread_map_data map[]; 14 16 }; ··· 21 19 struct thread_map *thread_map__new_by_uid(uid_t uid); 22 20 struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); 23 21 22 + struct thread_map *thread_map__get(struct thread_map *map); 23 + void thread_map__put(struct thread_map *map); 24 + 24 25 struct thread_map *thread_map__new_str(const char *pid, 25 26 const char *tid, uid_t uid); 26 - 27 - void thread_map__delete(struct thread_map *threads); 28 27 29 28 size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); 30 29