diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-06-07 11:39:02 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-07 11:39:02 -0400 |
commit | 3da297a60f7e8840f79f7d0b343af078890939ea (patch) | |
tree | c3b5b39be914caa30f1eb820afbdc228d531e25e | |
parent | 716c69fecacd42f2a304a97158e04af2786a3f65 (diff) |
perf record: Fall back to cpu-clock-ticks if no PMU
On architectures/CPUs without PMU support but with perfcounters
enabled 'perf record' currently fails because it cannot create a
cycle based hw-perfcounter.
Fall back to the cpu-clock-tick sw-perfcounter in this case, which
is hrtimer based and will always work (as long as perfcounters
are enabled).
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | tools/perf/builtin-record.c | 25 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 14 |
2 files changed, 33 insertions, 6 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index aeab9c4b15e4..87866294a0e6 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -37,6 +37,7 @@ static pid_t target_pid = -1; | |||
37 | static int inherit = 1; | 37 | static int inherit = 1; |
38 | static int force = 0; | 38 | static int force = 0; |
39 | static int append_file = 0; | 39 | static int append_file = 0; |
40 | static int verbose = 0; | ||
40 | 41 | ||
41 | static long samples; | 42 | static long samples; |
42 | static struct timeval last_read; | 43 | static struct timeval last_read; |
@@ -349,17 +350,35 @@ static void create_counter(int counter, int cpu, pid_t pid) | |||
349 | 350 | ||
350 | track = 0; /* only the first counter needs these */ | 351 | track = 0; /* only the first counter needs these */ |
351 | 352 | ||
353 | try_again: | ||
352 | fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); | 354 | fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0); |
353 | 355 | ||
354 | if (fd[nr_cpu][counter] < 0) { | 356 | if (fd[nr_cpu][counter] < 0) { |
355 | int err = errno; | 357 | int err = errno; |
356 | 358 | ||
357 | error("syscall returned with %d (%s)\n", | 359 | if (verbose) |
360 | error("sys_perf_counter_open() syscall returned with %d (%s)\n", | ||
358 | fd[nr_cpu][counter], strerror(err)); | 361 | fd[nr_cpu][counter], strerror(err)); |
359 | if (err == EPERM) | 362 | if (err == EPERM) |
360 | printf("Are you root?\n"); | 363 | die("Permission error - are you root?\n"); |
364 | |||
365 | /* | ||
366 | * If it's cycles then fall back to hrtimer | ||
367 | * based cpu-clock-tick sw counter, which | ||
368 | * is always available even if no PMU support: | ||
369 | */ | ||
370 | if (attr->type == PERF_TYPE_HARDWARE | ||
371 | && attr->config == PERF_COUNT_CPU_CYCLES) { | ||
372 | |||
373 | if (verbose) | ||
374 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | ||
375 | attr->type = PERF_TYPE_SOFTWARE; | ||
376 | attr->config = PERF_COUNT_CPU_CLOCK; | ||
377 | goto try_again; | ||
378 | } | ||
361 | exit(-1); | 379 | exit(-1); |
362 | } | 380 | } |
381 | |||
363 | assert(fd[nr_cpu][counter] >= 0); | 382 | assert(fd[nr_cpu][counter] >= 0); |
364 | fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); | 383 | fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK); |
365 | 384 | ||
@@ -519,6 +538,8 @@ static const struct option options[] = { | |||
519 | "profile at this frequency"), | 538 | "profile at this frequency"), |
520 | OPT_INTEGER('m', "mmap-pages", &mmap_pages, | 539 | OPT_INTEGER('m', "mmap-pages", &mmap_pages, |
521 | "number of mmap data pages"), | 540 | "number of mmap data pages"), |
541 | OPT_BOOLEAN('v', "verbose", &verbose, | ||
542 | "be more verbose (show counter open errors, etc)"), | ||
522 | OPT_END() | 543 | OPT_END() |
523 | }; | 544 | }; |
524 | 545 | ||
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 6da30a140e86..1f8c97d5c32e 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -65,6 +65,7 @@ static int group = 0; | |||
65 | static unsigned int page_size; | 65 | static unsigned int page_size; |
66 | static unsigned int mmap_pages = 16; | 66 | static unsigned int mmap_pages = 16; |
67 | static int freq = 0; | 67 | static int freq = 0; |
68 | static int verbose = 0; | ||
68 | 69 | ||
69 | static char *sym_filter; | 70 | static char *sym_filter; |
70 | static unsigned long filter_start; | 71 | static unsigned long filter_start; |
@@ -550,11 +551,12 @@ try_again: | |||
550 | if (fd[i][counter] < 0) { | 551 | if (fd[i][counter] < 0) { |
551 | int err = errno; | 552 | int err = errno; |
552 | 553 | ||
553 | error("sys_perf_counter_open() syscall returned with %d (%s)\n", | 554 | if (verbose) |
554 | fd[i][counter], strerror(err)); | 555 | error("sys_perf_counter_open() syscall returned with %d (%s)\n", |
556 | fd[i][counter], strerror(err)); | ||
555 | 557 | ||
556 | if (err == EPERM) | 558 | if (err == EPERM) |
557 | die(" No permission - are you root?\n"); | 559 | die("No permission - are you root?\n"); |
558 | /* | 560 | /* |
559 | * If it's cycles then fall back to hrtimer | 561 | * If it's cycles then fall back to hrtimer |
560 | * based cpu-clock-tick sw counter, which | 562 | * based cpu-clock-tick sw counter, which |
@@ -563,7 +565,9 @@ try_again: | |||
563 | if (attr->type == PERF_TYPE_HARDWARE | 565 | if (attr->type == PERF_TYPE_HARDWARE |
564 | && attr->config == PERF_COUNT_CPU_CYCLES) { | 566 | && attr->config == PERF_COUNT_CPU_CYCLES) { |
565 | 567 | ||
566 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | 568 | if (verbose) |
569 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | ||
570 | |||
567 | attr->type = PERF_TYPE_SOFTWARE; | 571 | attr->type = PERF_TYPE_SOFTWARE; |
568 | attr->config = PERF_COUNT_CPU_CLOCK; | 572 | attr->config = PERF_COUNT_CPU_CLOCK; |
569 | goto try_again; | 573 | goto try_again; |
@@ -673,6 +677,8 @@ static const struct option options[] = { | |||
673 | "profile at this frequency"), | 677 | "profile at this frequency"), |
674 | OPT_INTEGER('E', "entries", &print_entries, | 678 | OPT_INTEGER('E', "entries", &print_entries, |
675 | "display this many functions"), | 679 | "display this many functions"), |
680 | OPT_BOOLEAN('v', "verbose", &verbose, | ||
681 | "be more verbose (show counter open errors, etc)"), | ||
676 | OPT_END() | 682 | OPT_END() |
677 | }; | 683 | }; |
678 | 684 | ||