aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-12-05 08:32:55 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-12-06 12:43:00 -0500
commitcbf41645f35224798cb61641766e6a16e141ffe4 (patch)
treeff7572097138f20921e52a4cce5b693e0314df9d /tools
parente4e18d568b0e833c75c1f7833e1690cdde8f4d76 (diff)
perf session: Sort all events if ordered_samples=true
Now that we have timestamps on FORK, EXIT, COMM, MMAP events we can sort everything in time order. This fixes the following observed problem: mmap(file1) -> pagefault() -> munmap(file1) mmap(file2) -> pagefault() -> munmap(file2) Resulted in decoding both pagefaults in file2 because the file1 map was already replaced by the file2 map when the map address was identical. With all events sorted we decode both pagefaults correctly. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ian Munsie <imunsie@au1.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <alpine.LFD.2.00.1012051220450.2653@localhost6.localdomain6> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/session.c125
1 files changed, 72 insertions, 53 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5c756609104e..3074d38897e6 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -461,6 +461,11 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
461 } 461 }
462} 462}
463 463
464static int perf_session_deliver_event(struct perf_session *session,
465 event_t *event,
466 struct sample_data *sample,
467 struct perf_event_ops *ops);
468
464static void flush_sample_queue(struct perf_session *s, 469static void flush_sample_queue(struct perf_session *s,
465 struct perf_event_ops *ops) 470 struct perf_event_ops *ops)
466{ 471{
@@ -479,7 +484,7 @@ static void flush_sample_queue(struct perf_session *s,
479 break; 484 break;
480 485
481 event__parse_sample(iter->event, s, &sample); 486 event__parse_sample(iter->event, s, &sample);
482 ops->sample(iter->event, &sample, s); 487 perf_session_deliver_event(s, iter->event, &sample, ops);
483 488
484 os->last_flush = iter->timestamp; 489 os->last_flush = iter->timestamp;
485 list_del(&iter->list); 490 list_del(&iter->list);
@@ -544,8 +549,7 @@ static int process_finished_round(event_t *event __used,
544} 549}
545 550
546/* The queue is ordered by time */ 551/* The queue is ordered by time */
547static void __queue_sample_event(struct sample_queue *new, 552static void __queue_event(struct sample_queue *new, struct perf_session *s)
548 struct perf_session *s)
549{ 553{
550 struct ordered_samples *os = &s->ordered_samples; 554 struct ordered_samples *os = &s->ordered_samples;
551 struct sample_queue *sample = os->last_sample; 555 struct sample_queue *sample = os->last_sample;
@@ -591,14 +595,17 @@ static void __queue_sample_event(struct sample_queue *new,
591 595
592#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue)) 596#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
593 597
594static int queue_sample_event(event_t *event, struct sample_data *data, 598static int perf_session_queue_event(struct perf_session *s, event_t *event,
595 struct perf_session *s) 599 struct sample_data *data)
596{ 600{
597 struct ordered_samples *os = &s->ordered_samples; 601 struct ordered_samples *os = &s->ordered_samples;
598 struct list_head *sc = &os->sample_cache; 602 struct list_head *sc = &os->sample_cache;
599 u64 timestamp = data->time; 603 u64 timestamp = data->time;
600 struct sample_queue *new; 604 struct sample_queue *new;
601 605
606 if (!timestamp)
607 return -ETIME;
608
602 if (timestamp < s->ordered_samples.last_flush) { 609 if (timestamp < s->ordered_samples.last_flush) {
603 printf("Warning: Timestamp below last timeslice flush\n"); 610 printf("Warning: Timestamp below last timeslice flush\n");
604 return -EINVAL; 611 return -EINVAL;
@@ -623,20 +630,8 @@ static int queue_sample_event(event_t *event, struct sample_data *data,
623 new->timestamp = timestamp; 630 new->timestamp = timestamp;
624 new->event = event; 631 new->event = event;
625 632
626 __queue_sample_event(new, s); 633 __queue_event(new, s);
627
628 return 0;
629}
630
631static int perf_session__process_sample(event_t *event,
632 struct sample_data *sample,
633 struct perf_session *s,
634 struct perf_event_ops *ops)
635{
636 if (!ops->ordered_samples)
637 return ops->sample(event, sample, s);
638 634
639 queue_sample_event(event, sample, s);
640 return 0; 635 return 0;
641} 636}
642 637
@@ -670,83 +665,107 @@ static void perf_session__print_tstamp(struct perf_session *session,
670 printf("%Lu ", sample->time); 665 printf("%Lu ", sample->time);
671} 666}
672 667
673static int perf_session__process_event(struct perf_session *self, 668static int perf_session_deliver_event(struct perf_session *session,
669 event_t *event,
670 struct sample_data *sample,
671 struct perf_event_ops *ops)
672{
673 switch (event->header.type) {
674 case PERF_RECORD_SAMPLE:
675 return ops->sample(event, sample, session);
676 case PERF_RECORD_MMAP:
677 return ops->mmap(event, sample, session);
678 case PERF_RECORD_COMM:
679 return ops->comm(event, sample, session);
680 case PERF_RECORD_FORK:
681 return ops->fork(event, sample, session);
682 case PERF_RECORD_EXIT:
683 return ops->exit(event, sample, session);
684 case PERF_RECORD_LOST:
685 return ops->lost(event, sample, session);
686 case PERF_RECORD_READ:
687 return ops->read(event, sample, session);
688 case PERF_RECORD_THROTTLE:
689 return ops->throttle(event, sample, session);
690 case PERF_RECORD_UNTHROTTLE:
691 return ops->unthrottle(event, sample, session);
692 default:
693 ++session->hists.stats.nr_unknown_events;
694 return -1;
695 }
696}
697
698static int perf_session__process_event(struct perf_session *session,
674 event_t *event, 699 event_t *event,
675 struct perf_event_ops *ops, 700 struct perf_event_ops *ops,
676 u64 file_offset) 701 u64 file_offset)
677{ 702{
678 struct sample_data sample; 703 struct sample_data sample;
704 int ret;
679 705
680 trace_event(event); 706 trace_event(event);
681 707
682 if (self->header.needs_swap && event__swap_ops[event->header.type]) 708 if (session->header.needs_swap && event__swap_ops[event->header.type])
683 event__swap_ops[event->header.type](event); 709 event__swap_ops[event->header.type](event);
684 710
685 if (event->header.type >= PERF_RECORD_MMAP && 711 if (event->header.type >= PERF_RECORD_MMAP &&
686 event->header.type <= PERF_RECORD_SAMPLE) { 712 event->header.type <= PERF_RECORD_SAMPLE) {
687 event__parse_sample(event, self, &sample); 713 event__parse_sample(event, session, &sample);
688 if (dump_trace) 714 if (dump_trace)
689 perf_session__print_tstamp(self, event, &sample); 715 perf_session__print_tstamp(session, event, &sample);
690 } 716 }
691 717
692 if (event->header.type < PERF_RECORD_HEADER_MAX) { 718 if (event->header.type < PERF_RECORD_HEADER_MAX) {
693 dump_printf("%#Lx [%#x]: PERF_RECORD_%s", 719 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
694 file_offset, event->header.size, 720 file_offset, event->header.size,
695 event__name[event->header.type]); 721 event__name[event->header.type]);
696 hists__inc_nr_events(&self->hists, event->header.type); 722 hists__inc_nr_events(&session->hists, event->header.type);
697 } 723 }
698 724
725 /* These events are processed right away */
699 switch (event->header.type) { 726 switch (event->header.type) {
700 case PERF_RECORD_SAMPLE: 727 case PERF_RECORD_SAMPLE:
701 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc, 728 dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n",
729 event->header.misc,
702 sample.pid, sample.tid, sample.ip, sample.period); 730 sample.pid, sample.tid, sample.ip, sample.period);
703 731
704 if (self->sample_type & PERF_SAMPLE_CALLCHAIN) { 732 if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
705 if (!ip_callchain__valid(sample.callchain, event)) { 733 if (!ip_callchain__valid(sample.callchain, event)) {
706 pr_debug("call-chain problem with event, " 734 pr_debug("call-chain problem with event, "
707 "skipping it.\n"); 735 "skipping it.\n");
708 ++self->hists.stats.nr_invalid_chains; 736 ++session->hists.stats.nr_invalid_chains;
709 self->hists.stats.total_invalid_chains += sample.period; 737 session->hists.stats.total_invalid_chains +=
738 sample.period;
710 return 0; 739 return 0;
711 } 740 }
712 741
713 callchain__dump(&sample); 742 callchain__dump(&sample);
714 } 743 }
744 break;
715 745
716 return perf_session__process_sample(event, &sample, self, ops);
717
718 case PERF_RECORD_MMAP:
719 return ops->mmap(event, &sample, self);
720 case PERF_RECORD_COMM:
721 return ops->comm(event, &sample, self);
722 case PERF_RECORD_FORK:
723 return ops->fork(event, &sample, self);
724 case PERF_RECORD_EXIT:
725 return ops->exit(event, &sample, self);
726 case PERF_RECORD_LOST:
727 return ops->lost(event, &sample, self);
728 case PERF_RECORD_READ:
729 return ops->read(event, &sample, self);
730 case PERF_RECORD_THROTTLE:
731 return ops->throttle(event, &sample, self);
732 case PERF_RECORD_UNTHROTTLE:
733 return ops->unthrottle(event, &sample, self);
734 case PERF_RECORD_HEADER_ATTR: 746 case PERF_RECORD_HEADER_ATTR:
735 return ops->attr(event, self); 747 return ops->attr(event, session);
736 case PERF_RECORD_HEADER_EVENT_TYPE: 748 case PERF_RECORD_HEADER_EVENT_TYPE:
737 return ops->event_type(event, self); 749 return ops->event_type(event, session);
738 case PERF_RECORD_HEADER_TRACING_DATA: 750 case PERF_RECORD_HEADER_TRACING_DATA:
739 /* setup for reading amidst mmap */ 751 /* setup for reading amidst mmap */
740 lseek(self->fd, file_offset, SEEK_SET); 752 lseek(session->fd, file_offset, SEEK_SET);
741 return ops->tracing_data(event, self); 753 return ops->tracing_data(event, session);
742 case PERF_RECORD_HEADER_BUILD_ID: 754 case PERF_RECORD_HEADER_BUILD_ID:
743 return ops->build_id(event, self); 755 return ops->build_id(event, session);
744 case PERF_RECORD_FINISHED_ROUND: 756 case PERF_RECORD_FINISHED_ROUND:
745 return ops->finished_round(event, self, ops); 757 return ops->finished_round(event, session, ops);
746 default: 758 default:
747 ++self->hists.stats.nr_unknown_events; 759 break;
748 return -1;
749 } 760 }
761
762 if (ops->ordered_samples) {
763 ret = perf_session_queue_event(session, event, &sample);
764 if (ret != -ETIME)
765 return ret;
766 }
767
768 return perf_session_deliver_event(session, event, &sample, ops);
750} 769}
751 770
752void perf_event_header__bswap(struct perf_event_header *self) 771void perf_event_header__bswap(struct perf_event_header *self)