aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-timechart.c170
1 files changed, 30 insertions, 140 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index dd4d82ac7aa4..cb58b6605fcc 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -29,14 +29,14 @@
29#include "util/header.h" 29#include "util/header.h"
30#include "util/parse-options.h" 30#include "util/parse-options.h"
31#include "util/parse-events.h" 31#include "util/parse-events.h"
32#include "util/event.h"
33#include "util/data_map.h"
32#include "util/svghelper.h" 34#include "util/svghelper.h"
33 35
34static char const *input_name = "perf.data"; 36static char const *input_name = "perf.data";
35static char const *output_name = "output.svg"; 37static char const *output_name = "output.svg";
36 38
37 39
38static unsigned long page_size;
39static unsigned long mmap_window = 32;
40static u64 sample_type; 40static u64 sample_type;
41 41
42static unsigned int numcpus; 42static unsigned int numcpus;
@@ -49,8 +49,6 @@ static u64 first_time, last_time;
49static int power_only; 49static int power_only;
50 50
51 51
52static struct perf_header *header;
53
54struct per_pid; 52struct per_pid;
55struct per_pidcomm; 53struct per_pidcomm;
56 54
@@ -156,9 +154,9 @@ struct sample_wrapper *all_samples;
156 154
157struct process_filter; 155struct process_filter;
158struct process_filter { 156struct process_filter {
159 char *name; 157 char *name;
160 int pid; 158 int pid;
161 struct process_filter *next; 159 struct process_filter *next;
162}; 160};
163 161
164static struct process_filter *process_filter; 162static struct process_filter *process_filter;
@@ -1045,36 +1043,6 @@ static void write_svg_file(const char *filename)
1045 svg_close(); 1043 svg_close();
1046} 1044}
1047 1045
1048static int
1049process_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
1078static void process_samples(void) 1046static void process_samples(void)
1079{ 1047{
1080 struct sample_wrapper *cursor; 1048 struct sample_wrapper *cursor;
@@ -1090,114 +1058,38 @@ static void process_samples(void)
1090 } 1058 }
1091} 1059}
1092 1060
1093 1061static int sample_type_check(u64 type)
1094static int __cmd_timechart(void)
1095{ 1062{
1096 int err, rc = EXIT_FAILURE; 1063 sample_type = type;
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;
1104
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);
1112 }
1113
1114 err = fstat(input, &statbuf);
1115 if (err < 0) {
1116 perror("failed to stat file");
1117 exit(-1);
1118 }
1119
1120 if (!statbuf.st_size) {
1121 fprintf(stderr, "zero-sized file, nothing to do!\n");
1122 exit(0);
1123 }
1124 1064
1125 header = perf_header__new(); 1065 if (!(sample_type & PERF_SAMPLE_RAW)) {
1126 if (header == NULL) 1066 fprintf(stderr, "No trace samples found in the file.\n"
1127 return -ENOMEM; 1067 "Have you used 'perf timechart record' to record it?\n");
1128 1068 return -1;
1129 err = perf_header__read(header, input);
1130 if (err < 0) {
1131 perf_header__delete(header);
1132 return err;
1133 }
1134
1135 head = header->data_offset;
1136
1137 sample_type = perf_header__sample_type(header);
1138
1139 shift = page_size * (head / page_size);
1140 offset += shift;
1141 head -= shift;
1142
1143remap:
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
1151more:
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 } 1069 }
1188 1070
1189 head += size; 1071 return 0;
1072}
1190 1073
1191 if (offset + head >= header->data_offset + header->data_size) 1074static struct perf_file_handler file_handler = {
1192 goto done; 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};
1193 1081
1194 if (offset + head < (unsigned long)statbuf.st_size) 1082static int __cmd_timechart(void)
1195 goto more; 1083{
1084 struct perf_header *header;
1085 int ret;
1196 1086
1197done: 1087 register_perf_file_handler(&file_handler);
1198 rc = EXIT_SUCCESS;
1199 close(input);
1200 1088
1089 ret = mmap_dispatch_perf_file(&header, input_name, 0, 0,
1090 &event__cwdlen, &event__cwd);
1091 if (ret)
1092 return EXIT_FAILURE;
1201 1093
1202 process_samples(); 1094 process_samples();
1203 1095
@@ -1210,7 +1102,7 @@ done:
1210 pr_info("Written %2.1f seconds of trace to %s.\n", 1102 pr_info("Written %2.1f seconds of trace to %s.\n",
1211 (last_time - first_time) / 1000000000.0, output_name); 1103 (last_time - first_time) / 1000000000.0, output_name);
1212 1104
1213 return rc; 1105 return EXIT_SUCCESS;
1214} 1106}
1215 1107
1216static const char * const timechart_usage[] = { 1108static const char * const timechart_usage[] = {
@@ -1277,8 +1169,6 @@ int cmd_timechart(int argc, const char **argv, const char *prefix __used)
1277{ 1169{
1278 symbol__init(0); 1170 symbol__init(0);
1279 1171
1280 page_size = getpagesize();
1281
1282 argc = parse_options(argc, argv, options, timechart_usage, 1172 argc = parse_options(argc, argv, options, timechart_usage,
1283 PARSE_OPT_STOP_AT_NON_OPTION); 1173 PARSE_OPT_STOP_AT_NON_OPTION);
1284 1174