diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-06-17 11:37:44 (GMT) |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-06-17 11:37:44 (GMT) |
commit | 720a3aeb7373cb49cf222d5f12e121f78d3d4410 (patch) | |
tree | e2451f06fe4983c4aae971bdaf31fe538a7fec1a /tools/perf/util/session.c | |
parent | 174787cb5144e5a45141ec7cb9d95ea29bbe22bb (diff) | |
download | linux-fsl-qoriq-720a3aeb7373cb49cf222d5f12e121f78d3d4410.tar.xz |
perf session: Remove threads from tree on PERF_RECORD_EXIT
Move them to a session->dead_threads list just like we do with maps that
are replaced, because we may have hist_entries pointing to them.
This fixes a bug when inserting maps for a new thread that reused the
TID, mixing maps for two different threads, causing an endless loop.
The code for insering maps should be made more robust but for .35 this
is the minimalistic patch.
Reported-by: Ingo Molnar <mingo@elte.hu>
Cc: David S. Miller <davem@davemloft.net>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
LKML-Reference: <new-submission>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r-- | tools/perf/util/session.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8f83a18..c422cd6 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -90,6 +90,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc memcpy(self->filename, filename, len); self->threads = RB_ROOT; + INIT_LIST_HEAD(&self->dead_threads); self->hists_tree = RB_ROOT; self->last_match = NULL; self->mmap_window = 32; @@ -131,6 +132,16 @@ void perf_session__delete(struct perf_session *self) free(self); } +void perf_session__remove_thread(struct perf_session *self, struct thread *th) +{ + rb_erase(&th->rb_node, &self->threads); + /* + * We may have references to this thread, for instance in some hist_entry + * instances, so just move them to a separate list. + */ + list_add_tail(&th->node, &self->dead_threads); +} + static bool symbol__match_parent_regex(struct symbol *sym) { if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) |