Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3da297a6 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

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: default avatarIngo Molnar <mingo@elte.hu>
parent 716c69fe
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -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()
};

+10 −4
Original line number Diff line number Diff line
@@ -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,6 +551,7 @@ static void start_counter(int i, int counter)
	if (fd[i][counter] < 0) {
		int err = errno;

		if (verbose)
			error("sys_perf_counter_open() syscall returned with %d (%s)\n",
				fd[i][counter], strerror(err));

@@ -563,7 +565,9 @@ static void start_counter(int i, int counter)
		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;
@@ -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()
};