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>
This commit is contained in:
parent
f30a79b012
commit
186fbb7432
11 changed files with 43 additions and 14 deletions
|
@ -546,7 +546,7 @@ static int do_test_code_reading(bool try_kcore)
|
||||||
perf_evlist__delete(evlist);
|
perf_evlist__delete(evlist);
|
||||||
} else {
|
} else {
|
||||||
cpu_map__put(cpus);
|
cpu_map__put(cpus);
|
||||||
thread_map__delete(threads);
|
thread_map__put(threads);
|
||||||
}
|
}
|
||||||
machines__destroy_kernel_maps(&machines);
|
machines__destroy_kernel_maps(&machines);
|
||||||
machine__delete_threads(machine);
|
machine__delete_threads(machine);
|
||||||
|
|
|
@ -145,7 +145,7 @@ int test__keep_tracking(void)
|
||||||
perf_evlist__delete(evlist);
|
perf_evlist__delete(evlist);
|
||||||
} else {
|
} else {
|
||||||
cpu_map__put(cpus);
|
cpu_map__put(cpus);
|
||||||
thread_map__delete(threads);
|
thread_map__put(threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -142,6 +142,6 @@ int test__basic_mmap(void)
|
||||||
out_free_cpus:
|
out_free_cpus:
|
||||||
cpu_map__put(cpus);
|
cpu_map__put(cpus);
|
||||||
out_free_threads:
|
out_free_threads:
|
||||||
thread_map__delete(threads);
|
thread_map__put(threads);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ static int synth_process(struct machine *machine)
|
||||||
perf_event__process,
|
perf_event__process,
|
||||||
machine, 0, 500);
|
machine, 0, 500);
|
||||||
|
|
||||||
thread_map__delete(map);
|
thread_map__put(map);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,6 @@ int test__openat_syscall_event_on_all_cpus(void)
|
||||||
out_evsel_delete:
|
out_evsel_delete:
|
||||||
perf_evsel__delete(evsel);
|
perf_evsel__delete(evsel);
|
||||||
out_thread_map_delete:
|
out_thread_map_delete:
|
||||||
thread_map__delete(threads);
|
thread_map__put(threads);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,6 @@ int test__openat_syscall_event(void)
|
||||||
out_evsel_delete:
|
out_evsel_delete:
|
||||||
perf_evsel__delete(evsel);
|
perf_evsel__delete(evsel);
|
||||||
out_thread_map_delete:
|
out_thread_map_delete:
|
||||||
thread_map__delete(threads);
|
thread_map__put(threads);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -561,7 +561,7 @@ int test__switch_tracking(void)
|
||||||
perf_evlist__delete(evlist);
|
perf_evlist__delete(evlist);
|
||||||
} else {
|
} else {
|
||||||
cpu_map__put(cpus);
|
cpu_map__put(cpus);
|
||||||
thread_map__delete(threads);
|
thread_map__put(threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)
|
||||||
perf_evlist__munmap(evlist);
|
perf_evlist__munmap(evlist);
|
||||||
perf_evlist__close(evlist);
|
perf_evlist__close(evlist);
|
||||||
cpu_map__put(evlist->cpus);
|
cpu_map__put(evlist->cpus);
|
||||||
thread_map__delete(evlist->threads);
|
thread_map__put(evlist->threads);
|
||||||
evlist->cpus = NULL;
|
evlist->cpus = NULL;
|
||||||
evlist->threads = NULL;
|
evlist->threads = NULL;
|
||||||
perf_evlist__purge(evlist);
|
perf_evlist__purge(evlist);
|
||||||
|
@ -1120,7 +1120,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_delete_threads:
|
out_delete_threads:
|
||||||
thread_map__delete(evlist->threads);
|
thread_map__put(evlist->threads);
|
||||||
evlist->threads = NULL;
|
evlist->threads = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
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);
|
pthreads->ob_type->tp_free((PyObject*)pthreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "strlist.h"
|
#include "strlist.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "asm/bug.h"
|
||||||
#include "thread_map.h"
|
#include "thread_map.h"
|
||||||
#include "util.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++)
|
for (i = 0; i < items; i++)
|
||||||
thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
|
thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
|
||||||
threads->nr = items;
|
threads->nr = items;
|
||||||
|
atomic_set(&threads->refcnt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<items; i++)
|
for (i=0; i<items; i++)
|
||||||
|
@ -63,6 +65,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
|
||||||
if (threads != NULL) {
|
if (threads != NULL) {
|
||||||
thread_map__set_pid(threads, 0, tid);
|
thread_map__set_pid(threads, 0, tid);
|
||||||
threads->nr = 1;
|
threads->nr = 1;
|
||||||
|
atomic_set(&threads->refcnt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return threads;
|
return threads;
|
||||||
|
@ -84,6 +87,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
|
||||||
goto out_free_threads;
|
goto out_free_threads;
|
||||||
|
|
||||||
threads->nr = 0;
|
threads->nr = 0;
|
||||||
|
atomic_set(&threads->refcnt, 1);
|
||||||
|
|
||||||
while (!readdir_r(proc, &dirent, &next) && next) {
|
while (!readdir_r(proc, &dirent, &next) && next) {
|
||||||
char *end;
|
char *end;
|
||||||
|
@ -212,6 +216,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
|
||||||
|
|
||||||
out:
|
out:
|
||||||
strlist__delete(slist);
|
strlist__delete(slist);
|
||||||
|
if (threads)
|
||||||
|
atomic_set(&threads->refcnt, 1);
|
||||||
return threads;
|
return threads;
|
||||||
|
|
||||||
out_free_namelist:
|
out_free_namelist:
|
||||||
|
@ -231,6 +237,7 @@ struct thread_map *thread_map__new_dummy(void)
|
||||||
if (threads != NULL) {
|
if (threads != NULL) {
|
||||||
thread_map__set_pid(threads, 0, -1);
|
thread_map__set_pid(threads, 0, -1);
|
||||||
threads->nr = 1;
|
threads->nr = 1;
|
||||||
|
atomic_set(&threads->refcnt, 1);
|
||||||
}
|
}
|
||||||
return threads;
|
return threads;
|
||||||
}
|
}
|
||||||
|
@ -273,6 +280,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
|
||||||
threads->nr = ntasks;
|
threads->nr = ntasks;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
if (threads)
|
||||||
|
atomic_set(&threads->refcnt, 1);
|
||||||
return threads;
|
return threads;
|
||||||
|
|
||||||
out_free_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);
|
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)
|
size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <linux/atomic.h>
|
||||||
|
|
||||||
struct thread_map_data {
|
struct thread_map_data {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thread_map {
|
struct thread_map {
|
||||||
|
atomic_t refcnt;
|
||||||
int nr;
|
int nr;
|
||||||
struct thread_map_data map[];
|
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_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__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,
|
struct thread_map *thread_map__new_str(const char *pid,
|
||||||
const char *tid, uid_t uid);
|
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);
|
size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
|
||||||
|
|
||||||
static inline int thread_map__nr(struct thread_map *threads)
|
static inline int thread_map__nr(struct thread_map *threads)
|
||||||
|
|
Loading…
Reference in a new issue