aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-06-18 17:22:55 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-19 07:42:36 -0400
commitf5970550d5ccf90453cbd7d260370ea99d1f6513 (patch)
treef09c265d9c44bf0cb74d5e998626c6dede5e14c9
parent2a0a50fe9def21835d65035cc8109c0b6dd6099d (diff)
perf_counter tools: Add a data file header
Add a data file header so we can transfer data between record and report. LKML-Reference: <new-submission> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-record.c94
-rw-r--r--tools/perf/builtin-report.c16
-rw-r--r--tools/perf/perf.h6
3 files changed, 73 insertions, 43 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 06fdfb8b4828..28304677c73e 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -51,6 +51,9 @@ static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
51static int nr_poll; 51static int nr_poll;
52static int nr_cpu; 52static int nr_cpu;
53 53
54static int file_new = 1;
55static struct perf_file_header file_header;
56
54struct mmap_event { 57struct mmap_event {
55 struct perf_event_header header; 58 struct perf_event_header header;
56 __u32 pid; 59 __u32 pid;
@@ -100,6 +103,21 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
100 pc->data_tail = tail; 103 pc->data_tail = tail;
101} 104}
102 105
106static void write_output(void *buf, size_t size)
107{
108 while (size) {
109 int ret = write(output, buf, size);
110
111 if (ret < 0)
112 die("failed to write");
113
114 size -= ret;
115 buf += ret;
116
117 bytes_written += ret;
118 }
119}
120
103static void mmap_read(struct mmap_data *md) 121static void mmap_read(struct mmap_data *md)
104{ 122{
105 unsigned int head = mmap_read_head(md); 123 unsigned int head = mmap_read_head(md);
@@ -148,34 +166,14 @@ static void mmap_read(struct mmap_data *md)
148 size = md->mask + 1 - (old & md->mask); 166 size = md->mask + 1 - (old & md->mask);
149 old += size; 167 old += size;
150 168
151 while (size) { 169 write_output(buf, size);
152 int ret = write(output, buf, size);
153
154 if (ret < 0)
155 die("failed to write");
156
157 size -= ret;
158 buf += ret;
159
160 bytes_written += ret;
161 }
162 } 170 }
163 171
164 buf = &data[old & md->mask]; 172 buf = &data[old & md->mask];
165 size = head - old; 173 size = head - old;
166 old += size; 174 old += size;
167 175
168 while (size) { 176 write_output(buf, size);
169 int ret = write(output, buf, size);
170
171 if (ret < 0)
172 die("failed to write");
173
174 size -= ret;
175 buf += ret;
176
177 bytes_written += ret;
178 }
179 177
180 md->prev = old; 178 md->prev = old;
181 mmap_write_tail(md, old); 179 mmap_write_tail(md, old);
@@ -204,7 +202,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
204 struct comm_event comm_ev; 202 struct comm_event comm_ev;
205 char filename[PATH_MAX]; 203 char filename[PATH_MAX];
206 char bf[BUFSIZ]; 204 char bf[BUFSIZ];
207 int fd, ret; 205 int fd;
208 size_t size; 206 size_t size;
209 char *field, *sep; 207 char *field, *sep;
210 DIR *tasks; 208 DIR *tasks;
@@ -246,11 +244,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
246 if (!full) { 244 if (!full) {
247 comm_ev.tid = pid; 245 comm_ev.tid = pid;
248 246
249 ret = write(output, &comm_ev, comm_ev.header.size); 247 write_output(&comm_ev, comm_ev.header.size);
250 if (ret < 0) {
251 perror("failed to write");
252 exit(-1);
253 }
254 return; 248 return;
255 } 249 }
256 250
@@ -265,11 +259,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
265 259
266 comm_ev.tid = pid; 260 comm_ev.tid = pid;
267 261
268 ret = write(output, &comm_ev, comm_ev.header.size); 262 write_output(&comm_ev, comm_ev.header.size);
269 if (ret < 0) {
270 perror("failed to write");
271 exit(-1);
272 }
273 } 263 }
274 closedir(tasks); 264 closedir(tasks);
275 return; 265 return;
@@ -332,10 +322,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
332 mmap_ev.pid = pid; 322 mmap_ev.pid = pid;
333 mmap_ev.tid = pid; 323 mmap_ev.tid = pid;
334 324
335 if (write(output, &mmap_ev, mmap_ev.header.size) < 0) { 325 write_output(&mmap_ev, mmap_ev.header.size);
336 perror("failed to write");
337 exit(-1);
338 }
339 } 326 }
340 } 327 }
341 328
@@ -382,6 +369,15 @@ static void create_counter(int counter, int cpu, pid_t pid)
382 if (call_graph) 369 if (call_graph)
383 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 370 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
384 371
372 if (file_new) {
373 file_header.sample_type = attr->sample_type;
374 } else {
375 if (file_header.sample_type != attr->sample_type) {
376 fprintf(stderr, "incompatible append\n");
377 exit(-1);
378 }
379 }
380
385 attr->mmap = track; 381 attr->mmap = track;
386 attr->comm = track; 382 attr->comm = track;
387 attr->inherit = (cpu < 0) && inherit; 383 attr->inherit = (cpu < 0) && inherit;
@@ -461,6 +457,13 @@ static void open_counters(int cpu, pid_t pid)
461 nr_cpu++; 457 nr_cpu++;
462} 458}
463 459
460static void atexit_header(void)
461{
462 file_header.data_size += bytes_written;
463
464 pwrite(output, &file_header, sizeof(file_header), 0);
465}
466
464static int __cmd_record(int argc, const char **argv) 467static int __cmd_record(int argc, const char **argv)
465{ 468{
466 int i, counter; 469 int i, counter;
@@ -474,6 +477,10 @@ static int __cmd_record(int argc, const char **argv)
474 assert(nr_cpus <= MAX_NR_CPUS); 477 assert(nr_cpus <= MAX_NR_CPUS);
475 assert(nr_cpus >= 0); 478 assert(nr_cpus >= 0);
476 479
480 atexit(sig_atexit);
481 signal(SIGCHLD, sig_handler);
482 signal(SIGINT, sig_handler);
483
477 if (!stat(output_name, &st) && !force && !append_file) { 484 if (!stat(output_name, &st) && !force && !append_file) {
478 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 485 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
479 output_name); 486 output_name);
@@ -482,7 +489,7 @@ static int __cmd_record(int argc, const char **argv)
482 489
483 flags = O_CREAT|O_RDWR; 490 flags = O_CREAT|O_RDWR;
484 if (append_file) 491 if (append_file)
485 flags |= O_APPEND; 492 file_new = 0;
486 else 493 else
487 flags |= O_TRUNC; 494 flags |= O_TRUNC;
488 495
@@ -492,15 +499,18 @@ static int __cmd_record(int argc, const char **argv)
492 exit(-1); 499 exit(-1);
493 } 500 }
494 501
502 if (!file_new) {
503 read(output, &file_header, sizeof(file_header));
504 lseek(output, file_header.data_size, SEEK_CUR);
505 }
506
507 atexit(atexit_header);
508
495 if (!system_wide) { 509 if (!system_wide) {
496 open_counters(-1, target_pid != -1 ? target_pid : getpid()); 510 open_counters(-1, target_pid != -1 ? target_pid : getpid());
497 } else for (i = 0; i < nr_cpus; i++) 511 } else for (i = 0; i < nr_cpus; i++)
498 open_counters(i, target_pid); 512 open_counters(i, target_pid);
499 513
500 atexit(sig_atexit);
501 signal(SIGCHLD, sig_handler);
502 signal(SIGINT, sig_handler);
503
504 if (target_pid == -1 && argc) { 514 if (target_pid == -1 && argc) {
505 pid = fork(); 515 pid = fork();
506 if (pid < 0) 516 if (pid < 0)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 7a6577bf9a41..37b26ecb0d0b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -1366,11 +1366,13 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
1366 return 0; 1366 return 0;
1367} 1367}
1368 1368
1369static struct perf_file_header file_header;
1370
1369static int __cmd_report(void) 1371static int __cmd_report(void)
1370{ 1372{
1371 int ret, rc = EXIT_FAILURE; 1373 int ret, rc = EXIT_FAILURE;
1372 unsigned long offset = 0; 1374 unsigned long offset = 0;
1373 unsigned long head = 0; 1375 unsigned long head = sizeof(file_header);
1374 struct stat stat; 1376 struct stat stat;
1375 event_t *event; 1377 event_t *event;
1376 uint32_t size; 1378 uint32_t size;
@@ -1398,6 +1400,14 @@ static int __cmd_report(void)
1398 exit(0); 1400 exit(0);
1399 } 1401 }
1400 1402
1403 read(input, &file_header, sizeof(file_header));
1404
1405 if (sort__has_parent &&
1406 !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) {
1407 fprintf(stderr, "selected --sort parent, but no callchain data\n");
1408 exit(-1);
1409 }
1410
1401 if (load_kernel() < 0) { 1411 if (load_kernel() < 0) {
1402 perror("failed to load kernel symbols"); 1412 perror("failed to load kernel symbols");
1403 return EXIT_FAILURE; 1413 return EXIT_FAILURE;
@@ -1469,9 +1479,13 @@ more:
1469 1479
1470 head += size; 1480 head += size;
1471 1481
1482 if (offset + head >= sizeof(file_header) + file_header.data_size)
1483 goto done;
1484
1472 if (offset + head < stat.st_size) 1485 if (offset + head < stat.st_size)
1473 goto more; 1486 goto more;
1474 1487
1488done:
1475 rc = EXIT_SUCCESS; 1489 rc = EXIT_SUCCESS;
1476 close(input); 1490 close(input);
1477 1491
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 87a1aca4a424..55c62f4b990b 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -65,4 +65,10 @@ sys_perf_counter_open(struct perf_counter_attr *attr,
65#define MAX_COUNTERS 256 65#define MAX_COUNTERS 256
66#define MAX_NR_CPUS 256 66#define MAX_NR_CPUS 256
67 67
68struct perf_file_header {
69 __u64 version;
70 __u64 sample_type;
71 __u64 data_size;
72};
73
68#endif 74#endif