diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-10-06 15:26:02 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-10-06 15:34:13 -0400 |
commit | b0a7d1a0cd2e228dc06d099db2e1bb02f1b7d591 (patch) | |
tree | e943d42d36229261829b7c51978ecd1ee649a59a /tools/perf/util/event.c | |
parent | 0439539f72ea222fbfe511b47318b9c1815a7108 (diff) |
perf machine: Carve up event processing specific from perf_tool
The perf_tool vtable expects methods that receive perf_tool and
perf_sample entries, but for tools not interested in doing any special
processing on non PERF_RECORD_SAMPLE events, like 'perf top', and for
those not using perf_session, like 'perf trace', they were using
perf_event__process passing tool and sample paramenters that were just
not used.
Provide 'machine' methods for this purpose and make the perf_event
ones use them.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ot9cc6mt025o8kbngzckcrx9@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r-- | tools/perf/util/event.c | 211 |
1 files changed, 12 insertions, 199 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index eaaee22628ea..0ae444ef1429 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -520,134 +520,15 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused, | |||
520 | struct perf_sample *sample __maybe_unused, | 520 | struct perf_sample *sample __maybe_unused, |
521 | struct machine *machine) | 521 | struct machine *machine) |
522 | { | 522 | { |
523 | struct thread *thread = machine__findnew_thread(machine, event->comm.tid); | 523 | return machine__process_comm_event(machine, event); |
524 | |||
525 | if (dump_trace) | ||
526 | perf_event__fprintf_comm(event, stdout); | ||
527 | |||
528 | if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { | ||
529 | dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n"); | ||
530 | return -1; | ||
531 | } | ||
532 | |||
533 | return 0; | ||
534 | } | 524 | } |
535 | 525 | ||
536 | int perf_event__process_lost(struct perf_tool *tool __maybe_unused, | 526 | int perf_event__process_lost(struct perf_tool *tool __maybe_unused, |
537 | union perf_event *event, | 527 | union perf_event *event, |
538 | struct perf_sample *sample __maybe_unused, | 528 | struct perf_sample *sample __maybe_unused, |
539 | struct machine *machine __maybe_unused) | 529 | struct machine *machine) |
540 | { | ||
541 | dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n", | ||
542 | event->lost.id, event->lost.lost); | ||
543 | return 0; | ||
544 | } | ||
545 | |||
546 | static void perf_event__set_kernel_mmap_len(union perf_event *event, | ||
547 | struct map **maps) | ||
548 | { | ||
549 | maps[MAP__FUNCTION]->start = event->mmap.start; | ||
550 | maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len; | ||
551 | /* | ||
552 | * Be a bit paranoid here, some perf.data file came with | ||
553 | * a zero sized synthesized MMAP event for the kernel. | ||
554 | */ | ||
555 | if (maps[MAP__FUNCTION]->end == 0) | ||
556 | maps[MAP__FUNCTION]->end = ~0ULL; | ||
557 | } | ||
558 | |||
559 | static int perf_event__process_kernel_mmap(struct perf_tool *tool | ||
560 | __maybe_unused, | ||
561 | union perf_event *event, | ||
562 | struct machine *machine) | ||
563 | { | 530 | { |
564 | struct map *map; | 531 | return machine__process_lost_event(machine, event); |
565 | char kmmap_prefix[PATH_MAX]; | ||
566 | enum dso_kernel_type kernel_type; | ||
567 | bool is_kernel_mmap; | ||
568 | |||
569 | machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); | ||
570 | if (machine__is_host(machine)) | ||
571 | kernel_type = DSO_TYPE_KERNEL; | ||
572 | else | ||
573 | kernel_type = DSO_TYPE_GUEST_KERNEL; | ||
574 | |||
575 | is_kernel_mmap = memcmp(event->mmap.filename, | ||
576 | kmmap_prefix, | ||
577 | strlen(kmmap_prefix) - 1) == 0; | ||
578 | if (event->mmap.filename[0] == '/' || | ||
579 | (!is_kernel_mmap && event->mmap.filename[0] == '[')) { | ||
580 | |||
581 | char short_module_name[1024]; | ||
582 | char *name, *dot; | ||
583 | |||
584 | if (event->mmap.filename[0] == '/') { | ||
585 | name = strrchr(event->mmap.filename, '/'); | ||
586 | if (name == NULL) | ||
587 | goto out_problem; | ||
588 | |||
589 | ++name; /* skip / */ | ||
590 | dot = strrchr(name, '.'); | ||
591 | if (dot == NULL) | ||
592 | goto out_problem; | ||
593 | snprintf(short_module_name, sizeof(short_module_name), | ||
594 | "[%.*s]", (int)(dot - name), name); | ||
595 | strxfrchar(short_module_name, '-', '_'); | ||
596 | } else | ||
597 | strcpy(short_module_name, event->mmap.filename); | ||
598 | |||
599 | map = machine__new_module(machine, event->mmap.start, | ||
600 | event->mmap.filename); | ||
601 | if (map == NULL) | ||
602 | goto out_problem; | ||
603 | |||
604 | name = strdup(short_module_name); | ||
605 | if (name == NULL) | ||
606 | goto out_problem; | ||
607 | |||
608 | map->dso->short_name = name; | ||
609 | map->dso->sname_alloc = 1; | ||
610 | map->end = map->start + event->mmap.len; | ||
611 | } else if (is_kernel_mmap) { | ||
612 | const char *symbol_name = (event->mmap.filename + | ||
613 | strlen(kmmap_prefix)); | ||
614 | /* | ||
615 | * Should be there already, from the build-id table in | ||
616 | * the header. | ||
617 | */ | ||
618 | struct dso *kernel = __dsos__findnew(&machine->kernel_dsos, | ||
619 | kmmap_prefix); | ||
620 | if (kernel == NULL) | ||
621 | goto out_problem; | ||
622 | |||
623 | kernel->kernel = kernel_type; | ||
624 | if (__machine__create_kernel_maps(machine, kernel) < 0) | ||
625 | goto out_problem; | ||
626 | |||
627 | perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps); | ||
628 | |||
629 | /* | ||
630 | * Avoid using a zero address (kptr_restrict) for the ref reloc | ||
631 | * symbol. Effectively having zero here means that at record | ||
632 | * time /proc/sys/kernel/kptr_restrict was non zero. | ||
633 | */ | ||
634 | if (event->mmap.pgoff != 0) { | ||
635 | maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, | ||
636 | symbol_name, | ||
637 | event->mmap.pgoff); | ||
638 | } | ||
639 | |||
640 | if (machine__is_default_guest(machine)) { | ||
641 | /* | ||
642 | * preload dso of guest kernel and modules | ||
643 | */ | ||
644 | dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION], | ||
645 | NULL); | ||
646 | } | ||
647 | } | ||
648 | return 0; | ||
649 | out_problem: | ||
650 | return -1; | ||
651 | } | 532 | } |
652 | 533 | ||
653 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) | 534 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) |
@@ -657,43 +538,12 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) | |||
657 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); | 538 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); |
658 | } | 539 | } |
659 | 540 | ||
660 | int perf_event__process_mmap(struct perf_tool *tool, | 541 | int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, |
661 | union perf_event *event, | 542 | union perf_event *event, |
662 | struct perf_sample *sample __maybe_unused, | 543 | struct perf_sample *sample __maybe_unused, |
663 | struct machine *machine) | 544 | struct machine *machine) |
664 | { | 545 | { |
665 | struct thread *thread; | 546 | return machine__process_mmap_event(machine, event); |
666 | struct map *map; | ||
667 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
668 | int ret = 0; | ||
669 | |||
670 | if (dump_trace) | ||
671 | perf_event__fprintf_mmap(event, stdout); | ||
672 | |||
673 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || | ||
674 | cpumode == PERF_RECORD_MISC_KERNEL) { | ||
675 | ret = perf_event__process_kernel_mmap(tool, event, machine); | ||
676 | if (ret < 0) | ||
677 | goto out_problem; | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | thread = machine__findnew_thread(machine, event->mmap.pid); | ||
682 | if (thread == NULL) | ||
683 | goto out_problem; | ||
684 | map = map__new(&machine->user_dsos, event->mmap.start, | ||
685 | event->mmap.len, event->mmap.pgoff, | ||
686 | event->mmap.pid, event->mmap.filename, | ||
687 | MAP__FUNCTION); | ||
688 | if (map == NULL) | ||
689 | goto out_problem; | ||
690 | |||
691 | thread__insert_map(thread, map); | ||
692 | return 0; | ||
693 | |||
694 | out_problem: | ||
695 | dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); | ||
696 | return 0; | ||
697 | } | 547 | } |
698 | 548 | ||
699 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) | 549 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) |
@@ -708,19 +558,7 @@ int perf_event__process_fork(struct perf_tool *tool __maybe_unused, | |||
708 | struct perf_sample *sample __maybe_unused, | 558 | struct perf_sample *sample __maybe_unused, |
709 | struct machine *machine) | 559 | struct machine *machine) |
710 | { | 560 | { |
711 | struct thread *thread = machine__findnew_thread(machine, event->fork.tid); | 561 | return machine__process_fork_event(machine, event); |
712 | struct thread *parent = machine__findnew_thread(machine, event->fork.ptid); | ||
713 | |||
714 | if (dump_trace) | ||
715 | perf_event__fprintf_task(event, stdout); | ||
716 | |||
717 | if (thread == NULL || parent == NULL || | ||
718 | thread__fork(thread, parent) < 0) { | ||
719 | dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n"); | ||
720 | return -1; | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | } | 562 | } |
725 | 563 | ||
726 | int perf_event__process_exit(struct perf_tool *tool __maybe_unused, | 564 | int perf_event__process_exit(struct perf_tool *tool __maybe_unused, |
@@ -728,15 +566,7 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused, | |||
728 | struct perf_sample *sample __maybe_unused, | 566 | struct perf_sample *sample __maybe_unused, |
729 | struct machine *machine) | 567 | struct machine *machine) |
730 | { | 568 | { |
731 | struct thread *thread = machine__find_thread(machine, event->fork.tid); | 569 | return machine__process_exit_event(machine, event); |
732 | |||
733 | if (dump_trace) | ||
734 | perf_event__fprintf_task(event, stdout); | ||
735 | |||
736 | if (thread != NULL) | ||
737 | machine__remove_thread(machine, thread); | ||
738 | |||
739 | return 0; | ||
740 | } | 570 | } |
741 | 571 | ||
742 | size_t perf_event__fprintf(union perf_event *event, FILE *fp) | 572 | size_t perf_event__fprintf(union perf_event *event, FILE *fp) |
@@ -762,29 +592,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp) | |||
762 | return ret; | 592 | return ret; |
763 | } | 593 | } |
764 | 594 | ||
765 | int perf_event__process(struct perf_tool *tool, union perf_event *event, | 595 | int perf_event__process(struct perf_tool *tool __maybe_unused, |
766 | struct perf_sample *sample, struct machine *machine) | 596 | union perf_event *event, |
597 | struct perf_sample *sample __maybe_unused, | ||
598 | struct machine *machine) | ||
767 | { | 599 | { |
768 | switch (event->header.type) { | 600 | return machine__process_event(machine, event); |
769 | case PERF_RECORD_COMM: | ||
770 | perf_event__process_comm(tool, event, sample, machine); | ||
771 | break; | ||
772 | case PERF_RECORD_MMAP: | ||
773 | perf_event__process_mmap(tool, event, sample, machine); | ||
774 | break; | ||
775 | case PERF_RECORD_FORK: | ||
776 | perf_event__process_fork(tool, event, sample, machine); | ||
777 | break; | ||
778 | case PERF_RECORD_EXIT: | ||
779 | perf_event__process_exit(tool, event, sample, machine); | ||
780 | break; | ||
781 | case PERF_RECORD_LOST: | ||
782 | perf_event__process_lost(tool, event, sample, machine); | ||
783 | default: | ||
784 | break; | ||
785 | } | ||
786 | |||
787 | return 0; | ||
788 | } | 601 | } |
789 | 602 | ||
790 | void thread__find_addr_map(struct thread *self, | 603 | void thread__find_addr_map(struct thread *self, |