aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-06-07 11:31:52 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-07 11:31:52 -0400
commit716c69fecacd42f2a304a97158e04af2786a3f65 (patch)
tree5f86a0ce67ba87595d14a6fd6d5f59f8f7cf1f56
parent743ee1f80434138495bbb95ffb897acf46b51d54 (diff)
perf top: Fall back to cpu-clock-tick hrtimer sampling if no cycle counter available
On architectures/CPUs without PMU support but with perfcounters enabled 'perf top' 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 is 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-top.c113
-rw-r--r--tools/perf/util/usage.c10
2 files changed, 73 insertions, 50 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fdc1d5863b01..6da30a140e86 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -527,58 +527,81 @@ static void mmap_read(void)
527 } 527 }
528} 528}
529 529
530static int __cmd_top(void) 530int nr_poll;
531int group_fd;
532
533static void start_counter(int i, int counter)
531{ 534{
532 struct perf_counter_attr *attr; 535 struct perf_counter_attr *attr;
533 pthread_t thread;
534 int i, counter, group_fd, nr_poll = 0;
535 unsigned int cpu; 536 unsigned int cpu;
537
538 cpu = profile_cpu;
539 if (target_pid == -1 && profile_cpu == -1)
540 cpu = i;
541
542 attr = attrs + counter;
543
544 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
545 attr->freq = freq;
546
547try_again:
548 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
549
550 if (fd[i][counter] < 0) {
551 int err = errno;
552
553 error("sys_perf_counter_open() syscall returned with %d (%s)\n",
554 fd[i][counter], strerror(err));
555
556 if (err == EPERM)
557 die(" No permission - are you root?\n");
558 /*
559 * If it's cycles then fall back to hrtimer
560 * based cpu-clock-tick sw counter, which
561 * is always available even if no PMU support:
562 */
563 if (attr->type == PERF_TYPE_HARDWARE
564 && attr->config == PERF_COUNT_CPU_CYCLES) {
565
566 warning(" ... trying to fall back to cpu-clock-ticks\n");
567 attr->type = PERF_TYPE_SOFTWARE;
568 attr->config = PERF_COUNT_CPU_CLOCK;
569 goto try_again;
570 }
571 exit(-1);
572 }
573 assert(fd[i][counter] >= 0);
574 fcntl(fd[i][counter], F_SETFL, O_NONBLOCK);
575
576 /*
577 * First counter acts as the group leader:
578 */
579 if (group && group_fd == -1)
580 group_fd = fd[i][counter];
581
582 event_array[nr_poll].fd = fd[i][counter];
583 event_array[nr_poll].events = POLLIN;
584 nr_poll++;
585
586 mmap_array[i][counter].counter = counter;
587 mmap_array[i][counter].prev = 0;
588 mmap_array[i][counter].mask = mmap_pages*page_size - 1;
589 mmap_array[i][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
590 PROT_READ, MAP_SHARED, fd[i][counter], 0);
591 if (mmap_array[i][counter].base == MAP_FAILED)
592 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
593}
594
595static int __cmd_top(void)
596{
597 pthread_t thread;
598 int i, counter;
536 int ret; 599 int ret;
537 600
538 for (i = 0; i < nr_cpus; i++) { 601 for (i = 0; i < nr_cpus; i++) {
539 group_fd = -1; 602 group_fd = -1;
540 for (counter = 0; counter < nr_counters; counter++) { 603 for (counter = 0; counter < nr_counters; counter++)
541 604 start_counter(i, counter);
542 cpu = profile_cpu;
543 if (target_pid == -1 && profile_cpu == -1)
544 cpu = i;
545
546 attr = attrs + counter;
547
548 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
549 attr->freq = freq;
550
551 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
552 if (fd[i][counter] < 0) {
553 int err = errno;
554
555 error("syscall returned with %d (%s)\n",
556 fd[i][counter], strerror(err));
557 if (err == EPERM)
558 printf("Are you root?\n");
559 exit(-1);
560 }
561 assert(fd[i][counter] >= 0);
562 fcntl(fd[i][counter], F_SETFL, O_NONBLOCK);
563
564 /*
565 * First counter acts as the group leader:
566 */
567 if (group && group_fd == -1)
568 group_fd = fd[i][counter];
569
570 event_array[nr_poll].fd = fd[i][counter];
571 event_array[nr_poll].events = POLLIN;
572 nr_poll++;
573
574 mmap_array[i][counter].counter = counter;
575 mmap_array[i][counter].prev = 0;
576 mmap_array[i][counter].mask = mmap_pages*page_size - 1;
577 mmap_array[i][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
578 PROT_READ, MAP_SHARED, fd[i][counter], 0);
579 if (mmap_array[i][counter].base == MAP_FAILED)
580 die("failed to mmap with %d (%s)\n", errno, strerror(errno));
581 }
582 } 605 }
583 606
584 /* Wait for a minimal set of events before starting the snapshot */ 607 /* Wait for a minimal set of events before starting the snapshot */
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index 2cad286e4371..e16bf9a707e8 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -9,29 +9,29 @@ static void report(const char *prefix, const char *err, va_list params)
9{ 9{
10 char msg[1024]; 10 char msg[1024];
11 vsnprintf(msg, sizeof(msg), err, params); 11 vsnprintf(msg, sizeof(msg), err, params);
12 fprintf(stderr, "%s%s\n", prefix, msg); 12 fprintf(stderr, " %s%s\n", prefix, msg);
13} 13}
14 14
15static NORETURN void usage_builtin(const char *err) 15static NORETURN void usage_builtin(const char *err)
16{ 16{
17 fprintf(stderr, "\n usage: %s\n", err); 17 fprintf(stderr, "\n Usage: %s\n", err);
18 exit(129); 18 exit(129);
19} 19}
20 20
21static NORETURN void die_builtin(const char *err, va_list params) 21static NORETURN void die_builtin(const char *err, va_list params)
22{ 22{
23 report("fatal: ", err, params); 23 report(" Fatal: ", err, params);
24 exit(128); 24 exit(128);
25} 25}
26 26
27static void error_builtin(const char *err, va_list params) 27static void error_builtin(const char *err, va_list params)
28{ 28{
29 report("error: ", err, params); 29 report(" Error: ", err, params);
30} 30}
31 31
32static void warn_builtin(const char *warn, va_list params) 32static void warn_builtin(const char *warn, va_list params)
33{ 33{
34 report("warning: ", warn, params); 34 report(" Warning: ", warn, params);
35} 35}
36 36
37/* If we are in a dlopen()ed .so write to a global variable would segfault 37/* If we are in a dlopen()ed .so write to a global variable would segfault