aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-12-02 11:10:21 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-12-04 20:05:19 -0500
commit640c03ce837fe8d4b56342aba376ea0da3960459 (patch)
treee954290ccacf032ab4d9052eac01710fda1b7fab /tools/perf/util/session.c
parentc980d1091810df13f21aabbce545fd98f545bbf7 (diff)
perf session: Parse sample earlier
At perf_session__process_event, so that we reduce the number of lines in eache tool sample processing routine that now receives a sample_data pointer already parsed. This will also be useful in the next patch, where we'll allow sample the identity fields in MMAP, FORK, EXIT, etc, when it will be possible to see (cpu, timestamp) just after before every event. Also validate callchains in perf_session__process_event, i.e. as early as possible, and keep a counter of the number of events discarded due to invalid callchains, warning the user about it if it happens. There is an assumption that was kept that all events have the same sample_type, that will be dealt with in the future, when this preexisting limitation will be removed. Tested-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Ian Munsie <imunsie@au1.ibm.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <1291318772-30880-4-git-send-email-acme@infradead.org> 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.c103
1 files changed, 78 insertions, 25 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 52672dad1fe9..08ec018966a8 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -70,6 +70,11 @@ void perf_session__update_sample_type(struct perf_session *self)
70 self->sample_type = perf_header__sample_type(&self->header); 70 self->sample_type = perf_header__sample_type(&self->header);
71} 71}
72 72
73void perf_session__set_sample_type(struct perf_session *session, u64 type)
74{
75 session->sample_type = type;
76}
77
73int perf_session__create_kernel_maps(struct perf_session *self) 78int perf_session__create_kernel_maps(struct perf_session *self)
74{ 79{
75 int ret = machine__create_kernel_maps(&self->host_machine); 80 int ret = machine__create_kernel_maps(&self->host_machine);
@@ -240,7 +245,15 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
240 return syms; 245 return syms;
241} 246}
242 247
248static int process_event_synth_stub(event_t *event __used,
249 struct perf_session *session __used)
250{
251 dump_printf(": unhandled!\n");
252 return 0;
253}
254
243static int process_event_stub(event_t *event __used, 255static int process_event_stub(event_t *event __used,
256 struct sample_data *sample __used,
244 struct perf_session *session __used) 257 struct perf_session *session __used)
245{ 258{
246 dump_printf(": unhandled!\n"); 259 dump_printf(": unhandled!\n");
@@ -280,13 +293,13 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
280 if (handler->unthrottle == NULL) 293 if (handler->unthrottle == NULL)
281 handler->unthrottle = process_event_stub; 294 handler->unthrottle = process_event_stub;
282 if (handler->attr == NULL) 295 if (handler->attr == NULL)
283 handler->attr = process_event_stub; 296 handler->attr = process_event_synth_stub;
284 if (handler->event_type == NULL) 297 if (handler->event_type == NULL)
285 handler->event_type = process_event_stub; 298 handler->event_type = process_event_synth_stub;
286 if (handler->tracing_data == NULL) 299 if (handler->tracing_data == NULL)
287 handler->tracing_data = process_event_stub; 300 handler->tracing_data = process_event_synth_stub;
288 if (handler->build_id == NULL) 301 if (handler->build_id == NULL)
289 handler->build_id = process_event_stub; 302 handler->build_id = process_event_synth_stub;
290 if (handler->finished_round == NULL) { 303 if (handler->finished_round == NULL) {
291 if (handler->ordered_samples) 304 if (handler->ordered_samples)
292 handler->finished_round = process_finished_round; 305 handler->finished_round = process_finished_round;
@@ -419,6 +432,7 @@ static void flush_sample_queue(struct perf_session *s,
419 struct ordered_samples *os = &s->ordered_samples; 432 struct ordered_samples *os = &s->ordered_samples;
420 struct list_head *head = &os->samples; 433 struct list_head *head = &os->samples;
421 struct sample_queue *tmp, *iter; 434 struct sample_queue *tmp, *iter;
435 struct sample_data sample;
422 u64 limit = os->next_flush; 436 u64 limit = os->next_flush;
423 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; 437 u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
424 438
@@ -429,7 +443,8 @@ static void flush_sample_queue(struct perf_session *s,
429 if (iter->timestamp > limit) 443 if (iter->timestamp > limit)
430 break; 444 break;
431 445
432 ops->sample(iter->event, s); 446 event__parse_sample(iter->event, s->sample_type, &sample);
447 ops->sample(iter->event, &sample, s);
433 448
434 os->last_flush = iter->timestamp; 449 os->last_flush = iter->timestamp;
435 list_del(&iter->list); 450 list_del(&iter->list);
@@ -578,20 +593,29 @@ static int queue_sample_event(event_t *event, struct sample_data *data,
578 return 0; 593 return 0;
579} 594}
580 595
581static int perf_session__process_sample(event_t *event, struct perf_session *s, 596static int perf_session__process_sample(event_t *event,
597 struct sample_data *sample,
598 struct perf_session *s,
582 struct perf_event_ops *ops) 599 struct perf_event_ops *ops)
583{ 600{
584 struct sample_data data;
585
586 if (!ops->ordered_samples) 601 if (!ops->ordered_samples)
587 return ops->sample(event, s); 602 return ops->sample(event, sample, s);
603
604 queue_sample_event(event, sample, s);
605 return 0;
606}
588 607
589 bzero(&data, sizeof(struct sample_data)); 608static void callchain__dump(struct sample_data *sample)
590 event__parse_sample(event, s->sample_type, &data); 609{
610 unsigned int i;
591 611
592 queue_sample_event(event, &data, s); 612 if (!dump_trace)
613 return;
593 614
594 return 0; 615 printf("... chain: nr:%Lu\n", sample->callchain->nr);
616
617 for (i = 0; i < sample->callchain->nr; i++)
618 printf("..... %2d: %016Lx\n", i, sample->callchain->ips[i]);
595} 619}
596 620
597static int perf_session__process_event(struct perf_session *self, 621static int perf_session__process_event(struct perf_session *self,
@@ -599,8 +623,16 @@ static int perf_session__process_event(struct perf_session *self,
599 struct perf_event_ops *ops, 623 struct perf_event_ops *ops,
600 u64 file_offset) 624 u64 file_offset)
601{ 625{
626 struct sample_data sample;
627
602 trace_event(event); 628 trace_event(event);
603 629
630 if (self->header.needs_swap && event__swap_ops[event->header.type])
631 event__swap_ops[event->header.type](event);
632
633 if (event->header.type == PERF_RECORD_SAMPLE)
634 event__parse_sample(event, self->sample_type, &sample);
635
604 if (event->header.type < PERF_RECORD_HEADER_MAX) { 636 if (event->header.type < PERF_RECORD_HEADER_MAX) {
605 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 637 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
606 file_offset, event->header.size, 638 file_offset, event->header.size,
@@ -608,28 +640,41 @@ static int perf_session__process_event(struct perf_session *self,
608 hists__inc_nr_events(&self->hists, event->header.type); 640 hists__inc_nr_events(&self->hists, event->header.type);
609 } 641 }
610 642
611 if (self->header.needs_swap && event__swap_ops[event->header.type])
612 event__swap_ops[event->header.type](event);
613
614 switch (event->header.type) { 643 switch (event->header.type) {
615 case PERF_RECORD_SAMPLE: 644 case PERF_RECORD_SAMPLE:
616 return perf_session__process_sample(event, self, ops); 645 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
646 sample.pid, sample.tid, sample.ip, sample.period);
647
648 if (self->sample_type & PERF_SAMPLE_CALLCHAIN) {
649 if (!ip_callchain__valid(sample.callchain, event)) {
650 pr_debug("call-chain problem with event, "
651 "skipping it.\n");
652 ++self->hists.stats.nr_invalid_chains;
653 self->hists.stats.total_invalid_chains += sample.period;
654 return 0;
655 }
656
657 callchain__dump(&sample);
658 }
659
660 return perf_session__process_sample(event, &sample, self, ops);
661
617 case PERF_RECORD_MMAP: 662 case PERF_RECORD_MMAP:
618 return ops->mmap(event, self); 663 return ops->mmap(event, &sample, self);
619 case PERF_RECORD_COMM: 664 case PERF_RECORD_COMM:
620 return ops->comm(event, self); 665 return ops->comm(event, &sample, self);
621 case PERF_RECORD_FORK: 666 case PERF_RECORD_FORK:
622 return ops->fork(event, self); 667 return ops->fork(event, &sample, self);
623 case PERF_RECORD_EXIT: 668 case PERF_RECORD_EXIT:
624 return ops->exit(event, self); 669 return ops->exit(event, &sample, self);
625 case PERF_RECORD_LOST: 670 case PERF_RECORD_LOST:
626 return ops->lost(event, self); 671 return ops->lost(event, &sample, self);
627 case PERF_RECORD_READ: 672 case PERF_RECORD_READ:
628 return ops->read(event, self); 673 return ops->read(event, &sample, self);
629 case PERF_RECORD_THROTTLE: 674 case PERF_RECORD_THROTTLE:
630 return ops->throttle(event, self); 675 return ops->throttle(event, &sample, self);
631 case PERF_RECORD_UNTHROTTLE: 676 case PERF_RECORD_UNTHROTTLE:
632 return ops->unthrottle(event, self); 677 return ops->unthrottle(event, &sample, self);
633 case PERF_RECORD_HEADER_ATTR: 678 case PERF_RECORD_HEADER_ATTR:
634 return ops->attr(event, self); 679 return ops->attr(event, self);
635 case PERF_RECORD_HEADER_EVENT_TYPE: 680 case PERF_RECORD_HEADER_EVENT_TYPE:
@@ -894,6 +939,14 @@ out_err:
894 session->hists.stats.nr_unknown_events); 939 session->hists.stats.nr_unknown_events);
895 } 940 }
896 941
942 if (session->hists.stats.nr_invalid_chains != 0) {
943 ui__warning("Found invalid callchains!\n\n"
944 "%u out of %u events were discarded for this reason.\n\n"
945 "Consider reporting to linux-kernel@vger.kernel.org.\n\n",
946 session->hists.stats.nr_invalid_chains,
947 session->hists.stats.nr_events[PERF_RECORD_SAMPLE]);
948 }
949
897 perf_session_free_sample_buffers(session); 950 perf_session_free_sample_buffers(session);
898 return err; 951 return err;
899} 952}