Commit 5cbd08056142dcb2aea0dca7261afcb810a63c55

Authored by Li Zefan
Committed by Ingo Molnar
1 parent bab81b624e

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);