aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
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}