aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/perf_counter/builtin-stat.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-06-06 03:58:57 -0400
committerIngo Molnar <mingo@elte.hu>2009-06-06 05:37:22 -0400
commita21ca2cac582886a3e95c8bb84ff7c52d4d15e54 (patch)
treed110005d81e46b1afb3204fbaacc132d0ec946ee /Documentation/perf_counter/builtin-stat.c
parent2f335a02b3c816e77e7df1d15b12e3bbb8f4c8f0 (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.c76
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
47static int system_wide = 0; 47static struct perf_counter_attr default_attrs[MAX_COUNTERS] = {
48static int inherit = 1;
49 48
50static __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
62static int default_interval = 100000; 60static int system_wide = 0;
63static int event_count[MAX_COUNTERS]; 61static int inherit = 1;
62
64static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 63static int fd[MAX_NR_CPUS][MAX_COUNTERS];
65 64
66static int target_pid = -1; 65static int target_pid = -1;
@@ -86,22 +85,16 @@ static __u64 walltime_nsecs;
86 85
87static void create_perfstat_counter(int counter) 86static 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 */
127static inline int nsec_counter(int counter) 120static 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];
300static const struct option options[] = { 298static 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
316int cmd_stat(int argc, const char **argv, const char *prefix) 312int 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);