aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)