diff options
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r-- | tools/perf/util/machine.c | 205 |
1 files changed, 196 insertions, 9 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 502eec0d4773..1f09d0581e6b 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -2,9 +2,192 @@ | |||
2 | #include "event.h" | 2 | #include "event.h" |
3 | #include "machine.h" | 3 | #include "machine.h" |
4 | #include "map.h" | 4 | #include "map.h" |
5 | #include "strlist.h" | ||
5 | #include "thread.h" | 6 | #include "thread.h" |
6 | #include <stdbool.h> | 7 | #include <stdbool.h> |
7 | 8 | ||
9 | int machine__init(struct machine *machine, const char *root_dir, pid_t pid) | ||
10 | { | ||
11 | map_groups__init(&machine->kmaps); | ||
12 | RB_CLEAR_NODE(&machine->rb_node); | ||
13 | INIT_LIST_HEAD(&machine->user_dsos); | ||
14 | INIT_LIST_HEAD(&machine->kernel_dsos); | ||
15 | |||
16 | machine->threads = RB_ROOT; | ||
17 | INIT_LIST_HEAD(&machine->dead_threads); | ||
18 | machine->last_match = NULL; | ||
19 | |||
20 | machine->kmaps.machine = machine; | ||
21 | machine->pid = pid; | ||
22 | |||
23 | machine->root_dir = strdup(root_dir); | ||
24 | if (machine->root_dir == NULL) | ||
25 | return -ENOMEM; | ||
26 | |||
27 | if (pid != HOST_KERNEL_ID) { | ||
28 | struct thread *thread = machine__findnew_thread(machine, pid); | ||
29 | char comm[64]; | ||
30 | |||
31 | if (thread == NULL) | ||
32 | return -ENOMEM; | ||
33 | |||
34 | snprintf(comm, sizeof(comm), "[guest/%d]", pid); | ||
35 | thread__set_comm(thread, comm); | ||
36 | } | ||
37 | |||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | static void dsos__delete(struct list_head *dsos) | ||
42 | { | ||
43 | struct dso *pos, *n; | ||
44 | |||
45 | list_for_each_entry_safe(pos, n, dsos, node) { | ||
46 | list_del(&pos->node); | ||
47 | dso__delete(pos); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | void machine__exit(struct machine *machine) | ||
52 | { | ||
53 | map_groups__exit(&machine->kmaps); | ||
54 | dsos__delete(&machine->user_dsos); | ||
55 | dsos__delete(&machine->kernel_dsos); | ||
56 | free(machine->root_dir); | ||
57 | machine->root_dir = NULL; | ||
58 | } | ||
59 | |||
60 | void machine__delete(struct machine *machine) | ||
61 | { | ||
62 | machine__exit(machine); | ||
63 | free(machine); | ||
64 | } | ||
65 | |||
66 | struct machine *machines__add(struct rb_root *machines, pid_t pid, | ||
67 | const char *root_dir) | ||
68 | { | ||
69 | struct rb_node **p = &machines->rb_node; | ||
70 | struct rb_node *parent = NULL; | ||
71 | struct machine *pos, *machine = malloc(sizeof(*machine)); | ||
72 | |||
73 | if (machine == NULL) | ||
74 | return NULL; | ||
75 | |||
76 | if (machine__init(machine, root_dir, pid) != 0) { | ||
77 | free(machine); | ||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | while (*p != NULL) { | ||
82 | parent = *p; | ||
83 | pos = rb_entry(parent, struct machine, rb_node); | ||
84 | if (pid < pos->pid) | ||
85 | p = &(*p)->rb_left; | ||
86 | else | ||
87 | p = &(*p)->rb_right; | ||
88 | } | ||
89 | |||
90 | rb_link_node(&machine->rb_node, parent, p); | ||
91 | rb_insert_color(&machine->rb_node, machines); | ||
92 | |||
93 | return machine; | ||
94 | } | ||
95 | |||
96 | struct machine *machines__find(struct rb_root *machines, pid_t pid) | ||
97 | { | ||
98 | struct rb_node **p = &machines->rb_node; | ||
99 | struct rb_node *parent = NULL; | ||
100 | struct machine *machine; | ||
101 | struct machine *default_machine = NULL; | ||
102 | |||
103 | while (*p != NULL) { | ||
104 | parent = *p; | ||
105 | machine = rb_entry(parent, struct machine, rb_node); | ||
106 | if (pid < machine->pid) | ||
107 | p = &(*p)->rb_left; | ||
108 | else if (pid > machine->pid) | ||
109 | p = &(*p)->rb_right; | ||
110 | else | ||
111 | return machine; | ||
112 | if (!machine->pid) | ||
113 | default_machine = machine; | ||
114 | } | ||
115 | |||
116 | return default_machine; | ||
117 | } | ||
118 | |||
119 | struct machine *machines__findnew(struct rb_root *machines, pid_t pid) | ||
120 | { | ||
121 | char path[PATH_MAX]; | ||
122 | const char *root_dir = ""; | ||
123 | struct machine *machine = machines__find(machines, pid); | ||
124 | |||
125 | if (machine && (machine->pid == pid)) | ||
126 | goto out; | ||
127 | |||
128 | if ((pid != HOST_KERNEL_ID) && | ||
129 | (pid != DEFAULT_GUEST_KERNEL_ID) && | ||
130 | (symbol_conf.guestmount)) { | ||
131 | sprintf(path, "%s/%d", symbol_conf.guestmount, pid); | ||
132 | if (access(path, R_OK)) { | ||
133 | static struct strlist *seen; | ||
134 | |||
135 | if (!seen) | ||
136 | seen = strlist__new(true, NULL); | ||
137 | |||
138 | if (!strlist__has_entry(seen, path)) { | ||
139 | pr_err("Can't access file %s\n", path); | ||
140 | strlist__add(seen, path); | ||
141 | } | ||
142 | machine = NULL; | ||
143 | goto out; | ||
144 | } | ||
145 | root_dir = path; | ||
146 | } | ||
147 | |||
148 | machine = machines__add(machines, pid, root_dir); | ||
149 | out: | ||
150 | return machine; | ||
151 | } | ||
152 | |||
153 | void machines__process(struct rb_root *machines, | ||
154 | machine__process_t process, void *data) | ||
155 | { | ||
156 | struct rb_node *nd; | ||
157 | |||
158 | for (nd = rb_first(machines); nd; nd = rb_next(nd)) { | ||
159 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
160 | process(pos, data); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | char *machine__mmap_name(struct machine *machine, char *bf, size_t size) | ||
165 | { | ||
166 | if (machine__is_host(machine)) | ||
167 | snprintf(bf, size, "[%s]", "kernel.kallsyms"); | ||
168 | else if (machine__is_default_guest(machine)) | ||
169 | snprintf(bf, size, "[%s]", "guest.kernel.kallsyms"); | ||
170 | else { | ||
171 | snprintf(bf, size, "[%s.%d]", "guest.kernel.kallsyms", | ||
172 | machine->pid); | ||
173 | } | ||
174 | |||
175 | return bf; | ||
176 | } | ||
177 | |||
178 | void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size) | ||
179 | { | ||
180 | struct rb_node *node; | ||
181 | struct machine *machine; | ||
182 | |||
183 | for (node = rb_first(machines); node; node = rb_next(node)) { | ||
184 | machine = rb_entry(node, struct machine, rb_node); | ||
185 | machine->id_hdr_size = id_hdr_size; | ||
186 | } | ||
187 | |||
188 | return; | ||
189 | } | ||
190 | |||
8 | static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, | 191 | static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid, |
9 | bool create) | 192 | bool create) |
10 | { | 193 | { |
@@ -84,15 +267,19 @@ int machine__process_lost_event(struct machine *machine __maybe_unused, | |||
84 | static void machine__set_kernel_mmap_len(struct machine *machine, | 267 | static void machine__set_kernel_mmap_len(struct machine *machine, |
85 | union perf_event *event) | 268 | union perf_event *event) |
86 | { | 269 | { |
87 | machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start; | 270 | int i; |
88 | machine->vmlinux_maps[MAP__FUNCTION]->end = (event->mmap.start + | 271 | |
89 | event->mmap.len); | 272 | for (i = 0; i < MAP__NR_TYPES; i++) { |
90 | /* | 273 | machine->vmlinux_maps[i]->start = event->mmap.start; |
91 | * Be a bit paranoid here, some perf.data file came with | 274 | machine->vmlinux_maps[i]->end = (event->mmap.start + |
92 | * a zero sized synthesized MMAP event for the kernel. | 275 | event->mmap.len); |
93 | */ | 276 | /* |
94 | if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0) | 277 | * Be a bit paranoid here, some perf.data file came with |
95 | machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL; | 278 | * a zero sized synthesized MMAP event for the kernel. |
279 | */ | ||
280 | if (machine->vmlinux_maps[i]->end == 0) | ||
281 | machine->vmlinux_maps[i]->end = ~0ULL; | ||
282 | } | ||
96 | } | 283 | } |
97 | 284 | ||
98 | static int machine__process_kernel_mmap_event(struct machine *machine, | 285 | static int machine__process_kernel_mmap_event(struct machine *machine, |