diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2009-12-06 06:08:24 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-06 12:15:01 -0500 |
commit | 180f95e29aa8782c019caa64ede2a28d8ab62564 (patch) | |
tree | eefd1631820b00992f4495cc8cdba66a9155ee6c /tools/perf/builtin-report.c | |
parent | 028c515253761084c6594bf9ac9b194b51d87065 (diff) |
perf: Make common SAMPLE_EVENT parser
Currently, sample event data is parsed for each commands, and it
is assuming that the data is not including other data. (E.g.
timechart, trace, etc. can't parse the event if it has
PERF_SAMPLE_CALLCHAIN)
So, even if we record the superset data for multiple commands at
a time, commands can't parse. etc.
To fix it, this makes common sample event parser, and use it to
parse sample event correctly. (PERF_SAMPLE_READ is unsupported
for now though, it seems to be not using.)
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <87hbs48imv.fsf@devron.myhome.or.jp>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r-- | tools/perf/builtin-report.c | 39 |
1 files changed, 18 insertions, 21 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 383c4ab4f9af..2b9eb3a553ed 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -605,44 +605,41 @@ static int validate_chain(struct ip_callchain *chain, event_t *event) | |||
605 | 605 | ||
606 | static int process_sample_event(event_t *event) | 606 | static int process_sample_event(event_t *event) |
607 | { | 607 | { |
608 | u64 ip = event->ip.ip; | 608 | struct sample_data data; |
609 | u64 period = 1; | ||
610 | void *more_data = event->ip.__more_data; | ||
611 | struct ip_callchain *chain = NULL; | ||
612 | int cpumode; | 609 | int cpumode; |
613 | struct addr_location al; | 610 | struct addr_location al; |
614 | struct thread *thread = threads__findnew(event->ip.pid); | 611 | struct thread *thread; |
615 | 612 | ||
616 | if (sample_type & PERF_SAMPLE_PERIOD) { | 613 | memset(&data, 0, sizeof(data)); |
617 | period = *(u64 *)more_data; | 614 | data.period = 1; |
618 | more_data += sizeof(u64); | 615 | |
619 | } | 616 | event__parse_sample(event, sample_type, &data); |
620 | 617 | ||
621 | dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", | 618 | dump_printf("(IP, %d): %d/%d: %p period: %Ld\n", |
622 | event->header.misc, | 619 | event->header.misc, |
623 | event->ip.pid, event->ip.tid, | 620 | data.pid, data.tid, |
624 | (void *)(long)ip, | 621 | (void *)(long)data.ip, |
625 | (long long)period); | 622 | (long long)data.period); |
626 | 623 | ||
627 | if (sample_type & PERF_SAMPLE_CALLCHAIN) { | 624 | if (sample_type & PERF_SAMPLE_CALLCHAIN) { |
628 | unsigned int i; | 625 | unsigned int i; |
629 | 626 | ||
630 | chain = (void *)more_data; | 627 | dump_printf("... chain: nr:%Lu\n", data.callchain->nr); |
631 | |||
632 | dump_printf("... chain: nr:%Lu\n", chain->nr); | ||
633 | 628 | ||
634 | if (validate_chain(chain, event) < 0) { | 629 | if (validate_chain(data.callchain, event) < 0) { |
635 | pr_debug("call-chain problem with event, " | 630 | pr_debug("call-chain problem with event, " |
636 | "skipping it.\n"); | 631 | "skipping it.\n"); |
637 | return 0; | 632 | return 0; |
638 | } | 633 | } |
639 | 634 | ||
640 | if (dump_trace) { | 635 | if (dump_trace) { |
641 | for (i = 0; i < chain->nr; i++) | 636 | for (i = 0; i < data.callchain->nr; i++) |
642 | dump_printf("..... %2d: %016Lx\n", i, chain->ips[i]); | 637 | dump_printf("..... %2d: %016Lx\n", |
638 | i, data.callchain->ips[i]); | ||
643 | } | 639 | } |
644 | } | 640 | } |
645 | 641 | ||
642 | thread = threads__findnew(data.pid); | ||
646 | if (thread == NULL) { | 643 | if (thread == NULL) { |
647 | pr_debug("problem processing %d event, skipping it.\n", | 644 | pr_debug("problem processing %d event, skipping it.\n", |
648 | event->header.type); | 645 | event->header.type); |
@@ -657,7 +654,7 @@ static int process_sample_event(event_t *event) | |||
657 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 654 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
658 | 655 | ||
659 | thread__find_addr_location(thread, cpumode, | 656 | thread__find_addr_location(thread, cpumode, |
660 | MAP__FUNCTION, ip, &al, NULL); | 657 | MAP__FUNCTION, data.ip, &al, NULL); |
661 | /* | 658 | /* |
662 | * We have to do this here as we may have a dso with no symbol hit that | 659 | * We have to do this here as we may have a dso with no symbol hit that |
663 | * has a name longer than the ones with symbols sampled. | 660 | * has a name longer than the ones with symbols sampled. |
@@ -675,12 +672,12 @@ static int process_sample_event(event_t *event) | |||
675 | if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name)) | 672 | if (sym_list && al.sym && !strlist__has_entry(sym_list, al.sym->name)) |
676 | return 0; | 673 | return 0; |
677 | 674 | ||
678 | if (hist_entry__add(&al, chain, period)) { | 675 | if (hist_entry__add(&al, data.callchain, data.period)) { |
679 | pr_debug("problem incrementing symbol count, skipping event\n"); | 676 | pr_debug("problem incrementing symbol count, skipping event\n"); |
680 | return -1; | 677 | return -1; |
681 | } | 678 | } |
682 | 679 | ||
683 | event__stats.total += period; | 680 | event__stats.total += data.period; |
684 | 681 | ||
685 | return 0; | 682 | return 0; |
686 | } | 683 | } |