perf session: Move threads to struct machine
The 'machine' abstraction was introduced with 'perf kvm' where we could have samples for the host and multiple guests, but at the time we ended up keeping the list of all machines threads all in session->host_machine. Move the threads rb_tree to struct machine to separate the namespaces. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic 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> Link: http://lkml.kernel.org/n/tip-mdg7sm6j3va09vtgj49gbsrp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
01c2d99bcf
commit
b424eba271
6 changed files with 58 additions and 15 deletions
|
@ -48,8 +48,8 @@ static int perf_event__exit_del_thread(union perf_event *event,
|
|||
event->fork.ppid, event->fork.ptid);
|
||||
|
||||
if (thread) {
|
||||
rb_erase(&thread->rb_node, &session->threads);
|
||||
session->last_match = NULL;
|
||||
rb_erase(&thread->rb_node, &session->host_machine.threads);
|
||||
session->host_machine.last_match = NULL;
|
||||
thread__delete(thread);
|
||||
}
|
||||
|
||||
|
|
|
@ -562,6 +562,10 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
|
|||
INIT_LIST_HEAD(&self->user_dsos);
|
||||
INIT_LIST_HEAD(&self->kernel_dsos);
|
||||
|
||||
self->threads = RB_ROOT;
|
||||
INIT_LIST_HEAD(&self->dead_threads);
|
||||
self->last_match = NULL;
|
||||
|
||||
self->kmaps.machine = self;
|
||||
self->pid = pid;
|
||||
self->root_dir = strdup(root_dir);
|
||||
|
|
|
@ -62,6 +62,9 @@ struct machine {
|
|||
struct rb_node rb_node;
|
||||
pid_t pid;
|
||||
char *root_dir;
|
||||
struct rb_root threads;
|
||||
struct list_head dead_threads;
|
||||
struct thread *last_match;
|
||||
struct list_head user_dsos;
|
||||
struct list_head kernel_dsos;
|
||||
struct map_groups kmaps;
|
||||
|
@ -190,6 +193,12 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
|
|||
struct map **mapp,
|
||||
symbol_filter_t filter);
|
||||
|
||||
|
||||
struct thread *machine__findnew_thread(struct machine *machine, pid_t pid);
|
||||
void machine__remove_thread(struct machine *machine, struct thread *th);
|
||||
|
||||
size_t machine__fprintf(struct machine *machine, FILE *fp);
|
||||
|
||||
static inline
|
||||
struct symbol *machine__find_kernel_symbol(struct machine *self,
|
||||
enum map_type type, u64 addr,
|
||||
|
|
|
@ -139,9 +139,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
|
|||
goto out;
|
||||
|
||||
memcpy(self->filename, filename, len);
|
||||
self->threads = RB_ROOT;
|
||||
INIT_LIST_HEAD(&self->dead_threads);
|
||||
self->last_match = NULL;
|
||||
/*
|
||||
* On 64bit we can mmap the data file in one go. No need for tiny mmap
|
||||
* slices. On 32bit we use 32MB.
|
||||
|
@ -184,17 +181,22 @@ struct perf_session *perf_session__new(const char *filename, int mode,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void perf_session__delete_dead_threads(struct perf_session *self)
|
||||
static void machine__delete_dead_threads(struct machine *machine)
|
||||
{
|
||||
struct thread *n, *t;
|
||||
|
||||
list_for_each_entry_safe(t, n, &self->dead_threads, node) {
|
||||
list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
|
||||
list_del(&t->node);
|
||||
thread__delete(t);
|
||||
}
|
||||
}
|
||||
|
||||
static void perf_session__delete_threads(struct perf_session *self)
|
||||
static void perf_session__delete_dead_threads(struct perf_session *session)
|
||||
{
|
||||
machine__delete_dead_threads(&session->host_machine);
|
||||
}
|
||||
|
||||
static void machine__delete_threads(struct machine *self)
|
||||
{
|
||||
struct rb_node *nd = rb_first(&self->threads);
|
||||
|
||||
|
@ -207,6 +209,11 @@ static void perf_session__delete_threads(struct perf_session *self)
|
|||
}
|
||||
}
|
||||
|
||||
static void perf_session__delete_threads(struct perf_session *session)
|
||||
{
|
||||
machine__delete_threads(&session->host_machine);
|
||||
}
|
||||
|
||||
void perf_session__delete(struct perf_session *self)
|
||||
{
|
||||
perf_session__destroy_kernel_maps(self);
|
||||
|
@ -217,7 +224,7 @@ void perf_session__delete(struct perf_session *self)
|
|||
free(self);
|
||||
}
|
||||
|
||||
void perf_session__remove_thread(struct perf_session *self, struct thread *th)
|
||||
void machine__remove_thread(struct machine *self, struct thread *th)
|
||||
{
|
||||
self->last_match = NULL;
|
||||
rb_erase(&th->rb_node, &self->threads);
|
||||
|
@ -884,6 +891,11 @@ void perf_event_header__bswap(struct perf_event_header *self)
|
|||
self->size = bswap_16(self->size);
|
||||
}
|
||||
|
||||
struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
|
||||
{
|
||||
return machine__findnew_thread(&session->host_machine, pid);
|
||||
}
|
||||
|
||||
static struct thread *perf_session__register_idle_thread(struct perf_session *self)
|
||||
{
|
||||
struct thread *thread = perf_session__findnew(self, 0);
|
||||
|
@ -1224,6 +1236,27 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
size_t perf_session__fprintf(struct perf_session *session, FILE *fp)
|
||||
{
|
||||
/*
|
||||
* FIXME: Here we have to actually print all the machines in this
|
||||
* session, not just the host...
|
||||
*/
|
||||
return machine__fprintf(&session->host_machine, fp);
|
||||
}
|
||||
|
||||
void perf_session__remove_thread(struct perf_session *session,
|
||||
struct thread *th)
|
||||
{
|
||||
/*
|
||||
* FIXME: This one makes no sense, we need to remove the thread from
|
||||
* the machine it belongs to, perf_session can have many machines, so
|
||||
* doing it always on ->host_machine is wrong. Fix when auditing all
|
||||
* the 'perf kvm' code.
|
||||
*/
|
||||
machine__remove_thread(&session->host_machine, th);
|
||||
}
|
||||
|
||||
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
|
||||
unsigned int type)
|
||||
{
|
||||
|
|
|
@ -30,9 +30,6 @@ struct perf_session {
|
|||
struct perf_header header;
|
||||
unsigned long size;
|
||||
unsigned long mmap_window;
|
||||
struct rb_root threads;
|
||||
struct list_head dead_threads;
|
||||
struct thread *last_match;
|
||||
struct machine host_machine;
|
||||
struct rb_root machines;
|
||||
struct perf_evlist *evlist;
|
||||
|
|
|
@ -61,7 +61,7 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
|
|||
map_groups__fprintf(&self->mg, verbose, fp);
|
||||
}
|
||||
|
||||
struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
|
||||
struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
|
||||
{
|
||||
struct rb_node **p = &self->threads.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
|
@ -125,12 +125,12 @@ int thread__fork(struct thread *self, struct thread *parent)
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
|
||||
size_t machine__fprintf(struct machine *machine, FILE *fp)
|
||||
{
|
||||
size_t ret = 0;
|
||||
struct rb_node *nd;
|
||||
|
||||
for (nd = rb_first(&self->threads); nd; nd = rb_next(nd)) {
|
||||
for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
|
||||
struct thread *pos = rb_entry(nd, struct thread, rb_node);
|
||||
|
||||
ret += thread__fprintf(pos, fp);
|
||||
|
|
Loading…
Reference in a new issue