diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 93 |
1 files changed, 57 insertions, 36 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 3eeef339c78..ac5ddfff445 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -17,55 +17,51 @@ | |||
17 | #include "util/header.h" | 17 | #include "util/header.h" |
18 | #include "util/event.h" | 18 | #include "util/event.h" |
19 | #include "util/debug.h" | 19 | #include "util/debug.h" |
20 | #include "util/trace-event.h" | ||
21 | 20 | ||
22 | #include <unistd.h> | 21 | #include <unistd.h> |
23 | #include <sched.h> | 22 | #include <sched.h> |
24 | 23 | ||
25 | #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) | ||
26 | #define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) | ||
27 | |||
28 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; | 24 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; |
29 | 25 | ||
30 | static long default_interval = 100000; | 26 | static long default_interval = 0; |
31 | 27 | ||
32 | static int nr_cpus = 0; | 28 | static int nr_cpus = 0; |
33 | static unsigned int page_size; | 29 | static unsigned int page_size; |
34 | static unsigned int mmap_pages = 128; | 30 | static unsigned int mmap_pages = 128; |
35 | static int freq = 0; | 31 | static int freq = 1000; |
36 | static int output; | 32 | static int output; |
37 | static const char *output_name = "perf.data"; | 33 | static const char *output_name = "perf.data"; |
38 | static int group = 0; | 34 | static int group = 0; |
39 | static unsigned int realtime_prio = 0; | 35 | static unsigned int realtime_prio = 0; |
40 | static int raw_samples = 0; | 36 | static int raw_samples = 0; |
41 | static int system_wide = 0; | 37 | static int system_wide = 0; |
42 | static int profile_cpu = -1; | 38 | static int profile_cpu = -1; |
43 | static pid_t target_pid = -1; | 39 | static pid_t target_pid = -1; |
44 | static pid_t child_pid = -1; | 40 | static pid_t child_pid = -1; |
45 | static int inherit = 1; | 41 | static int inherit = 1; |
46 | static int force = 0; | 42 | static int force = 0; |
47 | static int append_file = 0; | 43 | static int append_file = 0; |
48 | static int call_graph = 0; | 44 | static int call_graph = 0; |
49 | static int inherit_stat = 0; | 45 | static int inherit_stat = 0; |
50 | static int no_samples = 0; | 46 | static int no_samples = 0; |
51 | static int sample_address = 0; | 47 | static int sample_address = 0; |
52 | static int multiplex = 0; | 48 | static int multiplex = 0; |
53 | static int multiplex_fd = -1; | 49 | static int multiplex_fd = -1; |
54 | 50 | ||
55 | static long samples; | 51 | static long samples = 0; |
56 | static struct timeval last_read; | 52 | static struct timeval last_read; |
57 | static struct timeval this_read; | 53 | static struct timeval this_read; |
58 | 54 | ||
59 | static u64 bytes_written; | 55 | static u64 bytes_written = 0; |
60 | 56 | ||
61 | static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; | 57 | static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; |
62 | 58 | ||
63 | static int nr_poll; | 59 | static int nr_poll = 0; |
64 | static int nr_cpu; | 60 | static int nr_cpu = 0; |
65 | 61 | ||
66 | static int file_new = 1; | 62 | static int file_new = 1; |
67 | 63 | ||
68 | struct perf_header *header; | 64 | struct perf_header *header = NULL; |
69 | 65 | ||
70 | struct mmap_data { | 66 | struct mmap_data { |
71 | int counter; | 67 | int counter; |
@@ -375,9 +371,11 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n | |||
375 | 371 | ||
376 | static void create_counter(int counter, int cpu, pid_t pid) | 372 | static void create_counter(int counter, int cpu, pid_t pid) |
377 | { | 373 | { |
374 | char *filter = filters[counter]; | ||
378 | struct perf_event_attr *attr = attrs + counter; | 375 | struct perf_event_attr *attr = attrs + counter; |
379 | struct perf_header_attr *h_attr; | 376 | struct perf_header_attr *h_attr; |
380 | int track = !counter; /* only the first counter needs these */ | 377 | int track = !counter; /* only the first counter needs these */ |
378 | int ret; | ||
381 | struct { | 379 | struct { |
382 | u64 count; | 380 | u64 count; |
383 | u64 time_enabled; | 381 | u64 time_enabled; |
@@ -480,7 +478,6 @@ try_again: | |||
480 | multiplex_fd = fd[nr_cpu][counter]; | 478 | multiplex_fd = fd[nr_cpu][counter]; |
481 | 479 | ||
482 | if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { | 480 | if (multiplex && fd[nr_cpu][counter] != multiplex_fd) { |
483 | int ret; | ||
484 | 481 | ||
485 | ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); | 482 | ret = ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_SET_OUTPUT, multiplex_fd); |
486 | assert(ret != -1); | 483 | assert(ret != -1); |
@@ -500,6 +497,16 @@ try_again: | |||
500 | } | 497 | } |
501 | } | 498 | } |
502 | 499 | ||
500 | if (filter != NULL) { | ||
501 | ret = ioctl(fd[nr_cpu][counter], | ||
502 | PERF_EVENT_IOC_SET_FILTER, filter); | ||
503 | if (ret) { | ||
504 | error("failed to set filter with %d (%s)\n", errno, | ||
505 | strerror(errno)); | ||
506 | exit(-1); | ||
507 | } | ||
508 | } | ||
509 | |||
503 | ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); | 510 | ioctl(fd[nr_cpu][counter], PERF_EVENT_IOC_ENABLE); |
504 | } | 511 | } |
505 | 512 | ||
@@ -566,17 +573,17 @@ static int __cmd_record(int argc, const char **argv) | |||
566 | else | 573 | else |
567 | header = perf_header__new(); | 574 | header = perf_header__new(); |
568 | 575 | ||
569 | |||
570 | if (raw_samples) { | 576 | if (raw_samples) { |
571 | read_tracing_data(attrs, nr_counters); | 577 | perf_header__feat_trace_info(header); |
572 | } else { | 578 | } else { |
573 | for (i = 0; i < nr_counters; i++) { | 579 | for (i = 0; i < nr_counters; i++) { |
574 | if (attrs[i].sample_type & PERF_SAMPLE_RAW) { | 580 | if (attrs[i].sample_type & PERF_SAMPLE_RAW) { |
575 | read_tracing_data(attrs, nr_counters); | 581 | perf_header__feat_trace_info(header); |
576 | break; | 582 | break; |
577 | } | 583 | } |
578 | } | 584 | } |
579 | } | 585 | } |
586 | |||
580 | atexit(atexit_header); | 587 | atexit(atexit_header); |
581 | 588 | ||
582 | if (!system_wide) { | 589 | if (!system_wide) { |
@@ -623,7 +630,7 @@ static int __cmd_record(int argc, const char **argv) | |||
623 | 630 | ||
624 | param.sched_priority = realtime_prio; | 631 | param.sched_priority = realtime_prio; |
625 | if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { | 632 | if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { |
626 | printf("Could not set realtime priority.\n"); | 633 | pr_err("Could not set realtime priority.\n"); |
627 | exit(-1); | 634 | exit(-1); |
628 | } | 635 | } |
629 | } | 636 | } |
@@ -677,6 +684,8 @@ static const struct option options[] = { | |||
677 | OPT_CALLBACK('e', "event", NULL, "event", | 684 | OPT_CALLBACK('e', "event", NULL, "event", |
678 | "event selector. use 'perf list' to list available events", | 685 | "event selector. use 'perf list' to list available events", |
679 | parse_events), | 686 | parse_events), |
687 | OPT_CALLBACK(0, "filter", NULL, "filter", | ||
688 | "event filter", parse_filter), | ||
680 | OPT_INTEGER('p', "pid", &target_pid, | 689 | OPT_INTEGER('p', "pid", &target_pid, |
681 | "record events on existing pid"), | 690 | "record events on existing pid"), |
682 | OPT_INTEGER('r', "realtime", &realtime_prio, | 691 | OPT_INTEGER('r', "realtime", &realtime_prio, |
@@ -731,6 +740,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __used) | |||
731 | attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; | 740 | attrs[0].config = PERF_COUNT_HW_CPU_CYCLES; |
732 | } | 741 | } |
733 | 742 | ||
743 | /* | ||
744 | * User specified count overrides default frequency. | ||
745 | */ | ||
746 | if (default_interval) | ||
747 | freq = 0; | ||
748 | else if (freq) { | ||
749 | default_interval = freq; | ||
750 | } else { | ||
751 | fprintf(stderr, "frequency and count are zero, aborting\n"); | ||
752 | exit(EXIT_FAILURE); | ||
753 | } | ||
754 | |||
734 | for (counter = 0; counter < nr_counters; counter++) { | 755 | for (counter = 0; counter < nr_counters; counter++) { |
735 | if (attrs[counter].sample_period) | 756 | if (attrs[counter].sample_period) |
736 | continue; | 757 | continue; |