perf tools: Reference count struct thread
We need to do that to stop accumulating entries in the dead_threads linked list, i.e. we were keeping references to threads in struct hists that continue to exist even after a thread exited and was removed from the machine threads rbtree. We still keep the dead_threads list, but just for debugging, allowing us to iterate at any given point over the threads that still are referenced by things like struct hist_entry. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Borislav Petkov <bp@suse.de> Cc: David Ahern <dsahern@gmail.com> Cc: Don Zickus <dzickus@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-3ejvfyed0r7ue61dkurzjux4@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
#include "unwind.h"
|
||||
#include "linux/hash.h"
|
||||
|
||||
static void machine__remove_thread(struct machine *machine, struct thread *th);
|
||||
|
||||
static void dsos__init(struct dsos *dsos)
|
||||
{
|
||||
INIT_LIST_HEAD(&dsos->head);
|
||||
@@ -89,16 +91,6 @@ static void dsos__delete(struct dsos *dsos)
|
||||
}
|
||||
}
|
||||
|
||||
void machine__delete_dead_threads(struct machine *machine)
|
||||
{
|
||||
struct thread *n, *t;
|
||||
|
||||
list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
|
||||
list_del(&t->node);
|
||||
thread__delete(t);
|
||||
}
|
||||
}
|
||||
|
||||
void machine__delete_threads(struct machine *machine)
|
||||
{
|
||||
struct rb_node *nd = rb_first(&machine->threads);
|
||||
@@ -106,9 +98,8 @@ void machine__delete_threads(struct machine *machine)
|
||||
while (nd) {
|
||||
struct thread *t = rb_entry(nd, struct thread, rb_node);
|
||||
|
||||
rb_erase(&t->rb_node, &machine->threads);
|
||||
nd = rb_next(nd);
|
||||
thread__delete(t);
|
||||
machine__remove_thread(machine, t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,9 +352,13 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
|
||||
* the full rbtree:
|
||||
*/
|
||||
th = machine->last_match;
|
||||
if (th && th->tid == tid) {
|
||||
machine__update_thread_pid(machine, th, pid);
|
||||
return th;
|
||||
if (th != NULL) {
|
||||
if (th->tid == tid) {
|
||||
machine__update_thread_pid(machine, th, pid);
|
||||
return th;
|
||||
}
|
||||
|
||||
thread__zput(machine->last_match);
|
||||
}
|
||||
|
||||
while (*p != NULL) {
|
||||
@@ -371,7 +366,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
|
||||
th = rb_entry(parent, struct thread, rb_node);
|
||||
|
||||
if (th->tid == tid) {
|
||||
machine->last_match = th;
|
||||
machine->last_match = thread__get(th);
|
||||
machine__update_thread_pid(machine, th, pid);
|
||||
return th;
|
||||
}
|
||||
@@ -403,8 +398,11 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
|
||||
thread__delete(th);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
machine->last_match = th;
|
||||
/*
|
||||
* It is now in the rbtree, get a ref
|
||||
*/
|
||||
thread__get(th);
|
||||
machine->last_match = thread__get(th);
|
||||
}
|
||||
|
||||
return th;
|
||||
@@ -1238,13 +1236,17 @@ out_problem:
|
||||
|
||||
static void machine__remove_thread(struct machine *machine, struct thread *th)
|
||||
{
|
||||
machine->last_match = NULL;
|
||||
if (machine->last_match == th)
|
||||
thread__zput(machine->last_match);
|
||||
|
||||
rb_erase(&th->rb_node, &machine->threads);
|
||||
/*
|
||||
* We may have references to this thread, for instance in some hist_entry
|
||||
* instances, so just move them to a separate list.
|
||||
* Move it first to the dead_threads list, then drop the reference,
|
||||
* if this is the last reference, then the thread__delete destructor
|
||||
* will be called and we will remove it from the dead_threads list.
|
||||
*/
|
||||
list_add_tail(&th->node, &machine->dead_threads);
|
||||
thread__put(th);
|
||||
}
|
||||
|
||||
int machine__process_fork_event(struct machine *machine, union perf_event *event,
|
||||
|
Reference in New Issue
Block a user