diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-06-06 03:58:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-06 05:37:22 -0400 |
commit | a21ca2cac582886a3e95c8bb84ff7c52d4d15e54 (patch) | |
tree | d110005d81e46b1afb3204fbaacc132d0ec946ee /Documentation/perf_counter/builtin-stat.c | |
parent | 2f335a02b3c816e77e7df1d15b12e3bbb8f4c8f0 (diff) |
perf_counter: Separate out attr->type from attr->config
Counter type is a frequently used value and we do a lot of
bit juggling by encoding and decoding it from attr->config.
Clean this up by creating a separate attr->type field.
Also clean up the various similarly complex user-space bits
all around counter attribute management.
The net improvement is significant, and it will be easier
to add a new major type (which is what triggered this cleanup).
(This changes the ABI, all tools are adapted.)
(PowerPC build-tested.)
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter/builtin-stat.c')
-rw-r--r-- | Documentation/perf_counter/builtin-stat.c | 76 |
1 files changed, 32 insertions, 44 deletions
diff --git a/Documentation/perf_counter/builtin-stat.c b/Documentation/perf_counter/builtin-stat.c index 4fc0d80440e7..9711e5524233 100644 --- a/Documentation/perf_counter/builtin-stat.c +++ b/Documentation/perf_counter/builtin-stat.c | |||
@@ -44,23 +44,22 @@ | |||
44 | 44 | ||
45 | #include <sys/prctl.h> | 45 | #include <sys/prctl.h> |
46 | 46 | ||
47 | static int system_wide = 0; | 47 | static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { |
48 | static int inherit = 1; | ||
49 | 48 | ||
50 | static __u64 default_event_id[MAX_COUNTERS] = { | 49 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_TASK_CLOCK }, |
51 | EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK), | 50 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_CONTEXT_SWITCHES }, |
52 | EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CONTEXT_SWITCHES), | 51 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_CPU_MIGRATIONS }, |
53 | EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_MIGRATIONS), | 52 | { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_PAGE_FAULTS }, |
54 | EID(PERF_TYPE_SOFTWARE, PERF_COUNT_PAGE_FAULTS), | ||
55 | 53 | ||
56 | EID(PERF_TYPE_HARDWARE, PERF_COUNT_CPU_CYCLES), | 54 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CPU_CYCLES }, |
57 | EID(PERF_TYPE_HARDWARE, PERF_COUNT_INSTRUCTIONS), | 55 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_INSTRUCTIONS }, |
58 | EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_REFERENCES), | 56 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CACHE_REFERENCES }, |
59 | EID(PERF_TYPE_HARDWARE, PERF_COUNT_CACHE_MISSES), | 57 | { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_CACHE_MISSES }, |
60 | }; | 58 | }; |
61 | 59 | ||
62 | static int default_interval = 100000; | 60 | static int system_wide = 0; |
63 | static int event_count[MAX_COUNTERS]; | 61 | static int inherit = 1; |
62 | |||
64 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; | 63 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; |
65 | 64 | ||
66 | static int target_pid = -1; | 65 | static int target_pid = -1; |
@@ -86,22 +85,16 @@ static __u64 walltime_nsecs; | |||
86 | 85 | ||
87 | static void create_perfstat_counter(int counter) | 86 | static void create_perfstat_counter(int counter) |
88 | { | 87 | { |
89 | struct perf_counter_attr attr; | 88 | struct perf_counter_attr *attr = attrs + counter; |
90 | |||
91 | memset(&attr, 0, sizeof(attr)); | ||
92 | attr.config = event_id[counter]; | ||
93 | attr.sample_type = 0; | ||
94 | attr.exclude_kernel = event_mask[counter] & EVENT_MASK_KERNEL; | ||
95 | attr.exclude_user = event_mask[counter] & EVENT_MASK_USER; | ||
96 | 89 | ||
97 | if (scale) | 90 | if (scale) |
98 | attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | 91 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | |
99 | PERF_FORMAT_TOTAL_TIME_RUNNING; | 92 | PERF_FORMAT_TOTAL_TIME_RUNNING; |
100 | 93 | ||
101 | if (system_wide) { | 94 | if (system_wide) { |
102 | int cpu; | 95 | int cpu; |
103 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | 96 | for (cpu = 0; cpu < nr_cpus; cpu ++) { |
104 | fd[cpu][counter] = sys_perf_counter_open(&attr, -1, cpu, -1, 0); | 97 | fd[cpu][counter] = sys_perf_counter_open(attr, -1, cpu, -1, 0); |
105 | if (fd[cpu][counter] < 0) { | 98 | if (fd[cpu][counter] < 0) { |
106 | printf("perfstat error: syscall returned with %d (%s)\n", | 99 | printf("perfstat error: syscall returned with %d (%s)\n", |
107 | fd[cpu][counter], strerror(errno)); | 100 | fd[cpu][counter], strerror(errno)); |
@@ -109,10 +102,10 @@ static void create_perfstat_counter(int counter) | |||
109 | } | 102 | } |
110 | } | 103 | } |
111 | } else { | 104 | } else { |
112 | attr.inherit = inherit; | 105 | attr->inherit = inherit; |
113 | attr.disabled = 1; | 106 | attr->disabled = 1; |
114 | 107 | ||
115 | fd[0][counter] = sys_perf_counter_open(&attr, 0, -1, -1, 0); | 108 | fd[0][counter] = sys_perf_counter_open(attr, 0, -1, -1, 0); |
116 | if (fd[0][counter] < 0) { | 109 | if (fd[0][counter] < 0) { |
117 | printf("perfstat error: syscall returned with %d (%s)\n", | 110 | printf("perfstat error: syscall returned with %d (%s)\n", |
118 | fd[0][counter], strerror(errno)); | 111 | fd[0][counter], strerror(errno)); |
@@ -126,9 +119,13 @@ static void create_perfstat_counter(int counter) | |||
126 | */ | 119 | */ |
127 | static inline int nsec_counter(int counter) | 120 | static inline int nsec_counter(int counter) |
128 | { | 121 | { |
129 | if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_CPU_CLOCK)) | 122 | if (attrs[counter].type != PERF_TYPE_SOFTWARE) |
123 | return 0; | ||
124 | |||
125 | if (attrs[counter].config == PERF_COUNT_CPU_CLOCK) | ||
130 | return 1; | 126 | return 1; |
131 | if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK)) | 127 | |
128 | if (attrs[counter].config == PERF_COUNT_TASK_CLOCK) | ||
132 | return 1; | 129 | return 1; |
133 | 130 | ||
134 | return 0; | 131 | return 0; |
@@ -177,7 +174,8 @@ static void read_counter(int counter) | |||
177 | /* | 174 | /* |
178 | * Save the full runtime - to allow normalization during printout: | 175 | * Save the full runtime - to allow normalization during printout: |
179 | */ | 176 | */ |
180 | if (event_id[counter] == EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK)) | 177 | if (attrs[counter].type == PERF_TYPE_SOFTWARE && |
178 | attrs[counter].config == PERF_COUNT_TASK_CLOCK) | ||
181 | runtime_nsecs = count[0]; | 179 | runtime_nsecs = count[0]; |
182 | } | 180 | } |
183 | 181 | ||
@@ -203,8 +201,8 @@ static void print_counter(int counter) | |||
203 | 201 | ||
204 | fprintf(stderr, " %14.6f %-20s", | 202 | fprintf(stderr, " %14.6f %-20s", |
205 | msecs, event_name(counter)); | 203 | msecs, event_name(counter)); |
206 | if (event_id[counter] == | 204 | if (attrs[counter].type == PERF_TYPE_SOFTWARE && |
207 | EID(PERF_TYPE_SOFTWARE, PERF_COUNT_TASK_CLOCK)) { | 205 | attrs[counter].config == PERF_COUNT_TASK_CLOCK) { |
208 | 206 | ||
209 | fprintf(stderr, " # %11.3f CPU utilization factor", | 207 | fprintf(stderr, " # %11.3f CPU utilization factor", |
210 | (double)count[0] / (double)walltime_nsecs); | 208 | (double)count[0] / (double)walltime_nsecs); |
@@ -300,8 +298,6 @@ static char events_help_msg[EVENTS_HELP_MAX]; | |||
300 | static const struct option options[] = { | 298 | static const struct option options[] = { |
301 | OPT_CALLBACK('e', "event", NULL, "event", | 299 | OPT_CALLBACK('e', "event", NULL, "event", |
302 | events_help_msg, parse_events), | 300 | events_help_msg, parse_events), |
303 | OPT_INTEGER('c', "count", &default_interval, | ||
304 | "event period to sample"), | ||
305 | OPT_BOOLEAN('i', "inherit", &inherit, | 301 | OPT_BOOLEAN('i', "inherit", &inherit, |
306 | "child tasks inherit counters"), | 302 | "child tasks inherit counters"), |
307 | OPT_INTEGER('p', "pid", &target_pid, | 303 | OPT_INTEGER('p', "pid", &target_pid, |
@@ -315,27 +311,19 @@ static const struct option options[] = { | |||
315 | 311 | ||
316 | int cmd_stat(int argc, const char **argv, const char *prefix) | 312 | int cmd_stat(int argc, const char **argv, const char *prefix) |
317 | { | 313 | { |
318 | int counter; | ||
319 | |||
320 | page_size = sysconf(_SC_PAGE_SIZE); | 314 | page_size = sysconf(_SC_PAGE_SIZE); |
321 | 315 | ||
322 | create_events_help(events_help_msg); | 316 | create_events_help(events_help_msg); |
323 | memcpy(event_id, default_event_id, sizeof(default_event_id)); | 317 | |
318 | memcpy(attrs, default_attrs, sizeof(attrs)); | ||
324 | 319 | ||
325 | argc = parse_options(argc, argv, options, stat_usage, 0); | 320 | argc = parse_options(argc, argv, options, stat_usage, 0); |
326 | if (!argc) | 321 | if (!argc) |
327 | usage_with_options(stat_usage, options); | 322 | usage_with_options(stat_usage, options); |
328 | 323 | ||
329 | if (!nr_counters) { | 324 | if (!nr_counters) |
330 | nr_counters = 8; | 325 | nr_counters = 8; |
331 | } | ||
332 | |||
333 | for (counter = 0; counter < nr_counters; counter++) { | ||
334 | if (event_count[counter]) | ||
335 | continue; | ||
336 | 326 | ||
337 | event_count[counter] = default_interval; | ||
338 | } | ||
339 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | 327 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); |
340 | assert(nr_cpus <= MAX_NR_CPUS); | 328 | assert(nr_cpus <= MAX_NR_CPUS); |
341 | assert(nr_cpus >= 0); | 329 | assert(nr_cpus >= 0); |