aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-10-07 06:47:31 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-08 10:56:32 -0400
commit016e92fbc9ef33689cf654f343a94383d43235e7 (patch)
treeedf9dc21d037ea138300b7e7e32574e6f6f17fb2 /tools/perf/builtin-trace.c
parent03456a158d9067d2f657bec170506009db81756d (diff)
perf tools: Unify perf.data mapping and events handling
This librarizes the perf.data file mapping and handling in various perf tools, roughly reducing the amount of code and fixing the places that mmap from beginning of the file whereas we want to mmap from the beginning of the data, leading to page fault because the mmap window is too small since the trace info are written in the file too. TODO: - convert perf timechart too Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arjan van de Ven <arjan@infradead.org> LKML-Reference: <20091007104729.GD5043@nowhere> Signed-off-by: Ingo Molnar <mingo@elte.hu>
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) {