aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
authorZhang, Yanmin <yanmin_zhang@linux.intel.com>2010-03-18 10:36:04 -0400
committerIngo Molnar <mingo@elte.hu>2010-03-18 11:21:11 -0400
commit46be604b5ba738d53e5f5314813a4e7092864baf (patch)
treee06fa3a1bc3ed6c2bd10c2379fa5478522477baa /tools/perf/builtin-record.c
parent6be2850effd6a8bae11d623c8c52e88d2fbc0e96 (diff)
perf record: Enable counters only when kernel is execing subcommand
'perf record' starts counters before subcommand is execed, so the statistics is not precise because it includes data of some preparation steps. I fix it with the patch. In addition, change the condition to fork/exec subcommand. If there is a subcommand parameter, perf always fork/exec it. The usage example is: # perf record -f -a sleep 10 So this command could collect statistics for 10 seconds precisely. User still could stop it by CTRL+C. Without the new capability, user could only input CTRL+C to stop it without precise time clock. Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Avi Kivity <avi@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Sheng Yang <sheng@linux.intel.com> Cc: oerg Roedel <joro@8bytes.org> Cc: Jes Sorensen <Jes.Sorensen@redhat.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Gleb Natapov <gleb@redhat.com> Cc: <zhiteng.huang@intel.com> Cc: Zachary Amsden <zamsden@redhat.com> LKML-Reference: <1268922965-14774-2-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c33
1 files changed, 15 insertions, 18 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 962cdbf44ae9..e2b35ad82a77 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -225,7 +225,7 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
225 return h_attr; 225 return h_attr;
226} 226}
227 227
228static void create_counter(int counter, int cpu, pid_t pid, bool forks) 228static void create_counter(int counter, int cpu, pid_t pid)
229{ 229{
230 char *filter = filters[counter]; 230 char *filter = filters[counter];
231 struct perf_event_attr *attr = attrs + counter; 231 struct perf_event_attr *attr = attrs + counter;
@@ -275,10 +275,10 @@ static void create_counter(int counter, int cpu, pid_t pid, bool forks)
275 attr->mmap = track; 275 attr->mmap = track;
276 attr->comm = track; 276 attr->comm = track;
277 attr->inherit = inherit; 277 attr->inherit = inherit;
278 attr->disabled = 1; 278 if (target_pid == -1 && !system_wide) {
279 279 attr->disabled = 1;
280 if (forks)
281 attr->enable_on_exec = 1; 280 attr->enable_on_exec = 1;
281 }
282 282
283try_again: 283try_again:
284 fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0); 284 fd[nr_cpu][counter] = sys_perf_event_open(attr, pid, cpu, group_fd, 0);
@@ -380,17 +380,15 @@ try_again:
380 exit(-1); 380 exit(-1);
381 } 381 }
382 } 382 }
383
384 ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE);
385} 383}
386 384
387static void open_counters(int cpu, pid_t pid, bool forks) 385static void open_counters(int cpu, pid_t pid)
388{ 386{
389 int counter; 387 int counter;
390 388
391 group_fd = -1; 389 group_fd = -1;
392 for (counter = 0; counter < nr_counters; counter++) 390 for (counter = 0; counter < nr_counters; counter++)
393 create_counter(counter, cpu, pid, forks); 391 create_counter(counter, cpu, pid);
394 392
395 nr_cpu++; 393 nr_cpu++;
396} 394}
@@ -425,7 +423,7 @@ static int __cmd_record(int argc, const char **argv)
425 int err; 423 int err;
426 unsigned long waking = 0; 424 unsigned long waking = 0;
427 int child_ready_pipe[2], go_pipe[2]; 425 int child_ready_pipe[2], go_pipe[2];
428 const bool forks = target_pid == -1 && argc > 0; 426 const bool forks = argc > 0;
429 char buf; 427 char buf;
430 428
431 page_size = sysconf(_SC_PAGE_SIZE); 429 page_size = sysconf(_SC_PAGE_SIZE);
@@ -496,13 +494,13 @@ static int __cmd_record(int argc, const char **argv)
496 atexit(atexit_header); 494 atexit(atexit_header);
497 495
498 if (forks) { 496 if (forks) {
499 pid = fork(); 497 child_pid = fork();
500 if (pid < 0) { 498 if (pid < 0) {
501 perror("failed to fork"); 499 perror("failed to fork");
502 exit(-1); 500 exit(-1);
503 } 501 }
504 502
505 if (!pid) { 503 if (!child_pid) {
506 close(child_ready_pipe[0]); 504 close(child_ready_pipe[0]);
507 close(go_pipe[1]); 505 close(go_pipe[1]);
508 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 506 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
@@ -531,11 +529,6 @@ static int __cmd_record(int argc, const char **argv)
531 exit(-1); 529 exit(-1);
532 } 530 }
533 531
534 child_pid = pid;
535
536 if (!system_wide)
537 target_pid = pid;
538
539 close(child_ready_pipe[1]); 532 close(child_ready_pipe[1]);
540 close(go_pipe[0]); 533 close(go_pipe[0]);
541 /* 534 /*
@@ -548,13 +541,17 @@ static int __cmd_record(int argc, const char **argv)
548 close(child_ready_pipe[0]); 541 close(child_ready_pipe[0]);
549 } 542 }
550 543
544 if (forks && target_pid == -1 && !system_wide)
545 pid = child_pid;
546 else
547 pid = target_pid;
551 548
552 if ((!system_wide && !inherit) || profile_cpu != -1) { 549 if ((!system_wide && !inherit) || profile_cpu != -1) {
553 open_counters(profile_cpu, target_pid, forks); 550 open_counters(profile_cpu, pid);
554 } else { 551 } else {
555 nr_cpus = read_cpu_map(); 552 nr_cpus = read_cpu_map();
556 for (i = 0; i < nr_cpus; i++) 553 for (i = 0; i < nr_cpus; i++)
557 open_counters(cpumap[i], target_pid, forks); 554 open_counters(cpumap[i], pid);
558 } 555 }
559 556
560 if (file_new) { 557 if (file_new) {