diff options
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r-- | tools/perf/util/session.c | 325 |
1 files changed, 64 insertions, 261 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index ce6f51162386..bd85280bb6e8 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include "cpumap.h" | 16 | #include "cpumap.h" |
17 | #include "event-parse.h" | 17 | #include "event-parse.h" |
18 | #include "perf_regs.h" | 18 | #include "perf_regs.h" |
19 | #include "unwind.h" | ||
20 | #include "vdso.h" | 19 | #include "vdso.h" |
21 | 20 | ||
22 | static int perf_session__open(struct perf_session *self, bool force) | 21 | static int perf_session__open(struct perf_session *self, bool force) |
@@ -87,13 +86,12 @@ void perf_session__set_id_hdr_size(struct perf_session *session) | |||
87 | { | 86 | { |
88 | u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist); | 87 | u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist); |
89 | 88 | ||
90 | session->host_machine.id_hdr_size = id_hdr_size; | ||
91 | machines__set_id_hdr_size(&session->machines, id_hdr_size); | 89 | machines__set_id_hdr_size(&session->machines, id_hdr_size); |
92 | } | 90 | } |
93 | 91 | ||
94 | int perf_session__create_kernel_maps(struct perf_session *self) | 92 | int perf_session__create_kernel_maps(struct perf_session *self) |
95 | { | 93 | { |
96 | int ret = machine__create_kernel_maps(&self->host_machine); | 94 | int ret = machine__create_kernel_maps(&self->machines.host); |
97 | 95 | ||
98 | if (ret >= 0) | 96 | if (ret >= 0) |
99 | ret = machines__create_guest_kernel_maps(&self->machines); | 97 | ret = machines__create_guest_kernel_maps(&self->machines); |
@@ -102,8 +100,7 @@ int perf_session__create_kernel_maps(struct perf_session *self) | |||
102 | 100 | ||
103 | static void perf_session__destroy_kernel_maps(struct perf_session *self) | 101 | static void perf_session__destroy_kernel_maps(struct perf_session *self) |
104 | { | 102 | { |
105 | machine__destroy_kernel_maps(&self->host_machine); | 103 | machines__destroy_kernel_maps(&self->machines); |
106 | machines__destroy_guest_kernel_maps(&self->machines); | ||
107 | } | 104 | } |
108 | 105 | ||
109 | struct perf_session *perf_session__new(const char *filename, int mode, | 106 | struct perf_session *perf_session__new(const char *filename, int mode, |
@@ -128,22 +125,11 @@ struct perf_session *perf_session__new(const char *filename, int mode, | |||
128 | goto out; | 125 | goto out; |
129 | 126 | ||
130 | memcpy(self->filename, filename, len); | 127 | memcpy(self->filename, filename, len); |
131 | /* | ||
132 | * On 64bit we can mmap the data file in one go. No need for tiny mmap | ||
133 | * slices. On 32bit we use 32MB. | ||
134 | */ | ||
135 | #if BITS_PER_LONG == 64 | ||
136 | self->mmap_window = ULLONG_MAX; | ||
137 | #else | ||
138 | self->mmap_window = 32 * 1024 * 1024ULL; | ||
139 | #endif | ||
140 | self->machines = RB_ROOT; | ||
141 | self->repipe = repipe; | 128 | self->repipe = repipe; |
142 | INIT_LIST_HEAD(&self->ordered_samples.samples); | 129 | INIT_LIST_HEAD(&self->ordered_samples.samples); |
143 | INIT_LIST_HEAD(&self->ordered_samples.sample_cache); | 130 | INIT_LIST_HEAD(&self->ordered_samples.sample_cache); |
144 | INIT_LIST_HEAD(&self->ordered_samples.to_free); | 131 | INIT_LIST_HEAD(&self->ordered_samples.to_free); |
145 | machine__init(&self->host_machine, "", HOST_KERNEL_ID); | 132 | machines__init(&self->machines); |
146 | hists__init(&self->hists); | ||
147 | 133 | ||
148 | if (mode == O_RDONLY) { | 134 | if (mode == O_RDONLY) { |
149 | if (perf_session__open(self, force) < 0) | 135 | if (perf_session__open(self, force) < 0) |
@@ -171,37 +157,30 @@ out_delete: | |||
171 | return NULL; | 157 | return NULL; |
172 | } | 158 | } |
173 | 159 | ||
174 | static void machine__delete_dead_threads(struct machine *machine) | ||
175 | { | ||
176 | struct thread *n, *t; | ||
177 | |||
178 | list_for_each_entry_safe(t, n, &machine->dead_threads, node) { | ||
179 | list_del(&t->node); | ||
180 | thread__delete(t); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void perf_session__delete_dead_threads(struct perf_session *session) | 160 | static void perf_session__delete_dead_threads(struct perf_session *session) |
185 | { | 161 | { |
186 | machine__delete_dead_threads(&session->host_machine); | 162 | machine__delete_dead_threads(&session->machines.host); |
187 | } | 163 | } |
188 | 164 | ||
189 | static void machine__delete_threads(struct machine *self) | 165 | static void perf_session__delete_threads(struct perf_session *session) |
190 | { | 166 | { |
191 | struct rb_node *nd = rb_first(&self->threads); | 167 | machine__delete_threads(&session->machines.host); |
192 | |||
193 | while (nd) { | ||
194 | struct thread *t = rb_entry(nd, struct thread, rb_node); | ||
195 | |||
196 | rb_erase(&t->rb_node, &self->threads); | ||
197 | nd = rb_next(nd); | ||
198 | thread__delete(t); | ||
199 | } | ||
200 | } | 168 | } |
201 | 169 | ||
202 | static void perf_session__delete_threads(struct perf_session *session) | 170 | static void perf_session_env__delete(struct perf_session_env *env) |
203 | { | 171 | { |
204 | machine__delete_threads(&session->host_machine); | 172 | free(env->hostname); |
173 | free(env->os_release); | ||
174 | free(env->version); | ||
175 | free(env->arch); | ||
176 | free(env->cpu_desc); | ||
177 | free(env->cpuid); | ||
178 | |||
179 | free(env->cmdline); | ||
180 | free(env->sibling_cores); | ||
181 | free(env->sibling_threads); | ||
182 | free(env->numa_nodes); | ||
183 | free(env->pmu_mappings); | ||
205 | } | 184 | } |
206 | 185 | ||
207 | void perf_session__delete(struct perf_session *self) | 186 | void perf_session__delete(struct perf_session *self) |
@@ -209,198 +188,13 @@ void perf_session__delete(struct perf_session *self) | |||
209 | perf_session__destroy_kernel_maps(self); | 188 | perf_session__destroy_kernel_maps(self); |
210 | perf_session__delete_dead_threads(self); | 189 | perf_session__delete_dead_threads(self); |
211 | perf_session__delete_threads(self); | 190 | perf_session__delete_threads(self); |
212 | machine__exit(&self->host_machine); | 191 | perf_session_env__delete(&self->header.env); |
192 | machines__exit(&self->machines); | ||
213 | close(self->fd); | 193 | close(self->fd); |
214 | free(self); | 194 | free(self); |
215 | vdso__exit(); | 195 | vdso__exit(); |
216 | } | 196 | } |
217 | 197 | ||
218 | void machine__remove_thread(struct machine *self, struct thread *th) | ||
219 | { | ||
220 | self->last_match = NULL; | ||
221 | rb_erase(&th->rb_node, &self->threads); | ||
222 | /* | ||
223 | * We may have references to this thread, for instance in some hist_entry | ||
224 | * instances, so just move them to a separate list. | ||
225 | */ | ||
226 | list_add_tail(&th->node, &self->dead_threads); | ||
227 | } | ||
228 | |||
229 | static bool symbol__match_parent_regex(struct symbol *sym) | ||
230 | { | ||
231 | if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) | ||
232 | return 1; | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static const u8 cpumodes[] = { | ||
238 | PERF_RECORD_MISC_USER, | ||
239 | PERF_RECORD_MISC_KERNEL, | ||
240 | PERF_RECORD_MISC_GUEST_USER, | ||
241 | PERF_RECORD_MISC_GUEST_KERNEL | ||
242 | }; | ||
243 | #define NCPUMODES (sizeof(cpumodes)/sizeof(u8)) | ||
244 | |||
245 | static void ip__resolve_ams(struct machine *self, struct thread *thread, | ||
246 | struct addr_map_symbol *ams, | ||
247 | u64 ip) | ||
248 | { | ||
249 | struct addr_location al; | ||
250 | size_t i; | ||
251 | u8 m; | ||
252 | |||
253 | memset(&al, 0, sizeof(al)); | ||
254 | |||
255 | for (i = 0; i < NCPUMODES; i++) { | ||
256 | m = cpumodes[i]; | ||
257 | /* | ||
258 | * We cannot use the header.misc hint to determine whether a | ||
259 | * branch stack address is user, kernel, guest, hypervisor. | ||
260 | * Branches may straddle the kernel/user/hypervisor boundaries. | ||
261 | * Thus, we have to try consecutively until we find a match | ||
262 | * or else, the symbol is unknown | ||
263 | */ | ||
264 | thread__find_addr_location(thread, self, m, MAP__FUNCTION, | ||
265 | ip, &al, NULL); | ||
266 | if (al.sym) | ||
267 | goto found; | ||
268 | } | ||
269 | found: | ||
270 | ams->addr = ip; | ||
271 | ams->al_addr = al.addr; | ||
272 | ams->sym = al.sym; | ||
273 | ams->map = al.map; | ||
274 | } | ||
275 | |||
276 | struct branch_info *machine__resolve_bstack(struct machine *self, | ||
277 | struct thread *thr, | ||
278 | struct branch_stack *bs) | ||
279 | { | ||
280 | struct branch_info *bi; | ||
281 | unsigned int i; | ||
282 | |||
283 | bi = calloc(bs->nr, sizeof(struct branch_info)); | ||
284 | if (!bi) | ||
285 | return NULL; | ||
286 | |||
287 | for (i = 0; i < bs->nr; i++) { | ||
288 | ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to); | ||
289 | ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from); | ||
290 | bi[i].flags = bs->entries[i].flags; | ||
291 | } | ||
292 | return bi; | ||
293 | } | ||
294 | |||
295 | static int machine__resolve_callchain_sample(struct machine *machine, | ||
296 | struct thread *thread, | ||
297 | struct ip_callchain *chain, | ||
298 | struct symbol **parent) | ||
299 | |||
300 | { | ||
301 | u8 cpumode = PERF_RECORD_MISC_USER; | ||
302 | unsigned int i; | ||
303 | int err; | ||
304 | |||
305 | callchain_cursor_reset(&callchain_cursor); | ||
306 | |||
307 | if (chain->nr > PERF_MAX_STACK_DEPTH) { | ||
308 | pr_warning("corrupted callchain. skipping...\n"); | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | for (i = 0; i < chain->nr; i++) { | ||
313 | u64 ip; | ||
314 | struct addr_location al; | ||
315 | |||
316 | if (callchain_param.order == ORDER_CALLEE) | ||
317 | ip = chain->ips[i]; | ||
318 | else | ||
319 | ip = chain->ips[chain->nr - i - 1]; | ||
320 | |||
321 | if (ip >= PERF_CONTEXT_MAX) { | ||
322 | switch (ip) { | ||
323 | case PERF_CONTEXT_HV: | ||
324 | cpumode = PERF_RECORD_MISC_HYPERVISOR; | ||
325 | break; | ||
326 | case PERF_CONTEXT_KERNEL: | ||
327 | cpumode = PERF_RECORD_MISC_KERNEL; | ||
328 | break; | ||
329 | case PERF_CONTEXT_USER: | ||
330 | cpumode = PERF_RECORD_MISC_USER; | ||
331 | break; | ||
332 | default: | ||
333 | pr_debug("invalid callchain context: " | ||
334 | "%"PRId64"\n", (s64) ip); | ||
335 | /* | ||
336 | * It seems the callchain is corrupted. | ||
337 | * Discard all. | ||
338 | */ | ||
339 | callchain_cursor_reset(&callchain_cursor); | ||
340 | return 0; | ||
341 | } | ||
342 | continue; | ||
343 | } | ||
344 | |||
345 | al.filtered = false; | ||
346 | thread__find_addr_location(thread, machine, cpumode, | ||
347 | MAP__FUNCTION, ip, &al, NULL); | ||
348 | if (al.sym != NULL) { | ||
349 | if (sort__has_parent && !*parent && | ||
350 | symbol__match_parent_regex(al.sym)) | ||
351 | *parent = al.sym; | ||
352 | if (!symbol_conf.use_callchain) | ||
353 | break; | ||
354 | } | ||
355 | |||
356 | err = callchain_cursor_append(&callchain_cursor, | ||
357 | ip, al.map, al.sym); | ||
358 | if (err) | ||
359 | return err; | ||
360 | } | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int unwind_entry(struct unwind_entry *entry, void *arg) | ||
366 | { | ||
367 | struct callchain_cursor *cursor = arg; | ||
368 | return callchain_cursor_append(cursor, entry->ip, | ||
369 | entry->map, entry->sym); | ||
370 | } | ||
371 | |||
372 | int machine__resolve_callchain(struct machine *machine, | ||
373 | struct perf_evsel *evsel, | ||
374 | struct thread *thread, | ||
375 | struct perf_sample *sample, | ||
376 | struct symbol **parent) | ||
377 | |||
378 | { | ||
379 | int ret; | ||
380 | |||
381 | callchain_cursor_reset(&callchain_cursor); | ||
382 | |||
383 | ret = machine__resolve_callchain_sample(machine, thread, | ||
384 | sample->callchain, parent); | ||
385 | if (ret) | ||
386 | return ret; | ||
387 | |||
388 | /* Can we do dwarf post unwind? */ | ||
389 | if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) && | ||
390 | (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) | ||
391 | return 0; | ||
392 | |||
393 | /* Bail out if nothing was captured. */ | ||
394 | if ((!sample->user_regs.regs) || | ||
395 | (!sample->user_stack.size)) | ||
396 | return 0; | ||
397 | |||
398 | return unwind__get_entries(unwind_entry, &callchain_cursor, machine, | ||
399 | thread, evsel->attr.sample_regs_user, | ||
400 | sample); | ||
401 | |||
402 | } | ||
403 | |||
404 | static int process_event_synth_tracing_data_stub(union perf_event *event | 198 | static int process_event_synth_tracing_data_stub(union perf_event *event |
405 | __maybe_unused, | 199 | __maybe_unused, |
406 | struct perf_session *session | 200 | struct perf_session *session |
@@ -1027,7 +821,7 @@ static struct machine * | |||
1027 | return perf_session__findnew_machine(session, pid); | 821 | return perf_session__findnew_machine(session, pid); |
1028 | } | 822 | } |
1029 | 823 | ||
1030 | return perf_session__find_host_machine(session); | 824 | return &session->machines.host; |
1031 | } | 825 | } |
1032 | 826 | ||
1033 | static int perf_session_deliver_event(struct perf_session *session, | 827 | static int perf_session_deliver_event(struct perf_session *session, |
@@ -1065,11 +859,11 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
1065 | case PERF_RECORD_SAMPLE: | 859 | case PERF_RECORD_SAMPLE: |
1066 | dump_sample(evsel, event, sample); | 860 | dump_sample(evsel, event, sample); |
1067 | if (evsel == NULL) { | 861 | if (evsel == NULL) { |
1068 | ++session->hists.stats.nr_unknown_id; | 862 | ++session->stats.nr_unknown_id; |
1069 | return 0; | 863 | return 0; |
1070 | } | 864 | } |
1071 | if (machine == NULL) { | 865 | if (machine == NULL) { |
1072 | ++session->hists.stats.nr_unprocessable_samples; | 866 | ++session->stats.nr_unprocessable_samples; |
1073 | return 0; | 867 | return 0; |
1074 | } | 868 | } |
1075 | return tool->sample(tool, event, sample, evsel, machine); | 869 | return tool->sample(tool, event, sample, evsel, machine); |
@@ -1083,7 +877,7 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
1083 | return tool->exit(tool, event, sample, machine); | 877 | return tool->exit(tool, event, sample, machine); |
1084 | case PERF_RECORD_LOST: | 878 | case PERF_RECORD_LOST: |
1085 | if (tool->lost == perf_event__process_lost) | 879 | if (tool->lost == perf_event__process_lost) |
1086 | session->hists.stats.total_lost += event->lost.lost; | 880 | session->stats.total_lost += event->lost.lost; |
1087 | return tool->lost(tool, event, sample, machine); | 881 | return tool->lost(tool, event, sample, machine); |
1088 | case PERF_RECORD_READ: | 882 | case PERF_RECORD_READ: |
1089 | return tool->read(tool, event, sample, evsel, machine); | 883 | return tool->read(tool, event, sample, evsel, machine); |
@@ -1092,7 +886,7 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
1092 | case PERF_RECORD_UNTHROTTLE: | 886 | case PERF_RECORD_UNTHROTTLE: |
1093 | return tool->unthrottle(tool, event, sample, machine); | 887 | return tool->unthrottle(tool, event, sample, machine); |
1094 | default: | 888 | default: |
1095 | ++session->hists.stats.nr_unknown_events; | 889 | ++session->stats.nr_unknown_events; |
1096 | return -1; | 890 | return -1; |
1097 | } | 891 | } |
1098 | } | 892 | } |
@@ -1106,8 +900,8 @@ static int perf_session__preprocess_sample(struct perf_session *session, | |||
1106 | 900 | ||
1107 | if (!ip_callchain__valid(sample->callchain, event)) { | 901 | if (!ip_callchain__valid(sample->callchain, event)) { |
1108 | pr_debug("call-chain problem with event, skipping it.\n"); | 902 | pr_debug("call-chain problem with event, skipping it.\n"); |
1109 | ++session->hists.stats.nr_invalid_chains; | 903 | ++session->stats.nr_invalid_chains; |
1110 | session->hists.stats.total_invalid_chains += sample->period; | 904 | session->stats.total_invalid_chains += sample->period; |
1111 | return -EINVAL; | 905 | return -EINVAL; |
1112 | } | 906 | } |
1113 | return 0; | 907 | return 0; |
@@ -1165,7 +959,7 @@ static int perf_session__process_event(struct perf_session *session, | |||
1165 | if (event->header.type >= PERF_RECORD_HEADER_MAX) | 959 | if (event->header.type >= PERF_RECORD_HEADER_MAX) |
1166 | return -EINVAL; | 960 | return -EINVAL; |
1167 | 961 | ||
1168 | hists__inc_nr_events(&session->hists, event->header.type); | 962 | events_stats__inc(&session->stats, event->header.type); |
1169 | 963 | ||
1170 | if (event->header.type >= PERF_RECORD_USER_TYPE_START) | 964 | if (event->header.type >= PERF_RECORD_USER_TYPE_START) |
1171 | return perf_session__process_user_event(session, event, tool, file_offset); | 965 | return perf_session__process_user_event(session, event, tool, file_offset); |
@@ -1201,7 +995,7 @@ void perf_event_header__bswap(struct perf_event_header *self) | |||
1201 | 995 | ||
1202 | struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) | 996 | struct thread *perf_session__findnew(struct perf_session *session, pid_t pid) |
1203 | { | 997 | { |
1204 | return machine__findnew_thread(&session->host_machine, pid); | 998 | return machine__findnew_thread(&session->machines.host, pid); |
1205 | } | 999 | } |
1206 | 1000 | ||
1207 | static struct thread *perf_session__register_idle_thread(struct perf_session *self) | 1001 | static struct thread *perf_session__register_idle_thread(struct perf_session *self) |
@@ -1220,39 +1014,39 @@ static void perf_session__warn_about_errors(const struct perf_session *session, | |||
1220 | const struct perf_tool *tool) | 1014 | const struct perf_tool *tool) |
1221 | { | 1015 | { |
1222 | if (tool->lost == perf_event__process_lost && | 1016 | if (tool->lost == perf_event__process_lost && |
1223 | session->hists.stats.nr_events[PERF_RECORD_LOST] != 0) { | 1017 | session->stats.nr_events[PERF_RECORD_LOST] != 0) { |
1224 | ui__warning("Processed %d events and lost %d chunks!\n\n" | 1018 | ui__warning("Processed %d events and lost %d chunks!\n\n" |
1225 | "Check IO/CPU overload!\n\n", | 1019 | "Check IO/CPU overload!\n\n", |
1226 | session->hists.stats.nr_events[0], | 1020 | session->stats.nr_events[0], |
1227 | session->hists.stats.nr_events[PERF_RECORD_LOST]); | 1021 | session->stats.nr_events[PERF_RECORD_LOST]); |
1228 | } | 1022 | } |
1229 | 1023 | ||
1230 | if (session->hists.stats.nr_unknown_events != 0) { | 1024 | if (session->stats.nr_unknown_events != 0) { |
1231 | ui__warning("Found %u unknown events!\n\n" | 1025 | ui__warning("Found %u unknown events!\n\n" |
1232 | "Is this an older tool processing a perf.data " | 1026 | "Is this an older tool processing a perf.data " |
1233 | "file generated by a more recent tool?\n\n" | 1027 | "file generated by a more recent tool?\n\n" |
1234 | "If that is not the case, consider " | 1028 | "If that is not the case, consider " |
1235 | "reporting to linux-kernel@vger.kernel.org.\n\n", | 1029 | "reporting to linux-kernel@vger.kernel.org.\n\n", |
1236 | session->hists.stats.nr_unknown_events); | 1030 | session->stats.nr_unknown_events); |
1237 | } | 1031 | } |
1238 | 1032 | ||
1239 | if (session->hists.stats.nr_unknown_id != 0) { | 1033 | if (session->stats.nr_unknown_id != 0) { |
1240 | ui__warning("%u samples with id not present in the header\n", | 1034 | ui__warning("%u samples with id not present in the header\n", |
1241 | session->hists.stats.nr_unknown_id); | 1035 | session->stats.nr_unknown_id); |
1242 | } | 1036 | } |
1243 | 1037 | ||
1244 | if (session->hists.stats.nr_invalid_chains != 0) { | 1038 | if (session->stats.nr_invalid_chains != 0) { |
1245 | ui__warning("Found invalid callchains!\n\n" | 1039 | ui__warning("Found invalid callchains!\n\n" |
1246 | "%u out of %u events were discarded for this reason.\n\n" | 1040 | "%u out of %u events were discarded for this reason.\n\n" |
1247 | "Consider reporting to linux-kernel@vger.kernel.org.\n\n", | 1041 | "Consider reporting to linux-kernel@vger.kernel.org.\n\n", |
1248 | session->hists.stats.nr_invalid_chains, | 1042 | session->stats.nr_invalid_chains, |
1249 | session->hists.stats.nr_events[PERF_RECORD_SAMPLE]); | 1043 | session->stats.nr_events[PERF_RECORD_SAMPLE]); |
1250 | } | 1044 | } |
1251 | 1045 | ||
1252 | if (session->hists.stats.nr_unprocessable_samples != 0) { | 1046 | if (session->stats.nr_unprocessable_samples != 0) { |
1253 | ui__warning("%u unprocessable samples recorded.\n" | 1047 | ui__warning("%u unprocessable samples recorded.\n" |
1254 | "Do you have a KVM guest running and not using 'perf kvm'?\n", | 1048 | "Do you have a KVM guest running and not using 'perf kvm'?\n", |
1255 | session->hists.stats.nr_unprocessable_samples); | 1049 | session->stats.nr_unprocessable_samples); |
1256 | } | 1050 | } |
1257 | } | 1051 | } |
1258 | 1052 | ||
@@ -1369,6 +1163,18 @@ fetch_mmaped_event(struct perf_session *session, | |||
1369 | return event; | 1163 | return event; |
1370 | } | 1164 | } |
1371 | 1165 | ||
1166 | /* | ||
1167 | * On 64bit we can mmap the data file in one go. No need for tiny mmap | ||
1168 | * slices. On 32bit we use 32MB. | ||
1169 | */ | ||
1170 | #if BITS_PER_LONG == 64 | ||
1171 | #define MMAP_SIZE ULLONG_MAX | ||
1172 | #define NUM_MMAPS 1 | ||
1173 | #else | ||
1174 | #define MMAP_SIZE (32 * 1024 * 1024ULL) | ||
1175 | #define NUM_MMAPS 128 | ||
1176 | #endif | ||
1177 | |||
1372 | int __perf_session__process_events(struct perf_session *session, | 1178 | int __perf_session__process_events(struct perf_session *session, |
1373 | u64 data_offset, u64 data_size, | 1179 | u64 data_offset, u64 data_size, |
1374 | u64 file_size, struct perf_tool *tool) | 1180 | u64 file_size, struct perf_tool *tool) |
@@ -1376,7 +1182,7 @@ int __perf_session__process_events(struct perf_session *session, | |||
1376 | u64 head, page_offset, file_offset, file_pos, progress_next; | 1182 | u64 head, page_offset, file_offset, file_pos, progress_next; |
1377 | int err, mmap_prot, mmap_flags, map_idx = 0; | 1183 | int err, mmap_prot, mmap_flags, map_idx = 0; |
1378 | size_t mmap_size; | 1184 | size_t mmap_size; |
1379 | char *buf, *mmaps[8]; | 1185 | char *buf, *mmaps[NUM_MMAPS]; |
1380 | union perf_event *event; | 1186 | union perf_event *event; |
1381 | uint32_t size; | 1187 | uint32_t size; |
1382 | 1188 | ||
@@ -1391,7 +1197,7 @@ int __perf_session__process_events(struct perf_session *session, | |||
1391 | 1197 | ||
1392 | progress_next = file_size / 16; | 1198 | progress_next = file_size / 16; |
1393 | 1199 | ||
1394 | mmap_size = session->mmap_window; | 1200 | mmap_size = MMAP_SIZE; |
1395 | if (mmap_size > file_size) | 1201 | if (mmap_size > file_size) |
1396 | mmap_size = file_size; | 1202 | mmap_size = file_size; |
1397 | 1203 | ||
@@ -1526,16 +1332,13 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, | |||
1526 | 1332 | ||
1527 | size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) | 1333 | size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp) |
1528 | { | 1334 | { |
1529 | return __dsos__fprintf(&self->host_machine.kernel_dsos, fp) + | 1335 | return machines__fprintf_dsos(&self->machines, fp); |
1530 | __dsos__fprintf(&self->host_machine.user_dsos, fp) + | ||
1531 | machines__fprintf_dsos(&self->machines, fp); | ||
1532 | } | 1336 | } |
1533 | 1337 | ||
1534 | size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, | 1338 | size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp, |
1535 | bool with_hits) | 1339 | bool (skip)(struct dso *dso, int parm), int parm) |
1536 | { | 1340 | { |
1537 | size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits); | 1341 | return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm); |
1538 | return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits); | ||
1539 | } | 1342 | } |
1540 | 1343 | ||
1541 | size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) | 1344 | size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) |
@@ -1543,11 +1346,11 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp) | |||
1543 | struct perf_evsel *pos; | 1346 | struct perf_evsel *pos; |
1544 | size_t ret = fprintf(fp, "Aggregated stats:\n"); | 1347 | size_t ret = fprintf(fp, "Aggregated stats:\n"); |
1545 | 1348 | ||
1546 | ret += hists__fprintf_nr_events(&session->hists, fp); | 1349 | ret += events_stats__fprintf(&session->stats, fp); |
1547 | 1350 | ||
1548 | list_for_each_entry(pos, &session->evlist->entries, node) { | 1351 | list_for_each_entry(pos, &session->evlist->entries, node) { |
1549 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); | 1352 | ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); |
1550 | ret += hists__fprintf_nr_events(&pos->hists, fp); | 1353 | ret += events_stats__fprintf(&pos->hists.stats, fp); |
1551 | } | 1354 | } |
1552 | 1355 | ||
1553 | return ret; | 1356 | return ret; |
@@ -1559,7 +1362,7 @@ size_t perf_session__fprintf(struct perf_session *session, FILE *fp) | |||
1559 | * FIXME: Here we have to actually print all the machines in this | 1362 | * FIXME: Here we have to actually print all the machines in this |
1560 | * session, not just the host... | 1363 | * session, not just the host... |
1561 | */ | 1364 | */ |
1562 | return machine__fprintf(&session->host_machine, fp); | 1365 | return machine__fprintf(&session->machines.host, fp); |
1563 | } | 1366 | } |
1564 | 1367 | ||
1565 | void perf_session__remove_thread(struct perf_session *session, | 1368 | void perf_session__remove_thread(struct perf_session *session, |
@@ -1568,10 +1371,10 @@ void perf_session__remove_thread(struct perf_session *session, | |||
1568 | /* | 1371 | /* |
1569 | * FIXME: This one makes no sense, we need to remove the thread from | 1372 | * FIXME: This one makes no sense, we need to remove the thread from |
1570 | * the machine it belongs to, perf_session can have many machines, so | 1373 | * the machine it belongs to, perf_session can have many machines, so |
1571 | * doing it always on ->host_machine is wrong. Fix when auditing all | 1374 | * doing it always on ->machines.host is wrong. Fix when auditing all |
1572 | * the 'perf kvm' code. | 1375 | * the 'perf kvm' code. |
1573 | */ | 1376 | */ |
1574 | machine__remove_thread(&session->host_machine, th); | 1377 | machine__remove_thread(&session->machines.host, th); |
1575 | } | 1378 | } |
1576 | 1379 | ||
1577 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, | 1380 | struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, |