aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c129
1 files changed, 18 insertions, 111 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index d9abb4ae5f79..fb3f3c220211 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -12,11 +12,9 @@
12#include "util/debug.h" 12#include "util/debug.h"
13 13
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include "util/data_map.h"
15 16
16static char const *input_name = "perf.data"; 17static char const *input_name = "perf.data";
17static int input;
18static unsigned long page_size;
19static unsigned long mmap_window = 32;
20 18
21static unsigned long total = 0; 19static unsigned long total = 0;
22static unsigned long total_comm = 0; 20static unsigned long total_comm = 0;
@@ -27,6 +25,9 @@ static struct thread *last_match;
27static struct perf_header *header; 25static struct perf_header *header;
28static u64 sample_type; 26static u64 sample_type;
29 27
28static char *cwd;
29static int cwdlen;
30
30 31
31static int 32static int
32process_comm_event(event_t *event, unsigned long offset, unsigned long head) 33process_comm_event(event_t *event, unsigned long offset, unsigned long head)
@@ -112,125 +113,32 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
112 return 0; 113 return 0;
113} 114}
114 115
115static int 116static int sample_type_check(u64 type)
116process_event(event_t *event, unsigned long offset, unsigned long head)
117{ 117{
118 trace_event(event); 118 sample_type = type;
119
120 switch (event->header.type) {
121 case PERF_RECORD_MMAP ... PERF_RECORD_LOST:
122 return 0;
123
124 case PERF_RECORD_COMM:
125 return process_comm_event(event, offset, head);
126
127 case PERF_RECORD_EXIT ... PERF_RECORD_READ:
128 return 0;
129 119
130 case PERF_RECORD_SAMPLE: 120 if (!(sample_type & PERF_SAMPLE_RAW)) {
131 return process_sample_event(event, offset, head); 121 fprintf(stderr,
132 122 "No trace sample to read. Did you call perf record "
133 case PERF_RECORD_MAX: 123 "without -R?");
134 default:
135 return -1; 124 return -1;
136 } 125 }
137 126
138 return 0; 127 return 0;
139} 128}
140 129
130static struct perf_file_handler file_handler = {
131 .process_sample_event = process_sample_event,
132 .process_comm_event = process_comm_event,
133 .sample_type_check = sample_type_check,
134};
135
141static int __cmd_trace(void) 136static int __cmd_trace(void)
142{ 137{
143 int ret, rc = EXIT_FAILURE;
144 unsigned long offset = 0;
145 unsigned long head = 0;
146 unsigned long shift;
147 struct stat perf_stat;
148 event_t *event;
149 uint32_t size;
150 char *buf;
151
152 register_idle_thread(&threads, &last_match); 138 register_idle_thread(&threads, &last_match);
139 register_perf_file_handler(&file_handler);
153 140
154 input = open(input_name, O_RDONLY); 141 return mmap_dispatch_perf_file(&header, input_name, 0, 0, &cwdlen, &cwd);
155 if (input < 0) {
156 perror("failed to open file");
157 exit(-1);
158 }
159
160 ret = fstat(input, &perf_stat);
161 if (ret < 0) {
162 perror("failed to stat file");
163 exit(-1);
164 }
165
166 if (!perf_stat.st_size) {
167 fprintf(stderr, "zero-sized file, nothing to do!\n");
168 exit(0);
169 }
170 header = perf_header__read(input);
171 head = header->data_offset;
172 sample_type = perf_header__sample_type(header);
173
174 if (!(sample_type & PERF_SAMPLE_RAW))
175 die("No trace sample to read. Did you call perf record "
176 "without -R?");
177
178 if (load_kernel() < 0) {
179 perror("failed to load kernel symbols");
180 return EXIT_FAILURE;
181 }
182
183 shift = page_size * (head / page_size);
184 offset += shift;
185 head -= shift;
186
187remap:
188 buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
189 MAP_SHARED, input, offset);
190 if (buf == MAP_FAILED) {
191 perror("failed to mmap file");
192 exit(-1);
193 }
194
195more:
196 event = (event_t *)(buf + head);
197
198 if (head + event->header.size >= page_size * mmap_window) {
199 int res;
200
201 shift = page_size * (head / page_size);
202 res = munmap(buf, page_size * mmap_window);
203 assert(res == 0);
204
205 offset += shift;
206 head -= shift;
207 goto remap;
208 }
209
210 size = event->header.size;
211
212 if (!size || process_event(event, offset, head) < 0) {
213
214 /*
215 * assume we lost track of the stream, check alignment, and
216 * increment a single u64 in the hope to catch on again 'soon'.
217 */
218
219 if (unlikely(head & 7))
220 head &= ~7ULL;
221
222 size = 8;
223 }
224
225 head += size;
226
227 if (offset + head < (unsigned long)perf_stat.st_size)
228 goto more;
229
230 rc = EXIT_SUCCESS;
231 close(input);
232
233 return rc;
234} 142}
235 143
236static const char * const annotate_usage[] = { 144static const char * const annotate_usage[] = {
@@ -249,7 +157,6 @@ static const struct option options[] = {
249int cmd_trace(int argc, const char **argv, const char *prefix __used) 157int cmd_trace(int argc, const char **argv, const char *prefix __used)
250{ 158{
251 symbol__init(); 159 symbol__init();
252 page_size = getpagesize();
253 160
254 argc = parse_options(argc, argv, options, annotate_usage, 0); 161 argc = parse_options(argc, argv, options, annotate_usage, 0);
255 if (argc) { 162 if (argc) {