aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-report.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-10-07 06:47:31 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-08 10:56:32 -0400
commit016e92fbc9ef33689cf654f343a94383d43235e7 (patch)
treeedf9dc21d037ea138300b7e7e32574e6f6f17fb2 /tools/perf/builtin-report.c
parent03456a158d9067d2f657bec170506009db81756d (diff)
perf tools: Unify perf.data mapping and events handling
This librarizes the perf.data file mapping and handling in various perf tools, roughly reducing the amount of code and fixing the places that mmap from beginning of the file whereas we want to mmap from the beginning of the data, leading to page fault because the mmap window is too small since the trace info are written in the file too. TODO: - convert perf timechart too Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arjan van de Ven <arjan@infradead.org> LKML-Reference: <20091007104729.GD5043@nowhere> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-report.c')
-rw-r--r--tools/perf/builtin-report.c211
1 files changed, 34 insertions, 177 deletions
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 12f8c868fcd..87c4582303b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -26,6 +26,7 @@
26#include "util/parse-options.h" 26#include "util/parse-options.h"
27#include "util/parse-events.h" 27#include "util/parse-events.h"
28 28
29#include "util/data_map.h"
29#include "util/thread.h" 30#include "util/thread.h"
30#include "util/sort.h" 31#include "util/sort.h"
31#include "util/hist.h" 32#include "util/hist.h"
@@ -37,7 +38,6 @@ static char *dso_list_str, *comm_list_str, *sym_list_str,
37static struct strlist *dso_list, *comm_list, *sym_list; 38static struct strlist *dso_list, *comm_list, *sym_list;
38 39
39static int force; 40static int force;
40static int input;
41 41
42static int full_paths; 42static int full_paths;
43static int show_nr_samples; 43static int show_nr_samples;
@@ -48,15 +48,11 @@ static struct perf_read_values show_threads_values;
48static char default_pretty_printing_style[] = "normal"; 48static char default_pretty_printing_style[] = "normal";
49static char *pretty_printing_style = default_pretty_printing_style; 49static char *pretty_printing_style = default_pretty_printing_style;
50 50
51static unsigned long page_size;
52static unsigned long mmap_window = 32;
53
54static int exclude_other = 1; 51static int exclude_other = 1;
55 52
56static char callchain_default_opt[] = "fractal,0.5"; 53static char callchain_default_opt[] = "fractal,0.5";
57 54
58static char __cwd[PATH_MAX]; 55static char *cwd;
59static char *cwd = __cwd;
60static int cwdlen; 56static int cwdlen;
61 57
62static struct rb_root threads; 58static struct rb_root threads;
@@ -815,208 +811,71 @@ process_read_event(event_t *event, unsigned long offset, unsigned long head)
815 return 0; 811 return 0;
816} 812}
817 813
818static int 814static int sample_type_check(u64 type)
819process_event(event_t *event, unsigned long offset, unsigned long head)
820{
821 trace_event(event);
822
823 switch (event->header.type) {
824 case PERF_RECORD_SAMPLE:
825 return process_sample_event(event, offset, head);
826
827 case PERF_RECORD_MMAP:
828 return process_mmap_event(event, offset, head);
829
830 case PERF_RECORD_COMM:
831 return process_comm_event(event, offset, head);
832
833 case PERF_RECORD_FORK:
834 case PERF_RECORD_EXIT:
835 return process_task_event(event, offset, head);
836
837 case PERF_RECORD_LOST:
838 return process_lost_event(event, offset, head);
839
840 case PERF_RECORD_READ:
841 return process_read_event(event, offset, head);
842
843 /*
844 * We dont process them right now but they are fine:
845 */
846
847 case PERF_RECORD_THROTTLE:
848 case PERF_RECORD_UNTHROTTLE:
849 return 0;
850
851 default:
852 return -1;
853 }
854
855 return 0;
856}
857
858static int __cmd_report(void)
859{ 815{
860 int ret, rc = EXIT_FAILURE; 816 sample_type = type;
861 unsigned long offset = 0;
862 unsigned long head, shift;
863 struct stat input_stat;
864 struct thread *idle;
865 event_t *event;
866 uint32_t size;
867 char *buf;
868
869 idle = register_idle_thread(&threads, &last_match);
870 thread__comm_adjust(idle);
871
872 if (show_threads)
873 perf_read_values_init(&show_threads_values);
874
875 input = open(input_name, O_RDONLY);
876 if (input < 0) {
877 fprintf(stderr, " failed to open file: %s", input_name);
878 if (!strcmp(input_name, "perf.data"))
879 fprintf(stderr, " (try 'perf record' first)");
880 fprintf(stderr, "\n");
881 exit(-1);
882 }
883
884 ret = fstat(input, &input_stat);
885 if (ret < 0) {
886 perror("failed to stat file");
887 exit(-1);
888 }
889
890 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
891 fprintf(stderr, "file: %s not owned by current user or root\n", input_name);
892 exit(-1);
893 }
894
895 if (!input_stat.st_size) {
896 fprintf(stderr, "zero-sized file, nothing to do!\n");
897 exit(0);
898 }
899
900 header = perf_header__read(input);
901 head = header->data_offset;
902
903 sample_type = perf_header__sample_type(header);
904 817
905 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) { 818 if (!(sample_type & PERF_SAMPLE_CALLCHAIN)) {
906 if (sort__has_parent) { 819 if (sort__has_parent) {
907 fprintf(stderr, "selected --sort parent, but no" 820 fprintf(stderr, "selected --sort parent, but no"
908 " callchain data. Did you call" 821 " callchain data. Did you call"
909 " perf record without -g?\n"); 822 " perf record without -g?\n");
910 exit(-1); 823 return -1;
911 } 824 }
912 if (callchain) { 825 if (callchain) {
913 fprintf(stderr, "selected -g but no callchain data." 826 fprintf(stderr, "selected -g but no callchain data."
914 " Did you call perf record without" 827 " Did you call perf record without"
915 " -g?\n"); 828 " -g?\n");
916 exit(-1); 829 return -1;
917 } 830 }
918 } else if (callchain_param.mode != CHAIN_NONE && !callchain) { 831 } else if (callchain_param.mode != CHAIN_NONE && !callchain) {
919 callchain = 1; 832 callchain = 1;
920 if (register_callchain_param(&callchain_param) < 0) { 833 if (register_callchain_param(&callchain_param) < 0) {
921 fprintf(stderr, "Can't register callchain" 834 fprintf(stderr, "Can't register callchain"
922 " params\n"); 835 " params\n");
923 exit(-1); 836 return -1;
924 } 837 }
925 } 838 }
926 839
927 if (load_kernel() < 0) { 840 return 0;
928 perror("failed to load kernel symbols"); 841}
929 return EXIT_FAILURE;
930 }
931
932 if (!full_paths) {
933 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
934 perror("failed to get the current directory");
935 return EXIT_FAILURE;
936 }
937 cwdlen = strlen(cwd);
938 } else {
939 cwd = NULL;
940 cwdlen = 0;
941 }
942
943 shift = page_size * (head / page_size);
944 offset += shift;
945 head -= shift;
946
947remap:
948 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
949 MAP_SHARED, input, offset);
950 if (buf == MAP_FAILED) {
951 perror("failed to mmap file");
952 exit(-1);
953 }
954
955more:
956 event = (event_t *)(buf + head);
957
958 size = event->header.size;
959 if (!size)
960 size = 8;
961
962 if (head + event->header.size >= page_size * mmap_window) {
963 int munmap_ret;
964
965 shift = page_size * (head / page_size);
966
967 munmap_ret = munmap(buf, page_size * mmap_window);
968 assert(munmap_ret == 0);
969
970 offset += shift;
971 head -= shift;
972 goto remap;
973 }
974
975 size = event->header.size;
976
977 dump_printf("\n%p [%p]: event: %d\n",
978 (void *)(offset + head),
979 (void *)(long)event->header.size,
980 event->header.type);
981
982 if (!size || process_event(event, offset, head) < 0) {
983
984 dump_printf("%p [%p]: skipping unknown header type: %d\n",
985 (void *)(offset + head),
986 (void *)(long)(event->header.size),
987 event->header.type);
988
989 total_unknown++;
990 842
991 /* 843static struct perf_file_handler file_handler = {
992 * assume we lost track of the stream, check alignment, and 844 .process_sample_event = process_sample_event,
993 * increment a single u64 in the hope to catch on again 'soon'. 845 .process_mmap_event = process_mmap_event,
994 */ 846 .process_comm_event = process_comm_event,
847 .process_exit_event = process_task_event,
848 .process_fork_event = process_task_event,
849 .process_lost_event = process_lost_event,
850 .process_read_event = process_read_event,
851 .sample_type_check = sample_type_check,
852};
995 853
996 if (unlikely(head & 7))
997 head &= ~7ULL;
998 854
999 size = 8; 855static int __cmd_report(void)
1000 } 856{
857 struct thread *idle;
858 int ret;
1001 859
1002 head += size; 860 idle = register_idle_thread(&threads, &last_match);
861 thread__comm_adjust(idle);
1003 862
1004 if (offset + head >= header->data_offset + header->data_size) 863 if (show_threads)
1005 goto done; 864 perf_read_values_init(&show_threads_values);
1006 865
1007 if (offset + head < (unsigned long)input_stat.st_size) 866 register_perf_file_handler(&file_handler);
1008 goto more;
1009 867
1010done: 868 ret = mmap_dispatch_perf_file(&header, input_name, force, full_paths,
1011 rc = EXIT_SUCCESS; 869 &cwdlen, &cwd);
1012 close(input); 870 if (ret)
871 return ret;
1013 872
1014 dump_printf(" IP events: %10ld\n", total); 873 dump_printf(" IP events: %10ld\n", total);
1015 dump_printf(" mmap events: %10ld\n", total_mmap); 874 dump_printf(" mmap events: %10ld\n", total_mmap);
1016 dump_printf(" comm events: %10ld\n", total_comm); 875 dump_printf(" comm events: %10ld\n", total_comm);
1017 dump_printf(" fork events: %10ld\n", total_fork); 876 dump_printf(" fork events: %10ld\n", total_fork);
1018 dump_printf(" lost events: %10ld\n", total_lost); 877 dump_printf(" lost events: %10ld\n", total_lost);
1019 dump_printf(" unknown events: %10ld\n", total_unknown); 878 dump_printf(" unknown events: %10ld\n", file_handler.total_unknown);
1020 879
1021 if (dump_trace) 880 if (dump_trace)
1022 return 0; 881 return 0;
@@ -1034,7 +893,7 @@ done:
1034 if (show_threads) 893 if (show_threads)
1035 perf_read_values_destroy(&show_threads_values); 894 perf_read_values_destroy(&show_threads_values);
1036 895
1037 return rc; 896 return ret;
1038} 897}
1039 898
1040static int 899static int
@@ -1177,8 +1036,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
1177{ 1036{
1178 symbol__init(); 1037 symbol__init();
1179 1038
1180 page_size = getpagesize();
1181
1182 argc = parse_options(argc, argv, options, report_usage, 0); 1039 argc = parse_options(argc, argv, options, report_usage, 0);
1183 1040
1184 setup_sorting(); 1041 setup_sorting();