aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-11-09 05:47:15 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-11-28 07:26:14 -0500
commit35b9d88ecd8c5fb720ba0dd325262f356d0b03e7 (patch)
tree536902f734862d5b04a6122c81386fddb19f4bcd /tools/perf/builtin-record.c
parent0f82ebc452f921590e216b28eee0b41f5e434a48 (diff)
perf evlist: Introduce {prepare,start}_workload refactored from 'perf record'
So that we can easily start a workload in other tools. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-zdsksd4aphu0nltg2lpwsw3x@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c81
1 files changed, 13 insertions, 68 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index c3ac5415c097..4799195ed246 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -47,11 +47,9 @@ static struct perf_record_opts record_opts = {
47static unsigned int page_size; 47static unsigned int page_size;
48static unsigned int mmap_pages = UINT_MAX; 48static unsigned int mmap_pages = UINT_MAX;
49static int output; 49static int output;
50static int pipe_output = 0;
51static const char *output_name = NULL; 50static const char *output_name = NULL;
52static bool group = false; 51static bool group = false;
53static int realtime_prio = 0; 52static int realtime_prio = 0;
54static pid_t child_pid = -1;
55static enum write_mode_t write_mode = WRITE_FORCE; 53static enum write_mode_t write_mode = WRITE_FORCE;
56static bool no_buildid = false; 54static bool no_buildid = false;
57static bool no_buildid_cache = false; 55static bool no_buildid_cache = false;
@@ -144,9 +142,9 @@ static void sig_atexit(void)
144{ 142{
145 int status; 143 int status;
146 144
147 if (child_pid > 0) { 145 if (evsel_list->workload.pid > 0) {
148 if (!child_finished) 146 if (!child_finished)
149 kill(child_pid, SIGTERM); 147 kill(evsel_list->workload.pid, SIGTERM);
150 148
151 wait(&status); 149 wait(&status);
152 if (WIFSIGNALED(status)) 150 if (WIFSIGNALED(status))
@@ -304,7 +302,7 @@ static int process_buildids(void)
304 302
305static void atexit_header(void) 303static void atexit_header(void)
306{ 304{
307 if (!pipe_output) { 305 if (!record_opts.pipe_output) {
308 session->header.data_size += bytes_written; 306 session->header.data_size += bytes_written;
309 307
310 if (!no_buildid) 308 if (!no_buildid)
@@ -377,9 +375,7 @@ static int __cmd_record(int argc, const char **argv)
377 int flags; 375 int flags;
378 int err; 376 int err;
379 unsigned long waking = 0; 377 unsigned long waking = 0;
380 int child_ready_pipe[2], go_pipe[2];
381 const bool forks = argc > 0; 378 const bool forks = argc > 0;
382 char buf;
383 struct machine *machine; 379 struct machine *machine;
384 380
385 progname = argv[0]; 381 progname = argv[0];
@@ -391,20 +387,15 @@ static int __cmd_record(int argc, const char **argv)
391 signal(SIGINT, sig_handler); 387 signal(SIGINT, sig_handler);
392 signal(SIGUSR1, sig_handler); 388 signal(SIGUSR1, sig_handler);
393 389
394 if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
395 perror("failed to create pipes");
396 exit(-1);
397 }
398
399 if (!output_name) { 390 if (!output_name) {
400 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode)) 391 if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
401 pipe_output = true; 392 record_opts.pipe_output = true;
402 else 393 else
403 output_name = "perf.data"; 394 output_name = "perf.data";
404 } 395 }
405 if (output_name) { 396 if (output_name) {
406 if (!strcmp(output_name, "-")) 397 if (!strcmp(output_name, "-"))
407 pipe_output = true; 398 record_opts.pipe_output = true;
408 else if (!stat(output_name, &st) && st.st_size) { 399 else if (!stat(output_name, &st) && st.st_size) {
409 if (write_mode == WRITE_FORCE) { 400 if (write_mode == WRITE_FORCE) {
410 char oldname[PATH_MAX]; 401 char oldname[PATH_MAX];
@@ -424,7 +415,7 @@ static int __cmd_record(int argc, const char **argv)
424 else 415 else
425 flags |= O_TRUNC; 416 flags |= O_TRUNC;
426 417
427 if (pipe_output) 418 if (record_opts.pipe_output)
428 output = STDOUT_FILENO; 419 output = STDOUT_FILENO;
429 else 420 else
430 output = open(output_name, flags, S_IRUSR | S_IWUSR); 421 output = open(output_name, flags, S_IRUSR | S_IWUSR);
@@ -470,57 +461,11 @@ static int __cmd_record(int argc, const char **argv)
470 mmap_pages = (512 * 1024) / page_size; 461 mmap_pages = (512 * 1024) / page_size;
471 462
472 if (forks) { 463 if (forks) {
473 child_pid = fork(); 464 err = perf_evlist__prepare_workload(evsel_list, &record_opts, argv);
474 if (child_pid < 0) { 465 if (err < 0) {
475 perror("failed to fork"); 466 pr_err("Couldn't run the workload!\n");
476 exit(-1); 467 goto out_delete_session;
477 }
478
479 if (!child_pid) {
480 if (pipe_output)
481 dup2(2, 1);
482 close(child_ready_pipe[0]);
483 close(go_pipe[1]);
484 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
485
486 /*
487 * Do a dummy execvp to get the PLT entry resolved,
488 * so we avoid the resolver overhead on the real
489 * execvp call.
490 */
491 execvp("", (char **)argv);
492
493 /*
494 * Tell the parent we're ready to go
495 */
496 close(child_ready_pipe[1]);
497
498 /*
499 * Wait until the parent tells us to go.
500 */
501 if (read(go_pipe[0], &buf, 1) == -1)
502 perror("unable to read pipe");
503
504 execvp(argv[0], (char **)argv);
505
506 perror(argv[0]);
507 kill(getppid(), SIGUSR1);
508 exit(-1);
509 }
510
511 if (!record_opts.system_wide && record_opts.target_tid == -1 && record_opts.target_pid == -1)
512 evsel_list->threads->map[0] = child_pid;
513
514 close(child_ready_pipe[1]);
515 close(go_pipe[0]);
516 /*
517 * wait for child to settle
518 */
519 if (read(child_ready_pipe[0], &buf, 1) == -1) {
520 perror("unable to read pipe");
521 exit(-1);
522 } 468 }
523 close(child_ready_pipe[0]);
524 } 469 }
525 470
526 open_counters(evsel_list); 471 open_counters(evsel_list);
@@ -530,7 +475,7 @@ static int __cmd_record(int argc, const char **argv)
530 */ 475 */
531 atexit(atexit_header); 476 atexit(atexit_header);
532 477
533 if (pipe_output) { 478 if (record_opts.pipe_output) {
534 err = perf_header__write_pipe(output); 479 err = perf_header__write_pipe(output);
535 if (err < 0) 480 if (err < 0)
536 return err; 481 return err;
@@ -543,7 +488,7 @@ static int __cmd_record(int argc, const char **argv)
543 488
544 post_processing_offset = lseek(output, 0, SEEK_CUR); 489 post_processing_offset = lseek(output, 0, SEEK_CUR);
545 490
546 if (pipe_output) { 491 if (record_opts.pipe_output) {
547 err = perf_session__synthesize_attrs(session, 492 err = perf_session__synthesize_attrs(session,
548 process_synthesized_event); 493 process_synthesized_event);
549 if (err < 0) { 494 if (err < 0) {
@@ -629,7 +574,7 @@ static int __cmd_record(int argc, const char **argv)
629 * Let the child rip 574 * Let the child rip
630 */ 575 */
631 if (forks) 576 if (forks)
632 close(go_pipe[1]); 577 perf_evlist__start_workload(evsel_list);
633 578
634 for (;;) { 579 for (;;) {
635 int hits = samples; 580 int hits = samples;