Commit 5cbd08056142dcb2aea0dca7261afcb810a63c55
Committed by
Ingo Molnar
1 parent
bab81b624e
Exists in
master
and in
7 other branches
perf timechart: Remove open-coded event parsing code
Convert builtin-timechart.c to mmap_dispatch_perf_file() + perf_file_handler. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> Acked-by: Arjan van de Ven <arjan@infradead.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Peter Zijlstra <peterz@infradead.org> LKML-Reference: <4B14B21C.2040406@cn.fujitsu.com> [ v2: cleaned up the printout, fixed a whitespace detail ] Signed-off-by: Ingo Molnar <mingo@elte.hu>
Showing 1 changed file with 30 additions and 140 deletions Side-by-side Diff
tools/perf/builtin-timechart.c
... | ... | @@ -29,14 +29,14 @@ |
29 | 29 | #include "util/header.h" |
30 | 30 | #include "util/parse-options.h" |
31 | 31 | #include "util/parse-events.h" |
32 | +#include "util/event.h" | |
33 | +#include "util/data_map.h" | |
32 | 34 | #include "util/svghelper.h" |
33 | 35 | |
34 | 36 | static char const *input_name = "perf.data"; |
35 | 37 | static char const *output_name = "output.svg"; |
36 | 38 | |
37 | 39 | |
38 | -static unsigned long page_size; | |
39 | -static unsigned long mmap_window = 32; | |
40 | 40 | static u64 sample_type; |
41 | 41 | |
42 | 42 | static unsigned int numcpus; |
... | ... | @@ -49,8 +49,6 @@ |
49 | 49 | static int power_only; |
50 | 50 | |
51 | 51 | |
52 | -static struct perf_header *header; | |
53 | - | |
54 | 52 | struct per_pid; |
55 | 53 | struct per_pidcomm; |
56 | 54 | |
... | ... | @@ -156,9 +154,9 @@ |
156 | 154 | |
157 | 155 | struct process_filter; |
158 | 156 | struct process_filter { |
159 | - char *name; | |
160 | - int pid; | |
161 | - struct process_filter *next; | |
157 | + char *name; | |
158 | + int pid; | |
159 | + struct process_filter *next; | |
162 | 160 | }; |
163 | 161 | |
164 | 162 | static struct process_filter *process_filter; |
... | ... | @@ -1045,36 +1043,6 @@ |
1045 | 1043 | svg_close(); |
1046 | 1044 | } |
1047 | 1045 | |
1048 | -static int | |
1049 | -process_event(event_t *event) | |
1050 | -{ | |
1051 | - | |
1052 | - switch (event->header.type) { | |
1053 | - | |
1054 | - case PERF_RECORD_COMM: | |
1055 | - return process_comm_event(event); | |
1056 | - case PERF_RECORD_FORK: | |
1057 | - return process_fork_event(event); | |
1058 | - case PERF_RECORD_EXIT: | |
1059 | - return process_exit_event(event); | |
1060 | - case PERF_RECORD_SAMPLE: | |
1061 | - return queue_sample_event(event); | |
1062 | - | |
1063 | - /* | |
1064 | - * We dont process them right now but they are fine: | |
1065 | - */ | |
1066 | - case PERF_RECORD_MMAP: | |
1067 | - case PERF_RECORD_THROTTLE: | |
1068 | - case PERF_RECORD_UNTHROTTLE: | |
1069 | - return 0; | |
1070 | - | |
1071 | - default: | |
1072 | - return -1; | |
1073 | - } | |
1074 | - | |
1075 | - return 0; | |
1076 | -} | |
1077 | - | |
1078 | 1046 | static void process_samples(void) |
1079 | 1047 | { |
1080 | 1048 | struct sample_wrapper *cursor; |
1081 | 1049 | |
1082 | 1050 | |
1083 | 1051 | |
1084 | 1052 | |
1085 | 1053 | |
1086 | 1054 | |
1087 | 1055 | |
1088 | 1056 | |
... | ... | @@ -1090,115 +1058,39 @@ |
1090 | 1058 | } |
1091 | 1059 | } |
1092 | 1060 | |
1093 | - | |
1094 | -static int __cmd_timechart(void) | |
1061 | +static int sample_type_check(u64 type) | |
1095 | 1062 | { |
1096 | - int err, rc = EXIT_FAILURE; | |
1097 | - unsigned long offset = 0; | |
1098 | - unsigned long head, shift; | |
1099 | - struct stat statbuf; | |
1100 | - event_t *event; | |
1101 | - uint32_t size; | |
1102 | - char *buf; | |
1103 | - int input; | |
1063 | + sample_type = type; | |
1104 | 1064 | |
1105 | - input = open(input_name, O_RDONLY); | |
1106 | - if (input < 0) { | |
1107 | - fprintf(stderr, " failed to open file: %s", input_name); | |
1108 | - if (!strcmp(input_name, "perf.data")) | |
1109 | - fprintf(stderr, " (try 'perf record' first)"); | |
1110 | - fprintf(stderr, "\n"); | |
1111 | - exit(-1); | |
1065 | + if (!(sample_type & PERF_SAMPLE_RAW)) { | |
1066 | + fprintf(stderr, "No trace samples found in the file.\n" | |
1067 | + "Have you used 'perf timechart record' to record it?\n"); | |
1068 | + return -1; | |
1112 | 1069 | } |
1113 | 1070 | |
1114 | - err = fstat(input, &statbuf); | |
1115 | - if (err < 0) { | |
1116 | - perror("failed to stat file"); | |
1117 | - exit(-1); | |
1118 | - } | |
1071 | + return 0; | |
1072 | +} | |
1119 | 1073 | |
1120 | - if (!statbuf.st_size) { | |
1121 | - fprintf(stderr, "zero-sized file, nothing to do!\n"); | |
1122 | - exit(0); | |
1123 | - } | |
1074 | +static struct perf_file_handler file_handler = { | |
1075 | + .process_comm_event = process_comm_event, | |
1076 | + .process_fork_event = process_fork_event, | |
1077 | + .process_exit_event = process_exit_event, | |
1078 | + .process_sample_event = queue_sample_event, | |
1079 | + .sample_type_check = sample_type_check, | |
1080 | +}; | |
1124 | 1081 | |
1125 | - header = perf_header__new(); | |
1126 | - if (header == NULL) | |
1127 | - return -ENOMEM; | |
1082 | +static int __cmd_timechart(void) | |
1083 | +{ | |
1084 | + struct perf_header *header; | |
1085 | + int ret; | |
1128 | 1086 | |
1129 | - err = perf_header__read(header, input); | |
1130 | - if (err < 0) { | |
1131 | - perf_header__delete(header); | |
1132 | - return err; | |
1133 | - } | |
1087 | + register_perf_file_handler(&file_handler); | |
1134 | 1088 | |
1135 | - head = header->data_offset; | |
1089 | + ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, | |
1090 | + &event__cwdlen, &event__cwd); | |
1091 | + if (ret) | |
1092 | + return EXIT_FAILURE; | |
1136 | 1093 | |
1137 | - sample_type = perf_header__sample_type(header); | |
1138 | - | |
1139 | - shift = page_size * (head / page_size); | |
1140 | - offset += shift; | |
1141 | - head -= shift; | |
1142 | - | |
1143 | -remap: | |
1144 | - buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ, | |
1145 | - MAP_SHARED, input, offset); | |
1146 | - if (buf == MAP_FAILED) { | |
1147 | - perror("failed to mmap file"); | |
1148 | - exit(-1); | |
1149 | - } | |
1150 | - | |
1151 | -more: | |
1152 | - event = (event_t *)(buf + head); | |
1153 | - | |
1154 | - size = event->header.size; | |
1155 | - if (!size) | |
1156 | - size = 8; | |
1157 | - | |
1158 | - if (head + event->header.size >= page_size * mmap_window) { | |
1159 | - int ret2; | |
1160 | - | |
1161 | - shift = page_size * (head / page_size); | |
1162 | - | |
1163 | - ret2 = munmap(buf, page_size * mmap_window); | |
1164 | - assert(ret2 == 0); | |
1165 | - | |
1166 | - offset += shift; | |
1167 | - head -= shift; | |
1168 | - goto remap; | |
1169 | - } | |
1170 | - | |
1171 | - size = event->header.size; | |
1172 | - | |
1173 | - if (!size || process_event(event) < 0) { | |
1174 | - pr_warning("%p [%p]: skipping unknown header type: %d\n", | |
1175 | - (void *)(offset + head), | |
1176 | - (void *)(long)(event->header.size), | |
1177 | - event->header.type); | |
1178 | - /* | |
1179 | - * assume we lost track of the stream, check alignment, and | |
1180 | - * increment a single u64 in the hope to catch on again 'soon'. | |
1181 | - */ | |
1182 | - | |
1183 | - if (unlikely(head & 7)) | |
1184 | - head &= ~7ULL; | |
1185 | - | |
1186 | - size = 8; | |
1187 | - } | |
1188 | - | |
1189 | - head += size; | |
1190 | - | |
1191 | - if (offset + head >= header->data_offset + header->data_size) | |
1192 | - goto done; | |
1193 | - | |
1194 | - if (offset + head < (unsigned long)statbuf.st_size) | |
1195 | - goto more; | |
1196 | - | |
1197 | -done: | |
1198 | - rc = EXIT_SUCCESS; | |
1199 | - close(input); | |
1200 | - | |
1201 | - | |
1202 | 1094 | process_samples(); |
1203 | 1095 | |
1204 | 1096 | end_sample_processing(); |
... | ... | @@ -1210,7 +1102,7 @@ |
1210 | 1102 | pr_info("Written %2.1f seconds of trace to %s.\n", |
1211 | 1103 | (last_time - first_time) / 1000000000.0, output_name); |
1212 | 1104 | |
1213 | - return rc; | |
1105 | + return EXIT_SUCCESS; | |
1214 | 1106 | } |
1215 | 1107 | |
1216 | 1108 | static const char * const timechart_usage[] = { |
... | ... | @@ -1276,8 +1168,6 @@ |
1276 | 1168 | int cmd_timechart(int argc, const char **argv, const char *prefix __used) |
1277 | 1169 | { |
1278 | 1170 | symbol__init(0); |
1279 | - | |
1280 | - page_size = getpagesize(); | |
1281 | 1171 | |
1282 | 1172 | argc = parse_options(argc, argv, options, timechart_usage, |
1283 | 1173 | PARSE_OPT_STOP_AT_NON_OPTION); |