From: Jiri Olsa Date: Mon, 22 Jun 2015 22:36:05 +0000 (+0200) Subject: perf tools: Add reference counting for thread_map object X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=186fbb7432f4a740b4fbaf4145375442210110bb;p=linux-beck.git 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 Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian 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 --- 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: perf_evlist__delete(evlist); } else { cpu_map__put(cpus); - thread_map__delete(threads); + thread_map__put(threads); } machines__destroy_kernel_maps(&machines); 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: perf_evlist__delete(evlist); } else { cpu_map__put(cpus); - thread_map__delete(threads); + thread_map__put(threads); } 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: out_free_cpus: cpu_map__put(cpus); out_free_threads: - thread_map__delete(threads); + thread_map__put(threads); return err; } 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) perf_event__process, machine, 0, 500); - thread_map__delete(map); + thread_map__put(map); return err; } 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: out_evsel_delete: perf_evsel__delete(evsel); out_thread_map_delete: - thread_map__delete(threads); + thread_map__put(threads); return err; } 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: out_evsel_delete: perf_evsel__delete(evsel); out_thread_map_delete: - thread_map__delete(threads); + thread_map__put(threads); return err; } 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: perf_evlist__delete(evlist); } else { cpu_map__put(cpus); - thread_map__delete(threads); + thread_map__put(threads); } 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) perf_evlist__munmap(evlist); perf_evlist__close(evlist); cpu_map__put(evlist->cpus); - thread_map__delete(evlist->threads); + thread_map__put(evlist->threads); evlist->cpus = NULL; evlist->threads = NULL; perf_evlist__purge(evlist); @@ -1120,7 +1120,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target) return 0; out_delete_threads: - thread_map__delete(evlist->threads); + thread_map__put(evlist->threads); evlist->threads = NULL; return -1; } 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, static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) { - thread_map__delete(pthreads->threads); + thread_map__put(pthreads->threads); pthreads->ob_type->tp_free((PyObject*)pthreads); } 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 @@ #include #include "strlist.h" #include +#include "asm/bug.h" #include "thread_map.h" #include "util.h" @@ -47,6 +48,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid) for (i = 0; i < items; i++) thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); threads->nr = items; + atomic_set(&threads->refcnt, 1); } for (i=0; inr = 1; + atomic_set(&threads->refcnt, 1); } return threads; @@ -84,6 +87,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid) goto out_free_threads; threads->nr = 0; + atomic_set(&threads->refcnt, 1); while (!readdir_r(proc, &dirent, &next) && next) { char *end; @@ -212,6 +216,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) out: strlist__delete(slist); + if (threads) + atomic_set(&threads->refcnt, 1); return threads; out_free_namelist: @@ -231,6 +237,7 @@ struct thread_map *thread_map__new_dummy(void) if (threads != NULL) { thread_map__set_pid(threads, 0, -1); threads->nr = 1; + atomic_set(&threads->refcnt, 1); } return threads; } @@ -273,6 +280,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) threads->nr = ntasks; } out: + if (threads) + atomic_set(&threads->refcnt, 1); return threads; out_free_threads: @@ -292,9 +301,26 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid, return thread_map__new_by_tid_str(tid); } -void thread_map__delete(struct thread_map *threads) +static void thread_map__delete(struct thread_map *threads) { - free(threads); + if (threads) { + WARN_ONCE(atomic_read(&threads->refcnt) != 0, + "thread map refcnt unbalanced\n"); + free(threads); + } +} + +struct thread_map *thread_map__get(struct thread_map *map) +{ + if (map) + atomic_inc(&map->refcnt); + return map; +} + +void thread_map__put(struct thread_map *map) +{ + if (map && atomic_dec_and_test(&map->refcnt)) + thread_map__delete(map); } 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 @@ #include #include +#include struct thread_map_data { pid_t pid; }; struct thread_map { + atomic_t refcnt; int nr; struct thread_map_data map[]; }; @@ -19,11 +21,12 @@ struct thread_map *thread_map__new_by_tid(pid_t tid); struct thread_map *thread_map__new_by_uid(uid_t uid); struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); +struct thread_map *thread_map__get(struct thread_map *map); +void thread_map__put(struct thread_map *map); + struct thread_map *thread_map__new_str(const char *pid, const char *tid, uid_t uid); -void thread_map__delete(struct thread_map *threads); - size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); static inline int thread_map__nr(struct thread_map *threads)