diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-11-09 15:32:52 +0100 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-11-09 15:32:52 +0100 |
commit | 69d2591a829132492662bbfe164fcde5e44ad1c4 (patch) | |
tree | 980dd4ff2e59c021f63ca82ef13427f3a70a7656 /tools/perf/util/machine.c | |
parent | perf diff: Use hists__link when not pairing just with baseline (diff) | |
download | linux-69d2591a829132492662bbfe164fcde5e44ad1c4.tar.xz linux-69d2591a829132492662bbfe164fcde5e44ad1c4.zip |
perf machine: Move more methods to machine.[ch]
This time out of map.[ch] mostly, just code move plus a buch of 'self'
removal, using machine or machines instead.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
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-j1vtux3vnu6wzmrjutpxnjcz@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r-- | tools/perf/util/machine.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 4c6754ac6b20..1f09d0581e6b 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -2,9 +2,192 @@ #include "event.h" #include "machine.h" #include "map.h" +#include "strlist.h" #include "thread.h" #include <stdbool.h> +int machine__init(struct machine *machine, const char *root_dir, pid_t pid) +{ + map_groups__init(&machine->kmaps); + RB_CLEAR_NODE(&machine->rb_node); + INIT_LIST_HEAD(&machine->user_dsos); + INIT_LIST_HEAD(&machine->kernel_dsos); + + machine->threads = RB_ROOT; + INIT_LIST_HEAD(&machine->dead_threads); + machine->last_match = NULL; + + machine->kmaps.machine = machine; + machine->pid = pid; + + machine->root_dir = strdup(root_dir); + if (machine->root_dir == NULL) + return -ENOMEM; + + if (pid != HOST_KERNEL_ID) { + struct thread *thread = machine__findnew_thread(machine, pid); + char comm[64]; + + if (thread == NULL) + return -ENOMEM; + + snprintf(comm, sizeof(comm), "[guest/%d]", pid); + thread__set_comm(thread, comm); + } + + return 0; +} + +static void dsos__delete(struct list_head *dsos) +{ + struct dso *pos, *n; + + list_for_each_entry_safe(pos, n, dsos, node) { + list_del(&pos->node); + dso__delete(pos); + } +} + +void machine__exit(struct machine *machine) +{ + map_groups__exit(&machine->kmaps); + dsos__delete(&machine->user_dsos); + dsos__delete(&machine->kernel_dsos); + free(machine->root_dir); + machine->root_dir = NULL; +} + +void machine__delete(struct machine *machine) +{ + machine__exit(machine); + free(machine); +} + +struct machine *machines__add(struct rb_root *machines, pid_t pid, + const char *root_dir) +{ + struct rb_node **p = &machines->rb_node; + struct rb_node *parent = NULL; + struct machine *pos, *machine = malloc(sizeof(*machine)); + + if (machine == NULL) + return NULL; + + if (machine__init(machine, root_dir, pid) != 0) { + free(machine); + return NULL; + } + + while (*p != NULL) { + parent = *p; + pos = rb_entry(parent, struct machine, rb_node); + if (pid < pos->pid) + p = &(*p)->rb_left; + else + p = &(*p)->rb_right; + } + + rb_link_node(&machine->rb_node, parent, p); + rb_insert_color(&machine->rb_node, machines); + + return machine; +} + +struct machine *machines__find(struct rb_root *machines, pid_t pid) +{ + struct rb_node **p = &machines->rb_node; + struct rb_node *parent = NULL; + struct machine *machine; + struct machine *default_machine = NULL; + + while (*p != NULL) { + parent = *p; + machine = rb_entry(parent, struct machine, rb_node); + if (pid < machine->pid) + p = &(*p)->rb_left; + else if (pid > machine->pid) + p = &(*p)->rb_right; + else + return machine; + if (!machine->pid) + default_machine = machine; + } + + return default_machine; +} + +struct machine *machines__findnew(struct rb_root *machines, pid_t pid) +{ + char path[PATH_MAX]; + const char *root_dir = ""; + struct machine *machine = machines__find(machines, pid); + + if (machine && (machine->pid == pid)) + goto out; + + if ((pid != HOST_KERNEL_ID) && + (pid != DEFAULT_GUEST_KERNEL_ID) && + (symbol_conf.guestmount)) { + sprintf(path, "%s/%d", symbol_conf.guestmount, pid); + if (access(path, R_OK)) { + static struct strlist *seen; + + if (!seen) + seen = strlist__new(true, NULL); + + if (!strlist__has_entry(seen, path)) { + pr_err("Can't access file %s\n", path); + strlist__add(seen, path); + } + machine = NULL; + goto out; + } + root_dir = path; + } + + machine = machines__add(machines, pid, root_dir); +out: + return machine; +} + +void machines__process(struct rb_root *machines, + machine__process_t process, void *data) +{ + struct rb_node *nd; + + for (nd = rb_first(machines); nd; nd = rb_next(nd)) { + struct machine *pos = rb_entry(nd, struct machine, rb_node); + process(pos, data); + } +} + +char *machine__mmap_name(struct machine *machine, char *bf, size_t size) +{ + if (machine__is_host(machine)) + snprintf(bf, size, "[%s]", "kernel.kallsyms"); + else if (machine__is_default_guest(machine)) + snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); + else { + snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", + machine->pid); + } + + return bf; +} + +void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size) +{ + struct rb_node *node; + struct machine *machine; + + for (node = rb_first(machines); node; node = rb_next(node)) { + machine = rb_entry(node, struct machine, rb_node); + machine->id_hdr_size = id_hdr_size; + } + + return; +} + static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, bool create) { |