aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c100
1 files changed, 65 insertions, 35 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 9b899ba1b410..f4f0240d2302 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -14,6 +14,8 @@
14#include "util/parse-events.h" 14#include "util/parse-events.h"
15#include "util/string.h" 15#include "util/string.h"
16 16
17#include "util/header.h"
18
17#include <unistd.h> 19#include <unistd.h>
18#include <sched.h> 20#include <sched.h>
19 21
@@ -52,7 +54,8 @@ static int nr_poll;
52static int nr_cpu; 54static int nr_cpu;
53 55
54static int file_new = 1; 56static int file_new = 1;
55static struct perf_file_header file_header; 57
58struct perf_header *header;
56 59
57struct mmap_event { 60struct mmap_event {
58 struct perf_event_header header; 61 struct perf_event_header header;
@@ -328,7 +331,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
328 fclose(fp); 331 fclose(fp);
329} 332}
330 333
331static void synthesize_samples(void) 334static void synthesize_all(void)
332{ 335{
333 DIR *proc; 336 DIR *proc;
334 struct dirent dirent, *next; 337 struct dirent dirent, *next;
@@ -352,10 +355,35 @@ static void synthesize_samples(void)
352 355
353static int group_fd; 356static int group_fd;
354 357
358static struct perf_header_attr *get_header_attr(struct perf_counter_attr *a, int nr)
359{
360 struct perf_header_attr *h_attr;
361
362 if (nr < header->attrs) {
363 h_attr = header->attr[nr];
364 } else {
365 h_attr = perf_header_attr__new(a);
366 perf_header__add_attr(header, h_attr);
367 }
368
369 return h_attr;
370}
371
355static void create_counter(int counter, int cpu, pid_t pid) 372static void create_counter(int counter, int cpu, pid_t pid)
356{ 373{
357 struct perf_counter_attr *attr = attrs + counter; 374 struct perf_counter_attr *attr = attrs + counter;
358 int track = 1; 375 struct perf_header_attr *h_attr;
376 int track = !counter; /* only the first counter needs these */
377 struct {
378 u64 count;
379 u64 time_enabled;
380 u64 time_running;
381 u64 id;
382 } read_data;
383
384 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
385 PERF_FORMAT_TOTAL_TIME_RUNNING |
386 PERF_FORMAT_ID;
359 387
360 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 388 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
361 389
@@ -368,22 +396,11 @@ static void create_counter(int counter, int cpu, pid_t pid)
368 if (call_graph) 396 if (call_graph)
369 attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 397 attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
370 398
371 if (file_new) {
372 file_header.sample_type = attr->sample_type;
373 } else {
374 if (file_header.sample_type != attr->sample_type) {
375 fprintf(stderr, "incompatible append\n");
376 exit(-1);
377 }
378 }
379
380 attr->mmap = track; 399 attr->mmap = track;
381 attr->comm = track; 400 attr->comm = track;
382 attr->inherit = (cpu < 0) && inherit; 401 attr->inherit = (cpu < 0) && inherit;
383 attr->disabled = 1; 402 attr->disabled = 1;
384 403
385 track = 0; /* only the first counter needs these */
386
387try_again: 404try_again:
388 fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); 405 fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
389 406
@@ -414,6 +431,19 @@ try_again:
414 exit(-1); 431 exit(-1);
415 } 432 }
416 433
434 h_attr = get_header_attr(attr, counter);
435
436 if (!file_new) {
437 if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
438 fprintf(stderr, "incompatible append\n");
439 exit(-1);
440 }
441 }
442
443 read(fd[nr_cpu][counter], &read_data, sizeof(read_data));
444
445 perf_header_attr__add_id(h_attr, read_data.id);
446
417 assert(fd[nr_cpu][counter] >= 0); 447 assert(fd[nr_cpu][counter] >= 0);
418 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); 448 fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
419 449
@@ -444,11 +474,6 @@ static void open_counters(int cpu, pid_t pid)
444{ 474{
445 int counter; 475 int counter;
446 476
447 if (pid > 0) {
448 pid_synthesize_comm_event(pid, 0);
449 pid_synthesize_mmap_samples(pid);
450 }
451
452 group_fd = -1; 477 group_fd = -1;
453 for (counter = 0; counter < nr_counters; counter++) 478 for (counter = 0; counter < nr_counters; counter++)
454 create_counter(counter, cpu, pid); 479 create_counter(counter, cpu, pid);
@@ -458,17 +483,16 @@ static void open_counters(int cpu, pid_t pid)
458 483
459static void atexit_header(void) 484static void atexit_header(void)
460{ 485{
461 file_header.data_size += bytes_written; 486 header->data_size += bytes_written;
462 487
463 if (pwrite(output, &file_header, sizeof(file_header), 0) == -1) 488 perf_header__write(header, output);
464 perror("failed to write on file headers");
465} 489}
466 490
467static int __cmd_record(int argc, const char **argv) 491static int __cmd_record(int argc, const char **argv)
468{ 492{
469 int i, counter; 493 int i, counter;
470 struct stat st; 494 struct stat st;
471 pid_t pid; 495 pid_t pid = 0;
472 int flags; 496 int flags;
473 int ret; 497 int ret;
474 498
@@ -499,22 +523,31 @@ static int __cmd_record(int argc, const char **argv)
499 exit(-1); 523 exit(-1);
500 } 524 }
501 525
502 if (!file_new) { 526 if (!file_new)
503 if (read(output, &file_header, sizeof(file_header)) == -1) { 527 header = perf_header__read(output);
504 perror("failed to read file headers"); 528 else
505 exit(-1); 529 header = perf_header__new();
506 }
507
508 lseek(output, file_header.data_size, SEEK_CUR);
509 }
510 530
511 atexit(atexit_header); 531 atexit(atexit_header);
512 532
513 if (!system_wide) { 533 if (!system_wide) {
514 open_counters(-1, target_pid != -1 ? target_pid : getpid()); 534 pid = target_pid;
535 if (pid == -1)
536 pid = getpid();
537
538 open_counters(-1, pid);
515 } else for (i = 0; i < nr_cpus; i++) 539 } else for (i = 0; i < nr_cpus; i++)
516 open_counters(i, target_pid); 540 open_counters(i, target_pid);
517 541
542 if (file_new)
543 perf_header__write(header, output);
544
545 if (!system_wide) {
546 pid_synthesize_comm_event(pid, 0);
547 pid_synthesize_mmap_samples(pid);
548 } else
549 synthesize_all();
550
518 if (target_pid == -1 && argc) { 551 if (target_pid == -1 && argc) {
519 pid = fork(); 552 pid = fork();
520 if (pid < 0) 553 if (pid < 0)
@@ -538,9 +571,6 @@ static int __cmd_record(int argc, const char **argv)
538 } 571 }
539 } 572 }
540 573
541 if (system_wide)
542 synthesize_samples();
543
544 while (!done) { 574 while (!done) {
545 int hits = samples; 575 int hits = samples;
546 576