diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-12-11 19:11:23 -0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-12-14 12:08:55 -0300 |
commit | abd828688407eb86044f1bc9e5133c55d7597596 (patch) | |
tree | b42146c0c9ffa8dc7cd3643af4e021b5a4f4d1b8 /tools/perf/util/thread.c | |
parent | b6847d2c2a50e96680e233ce4b2784981b6f309e (diff) | |
download | op-kernel-dev-abd828688407eb86044f1bc9e5133c55d7597596.zip op-kernel-dev-abd828688407eb86044f1bc9e5133c55d7597596.tar.gz |
perf thread: Fix reference count initial state
We should always return from thread__new(), the constructor, with the
object with a reference count of one, so that:
struct thread *thread = thread__new();
thread__put(thread);
Will call thread__delete().
If any reference is made to that 'thread' variable, it better use
thread__get(thread) to hold a reference.
We were returning with thread->refcnt set to zero, fix it and some cases
where thread__delete() was being called, which were not a problem
because just one reference was being used, now that we set it to 1, use
thread__put() instead.
Reported-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-4b9mkuk66to4ecckpmpvqx6s@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/thread.c')
-rw-r--r-- | tools/perf/util/thread.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 0a9ae80..dfd00c6 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -19,8 +19,10 @@ int thread__init_map_groups(struct thread *thread, struct machine *machine) thread->mg = map_groups__new(machine); } else { leader = __machine__findnew_thread(machine, pid, pid); - if (leader) + if (leader) { thread->mg = map_groups__get(leader->mg); + thread__put(leader); + } } return thread->mg ? 0 : -1; @@ -53,7 +55,7 @@ struct thread *thread__new(pid_t pid, pid_t tid) goto err_thread; list_add(&comm->list, &thread->comm_list); - atomic_set(&thread->refcnt, 0); + atomic_set(&thread->refcnt, 1); RB_CLEAR_NODE(&thread->rb_node); } @@ -95,6 +97,10 @@ struct thread *thread__get(struct thread *thread) void thread__put(struct thread *thread) { if (thread && atomic_dec_and_test(&thread->refcnt)) { + /* + * Remove it from the dead_threads list, as last reference + * is gone. + */ list_del_init(&thread->node); thread__delete(thread); } |