diff options
| -rw-r--r-- | tools/perf/builtin-record.c | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 65301c5ca1de..9b7c6d887d5a 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -402,7 +402,7 @@ static void atexit_header(void) | |||
| 402 | perf_header__write(&session->header, output, true); | 402 | perf_header__write(&session->header, output, true); |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | static int __cmd_record(int argc, const char **argv) | 405 | static int __cmd_record(int argc __used, const char **argv) |
| 406 | { | 406 | { |
| 407 | int i, counter; | 407 | int i, counter; |
| 408 | struct stat st; | 408 | struct stat st; |
| @@ -410,6 +410,8 @@ static int __cmd_record(int argc, const char **argv) | |||
| 410 | int flags; | 410 | int flags; |
| 411 | int err; | 411 | int err; |
| 412 | unsigned long waking = 0; | 412 | unsigned long waking = 0; |
| 413 | int child_ready_pipe[2], go_pipe[2]; | ||
| 414 | char buf; | ||
| 413 | 415 | ||
| 414 | page_size = sysconf(_SC_PAGE_SIZE); | 416 | page_size = sysconf(_SC_PAGE_SIZE); |
| 415 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | 417 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
| @@ -420,6 +422,11 @@ static int __cmd_record(int argc, const char **argv) | |||
| 420 | signal(SIGCHLD, sig_handler); | 422 | signal(SIGCHLD, sig_handler); |
| 421 | signal(SIGINT, sig_handler); | 423 | signal(SIGINT, sig_handler); |
| 422 | 424 | ||
| 425 | if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { | ||
| 426 | perror("failed to create pipes"); | ||
| 427 | exit(-1); | ||
| 428 | } | ||
| 429 | |||
| 423 | if (!stat(output_name, &st) && st.st_size) { | 430 | if (!stat(output_name, &st) && st.st_size) { |
| 424 | if (!force) { | 431 | if (!force) { |
| 425 | if (!append_file) { | 432 | if (!append_file) { |
| @@ -476,19 +483,65 @@ static int __cmd_record(int argc, const char **argv) | |||
| 476 | 483 | ||
| 477 | atexit(atexit_header); | 484 | atexit(atexit_header); |
| 478 | 485 | ||
| 479 | if (!system_wide) { | 486 | if (target_pid == -1) { |
| 480 | pid = target_pid; | 487 | pid = fork(); |
| 481 | if (pid == -1) | 488 | if (pid < 0) { |
| 482 | pid = getpid(); | 489 | perror("failed to fork"); |
| 490 | exit(-1); | ||
| 491 | } | ||
| 483 | 492 | ||
| 484 | open_counters(profile_cpu, pid); | 493 | if (!pid) { |
| 485 | } else { | 494 | close(child_ready_pipe[0]); |
| 486 | if (profile_cpu != -1) { | 495 | close(go_pipe[1]); |
| 487 | open_counters(profile_cpu, target_pid); | 496 | fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); |
| 488 | } else { | 497 | |
| 489 | for (i = 0; i < nr_cpus; i++) | 498 | /* |
| 490 | open_counters(i, target_pid); | 499 | * Do a dummy execvp to get the PLT entry resolved, |
| 500 | * so we avoid the resolver overhead on the real | ||
| 501 | * execvp call. | ||
| 502 | */ | ||
| 503 | execvp("", (char **)argv); | ||
| 504 | |||
| 505 | /* | ||
| 506 | * Tell the parent we're ready to go | ||
| 507 | */ | ||
| 508 | close(child_ready_pipe[1]); | ||
| 509 | |||
| 510 | /* | ||
| 511 | * Wait until the parent tells us to go. | ||
| 512 | */ | ||
| 513 | if (read(go_pipe[0], &buf, 1) == -1) | ||
| 514 | perror("unable to read pipe"); | ||
| 515 | |||
| 516 | execvp(argv[0], (char **)argv); | ||
| 517 | |||
| 518 | perror(argv[0]); | ||
| 519 | exit(-1); | ||
| 491 | } | 520 | } |
| 521 | |||
| 522 | child_pid = pid; | ||
| 523 | |||
| 524 | if (!system_wide) | ||
| 525 | target_pid = pid; | ||
| 526 | |||
| 527 | close(child_ready_pipe[1]); | ||
| 528 | close(go_pipe[0]); | ||
| 529 | /* | ||
| 530 | * wait for child to settle | ||
| 531 | */ | ||
| 532 | if (read(child_ready_pipe[0], &buf, 1) == -1) { | ||
| 533 | perror("unable to read pipe"); | ||
| 534 | exit(-1); | ||
| 535 | } | ||
| 536 | close(child_ready_pipe[0]); | ||
| 537 | } | ||
| 538 | |||
| 539 | |||
| 540 | if (!system_wide || profile_cpu != -1) { | ||
| 541 | open_counters(profile_cpu, target_pid); | ||
| 542 | } else { | ||
| 543 | for (i = 0; i < nr_cpus; i++) | ||
| 544 | open_counters(i, target_pid); | ||
| 492 | } | 545 | } |
| 493 | 546 | ||
| 494 | if (file_new) { | 547 | if (file_new) { |
| @@ -503,31 +556,6 @@ static int __cmd_record(int argc, const char **argv) | |||
| 503 | else | 556 | else |
| 504 | event__synthesize_threads(process_synthesized_event, session); | 557 | event__synthesize_threads(process_synthesized_event, session); |
| 505 | 558 | ||
| 506 | if (target_pid == -1 && argc) { | ||
| 507 | pid = fork(); | ||
| 508 | if (pid < 0) | ||
| 509 | die("failed to fork"); | ||
| 510 | |||
| 511 | if (!pid) { | ||
| 512 | if (execvp(argv[0], (char **)argv)) { | ||
| 513 | perror(argv[0]); | ||
| 514 | exit(-1); | ||
| 515 | } | ||
| 516 | } else { | ||
| 517 | /* | ||
| 518 | * Wait a bit for the execv'ed child to appear | ||
| 519 | * and be updated in /proc | ||
| 520 | * FIXME: Do you know a less heuristical solution? | ||
| 521 | */ | ||
| 522 | usleep(1000); | ||
| 523 | event__synthesize_thread(pid, | ||
| 524 | process_synthesized_event, | ||
| 525 | session); | ||
| 526 | } | ||
| 527 | |||
| 528 | child_pid = pid; | ||
| 529 | } | ||
| 530 | |||
| 531 | if (realtime_prio) { | 559 | if (realtime_prio) { |
| 532 | struct sched_param param; | 560 | struct sched_param param; |
| 533 | 561 | ||
| @@ -538,6 +566,11 @@ static int __cmd_record(int argc, const char **argv) | |||
| 538 | } | 566 | } |
| 539 | } | 567 | } |
| 540 | 568 | ||
| 569 | /* | ||
| 570 | * Let the child rip | ||
| 571 | */ | ||
| 572 | close(go_pipe[1]); | ||
| 573 | |||
| 541 | for (;;) { | 574 | for (;;) { |
| 542 | int hits = samples; | 575 | int hits = samples; |
| 543 | 576 | ||
| @@ -634,7 +667,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) | |||
| 634 | 667 | ||
| 635 | argc = parse_options(argc, argv, options, record_usage, | 668 | argc = parse_options(argc, argv, options, record_usage, |
| 636 | PARSE_OPT_STOP_AT_NON_OPTION); | 669 | PARSE_OPT_STOP_AT_NON_OPTION); |
| 637 | if (!argc && target_pid == -1 && !system_wide) | 670 | if (!argc && target_pid == -1 && (!system_wide || profile_cpu == -1)) |
| 638 | usage_with_options(record_usage, options); | 671 | usage_with_options(record_usage, options); |
| 639 | 672 | ||
| 640 | symbol__init(); | 673 | symbol__init(); |
