perf record: Fall back to cpu-clock-ticks if no PMU
authorIngo Molnar <mingo@elte.hu>
Sun, 7 Jun 2009 15:39:02 +0000 (17:39 +0200)
committerIngo Molnar <mingo@elte.hu>
Sun, 7 Jun 2009 15:39:02 +0000 (17:39 +0200)
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>
tools/perf/builtin-record.c
tools/perf/builtin-top.c

index aeab9c4..8786629 100644 (file)
@@ -37,6 +37,7 @@ static pid_t                  target_pid                      = -1;
 static int                     inherit                         = 1;
 static int                     force                           = 0;
 static int                     append_file                     = 0;
+static int                     verbose                         = 0;
 
 static long                    samples;
 static struct timeval          last_read;
@@ -349,17 +350,35 @@ static void create_counter(int counter, int cpu, pid_t pid)
 
        track = 0; /* only the first counter needs these */
 
+try_again:
        fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
 
        if (fd[nr_cpu][counter] < 0) {
                int err = errno;
 
-               error("syscall returned with %d (%s)\n",
+               if (verbose)
+                       error("sys_perf_counter_open() syscall returned with %d (%s)\n",
                                fd[nr_cpu][counter], strerror(err));
                if (err == EPERM)
-                       printf("Are you root?\n");
+                       die("Permission error - are you root?\n");
+
+               /*
+                * If it's cycles then fall back to hrtimer
+                * based cpu-clock-tick sw counter, which
+                * is always available even if no PMU support:
+                */
+               if (attr->type == PERF_TYPE_HARDWARE
+                       && attr->config == PERF_COUNT_CPU_CYCLES) {
+
+                       if (verbose)
+                               warning(" ... trying to fall back to cpu-clock-ticks\n");
+                       attr->type = PERF_TYPE_SOFTWARE;
+                       attr->config = PERF_COUNT_CPU_CLOCK;
+                       goto try_again;
+               }
                exit(-1);
        }
+
        assert(fd[nr_cpu][counter] >= 0);
        fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
 
@@ -519,6 +538,8 @@ static const struct option options[] = {
                    "profile at this frequency"),
        OPT_INTEGER('m', "mmap-pages", &mmap_pages,
                    "number of mmap data pages"),
+       OPT_BOOLEAN('v', "verbose", &verbose,
+                   "be more verbose (show counter open errors, etc)"),
        OPT_END()
 };
 
index 6da30a1..1f8c97d 100644 (file)
@@ -65,6 +65,7 @@ static int                    group                           =  0;
 static unsigned int            page_size;
 static unsigned int            mmap_pages                      = 16;
 static int                     freq                            =  0;
+static int                     verbose                         =  0;
 
 static char                    *sym_filter;
 static unsigned long           filter_start;
@@ -550,11 +551,12 @@ try_again:
        if (fd[i][counter] < 0) {
                int err = errno;
 
-               error("sys_perf_counter_open() syscall returned with %d (%s)\n",
-                       fd[i][counter], strerror(err));
+               if (verbose)
+                       error("sys_perf_counter_open() syscall returned with %d (%s)\n",
+                               fd[i][counter], strerror(err));
 
                if (err == EPERM)
-                       die(" No permission - are you root?\n");
+                       die("No permission - are you root?\n");
                /*
                 * If it's cycles then fall back to hrtimer
                 * based cpu-clock-tick sw counter, which
@@ -563,7 +565,9 @@ try_again:
                if (attr->type == PERF_TYPE_HARDWARE
                        && attr->config == PERF_COUNT_CPU_CYCLES) {
 
-                       warning(" ... trying to fall back to cpu-clock-ticks\n");
+                       if (verbose)
+                               warning(" ... trying to fall back to cpu-clock-ticks\n");
+
                        attr->type = PERF_TYPE_SOFTWARE;
                        attr->config = PERF_COUNT_CPU_CLOCK;
                        goto try_again;
@@ -673,6 +677,8 @@ static const struct option options[] = {
                    "profile at this frequency"),
        OPT_INTEGER('E', "entries", &print_entries,
                    "display this many functions"),
+       OPT_BOOLEAN('v', "verbose", &verbose,
+                   "be more verbose (show counter open errors, etc)"),
        OPT_END()
 };