diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-23 16:49:25 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-06 03:30:29 -0400 |
commit | 383c5f8cd7d253be0017d8d5a39cbb78aaf70206 (patch) | |
tree | a93de6088c2748daf92cdc91426dd0ec47f25b29 /Documentation | |
parent | bcbcb37cdb67d8100acfa66df40c4d636c28c4d1 (diff) |
perf_counter tools: tidy up in-kernel dependencies
Remove now unified perfstat.c and perf_counter.h, and link to the
in-kernel perf_counter.h.
Cc: Wu Fengguang <fengguang.wu@intel.com>
Cc: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Orig-LKML-Reference: <20090323172417.677932499@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation')
-rw-r--r-- | Documentation/perf_counter/Makefile | 2 | ||||
-rw-r--r-- | Documentation/perf_counter/kerneltop.c | 2 | ||||
-rw-r--r-- | Documentation/perf_counter/perfcounters.h | 142 | ||||
-rw-r--r-- | Documentation/perf_counter/perfstat.c | 251 |
4 files changed, 2 insertions, 395 deletions
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile index b45749753fcb..666da95a7877 100644 --- a/Documentation/perf_counter/Makefile +++ b/Documentation/perf_counter/Makefile | |||
@@ -2,7 +2,7 @@ BINS = kerneltop perfstat | |||
2 | 2 | ||
3 | all: $(BINS) | 3 | all: $(BINS) |
4 | 4 | ||
5 | kerneltop: kerneltop.c perfcounters.h | 5 | kerneltop: kerneltop.c ../../include/linux/perf_counter.h |
6 | cc -O6 -Wall -lrt `pkg-config --cflags --libs glib-2.0` -o $@ $< | 6 | cc -O6 -Wall -lrt `pkg-config --cflags --libs glib-2.0` -o $@ $< |
7 | 7 | ||
8 | perfstat: kerneltop | 8 | perfstat: kerneltop |
diff --git a/Documentation/perf_counter/kerneltop.c b/Documentation/perf_counter/kerneltop.c index 80b790553ec8..25e80bc44556 100644 --- a/Documentation/perf_counter/kerneltop.c +++ b/Documentation/perf_counter/kerneltop.c | |||
@@ -88,7 +88,7 @@ | |||
88 | 88 | ||
89 | #include <linux/unistd.h> | 89 | #include <linux/unistd.h> |
90 | 90 | ||
91 | #include "include/linux/perf_counter.h" | 91 | #include "../../include/linux/perf_counter.h" |
92 | 92 | ||
93 | 93 | ||
94 | /* | 94 | /* |
diff --git a/Documentation/perf_counter/perfcounters.h b/Documentation/perf_counter/perfcounters.h deleted file mode 100644 index 32e24b9154ab..000000000000 --- a/Documentation/perf_counter/perfcounters.h +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * Ioctls that can be done on a perf counter fd: | ||
3 | */ | ||
4 | #define PERF_COUNTER_IOC_ENABLE _IO('$', 0) | ||
5 | #define PERF_COUNTER_IOC_DISABLE _IO('$', 1) | ||
6 | |||
7 | /* | ||
8 | * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all | ||
9 | * counters in the current task. | ||
10 | */ | ||
11 | #define PR_TASK_PERF_COUNTERS_DISABLE 31 | ||
12 | #define PR_TASK_PERF_COUNTERS_ENABLE 32 | ||
13 | |||
14 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | ||
15 | |||
16 | #define rdclock() \ | ||
17 | ({ \ | ||
18 | struct timespec ts; \ | ||
19 | \ | ||
20 | clock_gettime(CLOCK_MONOTONIC, &ts); \ | ||
21 | ts.tv_sec * 1000000000ULL + ts.tv_nsec; \ | ||
22 | }) | ||
23 | |||
24 | /* | ||
25 | * Pick up some kernel type conventions: | ||
26 | */ | ||
27 | #define __user | ||
28 | #define asmlinkage | ||
29 | |||
30 | typedef unsigned int __u32; | ||
31 | typedef unsigned long long __u64; | ||
32 | typedef long long __s64; | ||
33 | |||
34 | /* | ||
35 | * User-space ABI bits: | ||
36 | */ | ||
37 | |||
38 | /* | ||
39 | * Generalized performance counter event types, used by the hw_event.type | ||
40 | * parameter of the sys_perf_counter_open() syscall: | ||
41 | */ | ||
42 | enum hw_event_types { | ||
43 | /* | ||
44 | * Common hardware events, generalized by the kernel: | ||
45 | */ | ||
46 | PERF_COUNT_CPU_CYCLES = 0, | ||
47 | PERF_COUNT_INSTRUCTIONS = 1, | ||
48 | PERF_COUNT_CACHE_REFERENCES = 2, | ||
49 | PERF_COUNT_CACHE_MISSES = 3, | ||
50 | PERF_COUNT_BRANCH_INSTRUCTIONS = 4, | ||
51 | PERF_COUNT_BRANCH_MISSES = 5, | ||
52 | PERF_COUNT_BUS_CYCLES = 6, | ||
53 | |||
54 | PERF_HW_EVENTS_MAX = 7, | ||
55 | |||
56 | /* | ||
57 | * Special "software" counters provided by the kernel, even if | ||
58 | * the hardware does not support performance counters. These | ||
59 | * counters measure various physical and sw events of the | ||
60 | * kernel (and allow the profiling of them as well): | ||
61 | */ | ||
62 | PERF_COUNT_CPU_CLOCK = -1, | ||
63 | PERF_COUNT_TASK_CLOCK = -2, | ||
64 | PERF_COUNT_PAGE_FAULTS = -3, | ||
65 | PERF_COUNT_CONTEXT_SWITCHES = -4, | ||
66 | PERF_COUNT_CPU_MIGRATIONS = -5, | ||
67 | |||
68 | PERF_SW_EVENTS_MIN = -6, | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * IRQ-notification data record type: | ||
73 | */ | ||
74 | enum perf_counter_record_type { | ||
75 | PERF_RECORD_SIMPLE = 0, | ||
76 | PERF_RECORD_IRQ = 1, | ||
77 | PERF_RECORD_GROUP = 2, | ||
78 | }; | ||
79 | |||
80 | /* | ||
81 | * Hardware event to monitor via a performance monitoring counter: | ||
82 | */ | ||
83 | struct perf_counter_hw_event { | ||
84 | __s64 type; | ||
85 | |||
86 | __u64 irq_period; | ||
87 | __u64 record_type; | ||
88 | __u64 read_format; | ||
89 | |||
90 | __u64 disabled : 1, /* off by default */ | ||
91 | nmi : 1, /* NMI sampling */ | ||
92 | raw : 1, /* raw event type */ | ||
93 | inherit : 1, /* children inherit it */ | ||
94 | pinned : 1, /* must always be on PMU */ | ||
95 | exclusive : 1, /* only group on PMU */ | ||
96 | exclude_user : 1, /* don't count user */ | ||
97 | exclude_kernel : 1, /* ditto kernel */ | ||
98 | exclude_hv : 1, /* ditto hypervisor */ | ||
99 | exclude_idle : 1, /* don't count when idle */ | ||
100 | |||
101 | __reserved_1 : 54; | ||
102 | |||
103 | __u32 extra_config_len; | ||
104 | __u32 __reserved_4; | ||
105 | |||
106 | __u64 __reserved_2; | ||
107 | __u64 __reserved_3; | ||
108 | }; | ||
109 | |||
110 | |||
111 | #ifdef __x86_64__ | ||
112 | # define __NR_perf_counter_open 295 | ||
113 | #endif | ||
114 | |||
115 | #ifdef __i386__ | ||
116 | # define __NR_perf_counter_open 333 | ||
117 | #endif | ||
118 | |||
119 | #ifdef __powerpc__ | ||
120 | #define __NR_perf_counter_open 319 | ||
121 | #endif | ||
122 | |||
123 | asmlinkage int sys_perf_counter_open( | ||
124 | |||
125 | struct perf_counter_hw_event *hw_event_uptr __user, | ||
126 | pid_t pid, | ||
127 | int cpu, | ||
128 | int group_fd, | ||
129 | unsigned long flags) | ||
130 | { | ||
131 | int ret; | ||
132 | |||
133 | ret = syscall( | ||
134 | __NR_perf_counter_open, hw_event_uptr, pid, cpu, group_fd, flags); | ||
135 | #if defined(__x86_64__) || defined(__i386__) | ||
136 | if (ret < 0 && ret > -4096) { | ||
137 | errno = -ret; | ||
138 | ret = -1; | ||
139 | } | ||
140 | #endif | ||
141 | return ret; | ||
142 | } | ||
diff --git a/Documentation/perf_counter/perfstat.c b/Documentation/perf_counter/perfstat.c deleted file mode 100644 index fd594468e655..000000000000 --- a/Documentation/perf_counter/perfstat.c +++ /dev/null | |||
@@ -1,251 +0,0 @@ | |||
1 | /* | ||
2 | * perfstat: /usr/bin/time -alike performance counter statistics utility | ||
3 | * | ||
4 | * It summarizes the counter events of all tasks (and child tasks), | ||
5 | * covering all CPUs that the command (or workload) executes on. | ||
6 | * It only counts the per-task events of the workload started, | ||
7 | * independent of how many other tasks run on those CPUs. | ||
8 | * | ||
9 | * Build with: cc -O2 -g -lrt -Wall -W -o perfstat perfstat.c | ||
10 | * | ||
11 | * Sample output: | ||
12 | * | ||
13 | |||
14 | $ ./perfstat -e 1 -e 3 -e 5 ls -lR /usr/include/ >/dev/null | ||
15 | |||
16 | Performance counter stats for 'ls': | ||
17 | |||
18 | 163516953 instructions | ||
19 | 2295 cache-misses | ||
20 | 2855182 branch-misses | ||
21 | |||
22 | * | ||
23 | * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com> | ||
24 | * | ||
25 | * Released under the GPLv2 (not later). | ||
26 | * | ||
27 | * Percpu counter support by: Yanmin Zhang <yanmin_zhang@linux.intel.com> | ||
28 | * Symbolic event options by: Wu Fengguang <fengguang.wu@intel.com> | ||
29 | */ | ||
30 | #define _GNU_SOURCE | ||
31 | |||
32 | #include <assert.h> | ||
33 | #include <getopt.h> | ||
34 | #include <stdint.h> | ||
35 | #include <stdlib.h> | ||
36 | #include <string.h> | ||
37 | #include <unistd.h> | ||
38 | #include <ctype.h> | ||
39 | #include <errno.h> | ||
40 | #include <fcntl.h> | ||
41 | #include <stdio.h> | ||
42 | #include <time.h> | ||
43 | |||
44 | #include <sys/syscall.h> | ||
45 | #include <sys/ioctl.h> | ||
46 | #include <sys/prctl.h> | ||
47 | #include <sys/types.h> | ||
48 | #include <sys/stat.h> | ||
49 | #include <sys/time.h> | ||
50 | #include <sys/wait.h> | ||
51 | #include <sys/uio.h> | ||
52 | |||
53 | #include <linux/unistd.h> | ||
54 | |||
55 | #include "perfcounters.h" | ||
56 | |||
57 | static int nr_cpus = 0; | ||
58 | |||
59 | static int system_wide = 0; | ||
60 | |||
61 | static void display_help(void) | ||
62 | { | ||
63 | unsigned int i; | ||
64 | int e; | ||
65 | |||
66 | printf( | ||
67 | "Usage: perfstat [<events...>] <cmd...>\n\n" | ||
68 | "PerfStat Options (up to %d event types can be specified):\n\n", | ||
69 | MAX_COUNTERS); | ||
70 | printf( | ||
71 | " -e EVENT --event=EVENT # symbolic-name abbreviations"); | ||
72 | |||
73 | for (i = 0, e = PERF_HW_EVENTS_MAX; i < ARRAY_SIZE(event_symbols); i++) { | ||
74 | if (e != event_symbols[i].event) { | ||
75 | e = event_symbols[i].event; | ||
76 | printf( | ||
77 | "\n %2d: %-20s", e, event_symbols[i].symbol); | ||
78 | } else | ||
79 | printf(" %s", event_symbols[i].symbol); | ||
80 | } | ||
81 | |||
82 | printf("\n" | ||
83 | " rNNN: raw event type\n\n" | ||
84 | " -s # system-wide collection\n\n" | ||
85 | " -c <cmd..> --command=<cmd..> # command+arguments to be timed.\n" | ||
86 | "\n"); | ||
87 | exit(0); | ||
88 | } | ||
89 | |||
90 | static void process_options(int argc, char *argv[]) | ||
91 | { | ||
92 | for (;;) { | ||
93 | int option_index = 0; | ||
94 | /** Options for getopt */ | ||
95 | static struct option long_options[] = { | ||
96 | {"event", required_argument, NULL, 'e'}, | ||
97 | {"help", no_argument, NULL, 'h'}, | ||
98 | {"command", no_argument, NULL, 'c'}, | ||
99 | {NULL, 0, NULL, 0 } | ||
100 | }; | ||
101 | int c = getopt_long(argc, argv, "+:e:c:s", | ||
102 | long_options, &option_index); | ||
103 | if (c == -1) | ||
104 | break; | ||
105 | |||
106 | switch (c) { | ||
107 | case 'c': | ||
108 | break; | ||
109 | case 's': | ||
110 | system_wide = 1; | ||
111 | break; | ||
112 | case 'e': | ||
113 | parse_events(optarg); | ||
114 | break; | ||
115 | default: | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | if (optind == argc) | ||
120 | goto err; | ||
121 | |||
122 | if (!nr_counters) | ||
123 | nr_counters = 8; | ||
124 | return; | ||
125 | |||
126 | err: | ||
127 | display_help(); | ||
128 | } | ||
129 | |||
130 | char fault_here[1000000]; | ||
131 | |||
132 | static int fd[MAX_NR_CPUS][MAX_COUNTERS]; | ||
133 | |||
134 | static void create_counter(int counter) | ||
135 | { | ||
136 | struct perf_counter_hw_event hw_event; | ||
137 | |||
138 | memset(&hw_event, 0, sizeof(hw_event)); | ||
139 | hw_event.type = event_id[counter]; | ||
140 | hw_event.raw = event_raw[counter]; | ||
141 | hw_event.record_type = PERF_RECORD_SIMPLE; | ||
142 | hw_event.nmi = 0; | ||
143 | |||
144 | if (system_wide) { | ||
145 | int cpu; | ||
146 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | ||
147 | fd[cpu][counter] = sys_perf_counter_open(&hw_event, -1, cpu, -1, 0); | ||
148 | if (fd[cpu][counter] < 0) { | ||
149 | printf("perfstat error: syscall returned with %d (%s)\n", | ||
150 | fd[cpu][counter], strerror(errno)); | ||
151 | exit(-1); | ||
152 | } | ||
153 | |||
154 | } | ||
155 | } else { | ||
156 | hw_event.inherit = 1; | ||
157 | hw_event.disabled = 1; | ||
158 | |||
159 | fd[0][counter] = sys_perf_counter_open(&hw_event, 0, -1, -1, 0); | ||
160 | if (fd[0][counter] < 0) { | ||
161 | printf("perfstat error: syscall returned with %d (%s)\n", | ||
162 | fd[0][counter], strerror(errno)); | ||
163 | exit(-1); | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
168 | |||
169 | int main(int argc, char *argv[]) | ||
170 | { | ||
171 | unsigned long long t0, t1; | ||
172 | int counter; | ||
173 | ssize_t res; | ||
174 | int status; | ||
175 | int pid; | ||
176 | |||
177 | process_options(argc, argv); | ||
178 | |||
179 | if (system_wide) { | ||
180 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | ||
181 | assert(nr_cpus <= MAX_NR_CPUS); | ||
182 | assert(nr_cpus >= 0); | ||
183 | } else | ||
184 | nr_cpus = 1; | ||
185 | |||
186 | for (counter = 0; counter < nr_counters; counter++) | ||
187 | create_counter(counter); | ||
188 | |||
189 | argc -= optind; | ||
190 | argv += optind; | ||
191 | |||
192 | /* | ||
193 | * Enable counters and exec the command: | ||
194 | */ | ||
195 | t0 = rdclock(); | ||
196 | prctl(PR_TASK_PERF_COUNTERS_ENABLE); | ||
197 | |||
198 | if ((pid = fork()) < 0) | ||
199 | perror("failed to fork"); | ||
200 | if (!pid) { | ||
201 | if (execvp(argv[0], argv)) { | ||
202 | perror(argv[0]); | ||
203 | exit(-1); | ||
204 | } | ||
205 | } | ||
206 | while (wait(&status) >= 0) | ||
207 | ; | ||
208 | prctl(PR_TASK_PERF_COUNTERS_DISABLE); | ||
209 | t1 = rdclock(); | ||
210 | |||
211 | fflush(stdout); | ||
212 | |||
213 | fprintf(stderr, "\n"); | ||
214 | fprintf(stderr, " Performance counter stats for \'%s\':\n", | ||
215 | argv[0]); | ||
216 | fprintf(stderr, "\n"); | ||
217 | |||
218 | for (counter = 0; counter < nr_counters; counter++) { | ||
219 | int cpu; | ||
220 | __u64 count, single_count; | ||
221 | |||
222 | count = 0; | ||
223 | for (cpu = 0; cpu < nr_cpus; cpu ++) { | ||
224 | res = read(fd[cpu][counter], | ||
225 | (char *) &single_count, sizeof(single_count)); | ||
226 | assert(res == sizeof(single_count)); | ||
227 | count += single_count; | ||
228 | } | ||
229 | |||
230 | if (!event_raw[counter] && | ||
231 | (event_id[counter] == PERF_COUNT_CPU_CLOCK || | ||
232 | event_id[counter] == PERF_COUNT_TASK_CLOCK)) { | ||
233 | |||
234 | double msecs = (double)count / 1000000; | ||
235 | |||
236 | fprintf(stderr, " %14.6f %-20s (msecs)\n", | ||
237 | msecs, event_name(counter)); | ||
238 | } else { | ||
239 | fprintf(stderr, " %14Ld %-20s (events)\n", | ||
240 | count, event_name(counter)); | ||
241 | } | ||
242 | if (!counter) | ||
243 | fprintf(stderr, "\n"); | ||
244 | } | ||
245 | fprintf(stderr, "\n"); | ||
246 | fprintf(stderr, " Wall-clock time elapsed: %12.6f msecs\n", | ||
247 | (double)(t1-t0)/1e6); | ||
248 | fprintf(stderr, "\n"); | ||
249 | |||
250 | return 0; | ||
251 | } | ||