diff options
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r-- | tools/perf/builtin-trace.c | 129 |
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 | ||
16 | static char const *input_name = "perf.data"; | 17 | static char const *input_name = "perf.data"; |
17 | static int input; | ||
18 | static unsigned long page_size; | ||
19 | static unsigned long mmap_window = 32; | ||
20 | 18 | ||
21 | static unsigned long total = 0; | 19 | static unsigned long total = 0; |
22 | static unsigned long total_comm = 0; | 20 | static unsigned long total_comm = 0; |
@@ -27,6 +25,9 @@ static struct thread *last_match; | |||
27 | static struct perf_header *header; | 25 | static struct perf_header *header; |
28 | static u64 sample_type; | 26 | static u64 sample_type; |
29 | 27 | ||
28 | static char *cwd; | ||
29 | static int cwdlen; | ||
30 | |||
30 | 31 | ||
31 | static int | 32 | static int |
32 | process_comm_event(event_t *event, unsigned long offset, unsigned long head) | 33 | process_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 | ||
115 | static int | 116 | static int sample_type_check(u64 type) |
116 | process_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 | ||
130 | static 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 | |||
141 | static int __cmd_trace(void) | 136 | static 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 | |||
187 | remap: | ||
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 | |||
195 | more: | ||
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 | ||
236 | static const char * const annotate_usage[] = { | 144 | static const char * const annotate_usage[] = { |
@@ -249,7 +157,6 @@ static const struct option options[] = { | |||
249 | int cmd_trace(int argc, const char **argv, const char *prefix __used) | 157 | int 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) { |