diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-04-14 10:20:14 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-04-15 11:52:28 -0400 |
commit | 5d2cd90922c778908bd0cd669e572a5b5eafd737 (patch) | |
tree | 0467726f17165b6e2461521e9cca4f54c959d6d6 /tools/perf/util | |
parent | db9a9cbc8142eed008e242e389938689c6feb1ba (diff) |
perf evsel: Fix use of inherit
perf stat doesn't mmap and its perfectly fine for it to use task-bound
counters with inheritance.
So set the attr.inherit on the caller and leave the syscall itself to
validate it.
When the mmap fails perf_evlist__mmap will just emit a warning if this
is the failure reason.
Reported-by: Peter Zijlstra <peterz@infradead.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Link: http://lkml.kernel.org/r/20110414170121.GC3229@ghostprotocols.net
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/evlist.c | 14 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 27 | ||||
-rw-r--r-- | tools/perf/util/evsel.h | 6 | ||||
-rw-r--r-- | tools/perf/util/python.c | 9 |
4 files changed, 25 insertions, 31 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d852cefa20de..45da8d186b49 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "evlist.h" | 12 | #include "evlist.h" |
13 | #include "evsel.h" | 13 | #include "evsel.h" |
14 | #include "util.h" | 14 | #include "util.h" |
15 | #include "debug.h" | ||
15 | 16 | ||
16 | #include <sys/mman.h> | 17 | #include <sys/mman.h> |
17 | 18 | ||
@@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | |||
250 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 251 | return evlist->mmap != NULL ? 0 : -ENOMEM; |
251 | } | 252 | } |
252 | 253 | ||
253 | static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot, | 254 | static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, |
254 | int mask, int fd) | 255 | int cpu, int prot, int mask, int fd) |
255 | { | 256 | { |
256 | evlist->mmap[cpu].prev = 0; | 257 | evlist->mmap[cpu].prev = 0; |
257 | evlist->mmap[cpu].mask = mask; | 258 | evlist->mmap[cpu].mask = mask; |
258 | evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, | 259 | evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, |
259 | MAP_SHARED, fd, 0); | 260 | MAP_SHARED, fd, 0); |
260 | if (evlist->mmap[cpu].base == MAP_FAILED) | 261 | if (evlist->mmap[cpu].base == MAP_FAILED) { |
262 | if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit) | ||
263 | ui__warning("Inherit is not allowed on per-task " | ||
264 | "events using mmap.\n"); | ||
261 | return -1; | 265 | return -1; |
266 | } | ||
262 | 267 | ||
263 | perf_evlist__add_pollfd(evlist, fd); | 268 | perf_evlist__add_pollfd(evlist, fd); |
264 | return 0; | 269 | return 0; |
@@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) | |||
312 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, | 317 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, |
313 | FD(first_evsel, cpu, 0)) != 0) | 318 | FD(first_evsel, cpu, 0)) != 0) |
314 | goto out_unmap; | 319 | goto out_unmap; |
315 | } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0) | 320 | } else if (__perf_evlist__mmap(evlist, evsel, cpu, |
321 | prot, mask, fd) < 0) | ||
316 | goto out_unmap; | 322 | goto out_unmap; |
317 | 323 | ||
318 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 324 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 662596afd7f1..d6fd59beb860 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel, | |||
175 | } | 175 | } |
176 | 176 | ||
177 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 177 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
178 | struct thread_map *threads, bool group, bool inherit) | 178 | struct thread_map *threads, bool group) |
179 | { | 179 | { |
180 | int cpu, thread; | 180 | int cpu, thread; |
181 | unsigned long flags = 0; | 181 | unsigned long flags = 0; |
@@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
192 | 192 | ||
193 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 193 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
194 | int group_fd = -1; | 194 | int group_fd = -1; |
195 | /* | ||
196 | * Don't allow mmap() of inherited per-task counters. This | ||
197 | * would create a performance issue due to all children writing | ||
198 | * to the same buffer. | ||
199 | * | ||
200 | * FIXME: | ||
201 | * Proper fix is not to pass 'inherit' to perf_evsel__open*, | ||
202 | * but a 'flags' parameter, with 'group' folded there as well, | ||
203 | * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if | ||
204 | * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is | ||
205 | * set. Lets go for the minimal fix first tho. | ||
206 | */ | ||
207 | evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit; | ||
208 | 195 | ||
209 | for (thread = 0; thread < threads->nr; thread++) { | 196 | for (thread = 0; thread < threads->nr; thread++) { |
210 | 197 | ||
@@ -253,7 +240,7 @@ static struct { | |||
253 | }; | 240 | }; |
254 | 241 | ||
255 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 242 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
256 | struct thread_map *threads, bool group, bool inherit) | 243 | struct thread_map *threads, bool group) |
257 | { | 244 | { |
258 | if (cpus == NULL) { | 245 | if (cpus == NULL) { |
259 | /* Work around old compiler warnings about strict aliasing */ | 246 | /* Work around old compiler warnings about strict aliasing */ |
@@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
263 | if (threads == NULL) | 250 | if (threads == NULL) |
264 | threads = &empty_thread_map.map; | 251 | threads = &empty_thread_map.map; |
265 | 252 | ||
266 | return __perf_evsel__open(evsel, cpus, threads, group, inherit); | 253 | return __perf_evsel__open(evsel, cpus, threads, group); |
267 | } | 254 | } |
268 | 255 | ||
269 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, | 256 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, |
270 | struct cpu_map *cpus, bool group, bool inherit) | 257 | struct cpu_map *cpus, bool group) |
271 | { | 258 | { |
272 | return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit); | 259 | return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group); |
273 | } | 260 | } |
274 | 261 | ||
275 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, | 262 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, |
276 | struct thread_map *threads, bool group, bool inherit) | 263 | struct thread_map *threads, bool group) |
277 | { | 264 | { |
278 | return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); | 265 | return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group); |
279 | } | 266 | } |
280 | 267 | ||
281 | static int perf_event__parse_id_sample(const union perf_event *event, u64 type, | 268 | static int perf_event__parse_id_sample(const union perf_event *event, u64 type, |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 6710ab538342..f79bb2c09a6c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
@@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel); | |||
81 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | 81 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); |
82 | 82 | ||
83 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, | 83 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, |
84 | struct cpu_map *cpus, bool group, bool inherit); | 84 | struct cpu_map *cpus, bool group); |
85 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, | 85 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, |
86 | struct thread_map *threads, bool group, bool inherit); | 86 | struct thread_map *threads, bool group); |
87 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 87 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
88 | struct thread_map *threads, bool group, bool inherit); | 88 | struct thread_map *threads, bool group); |
89 | 89 | ||
90 | #define perf_evsel__match(evsel, t, c) \ | 90 | #define perf_evsel__match(evsel, t, c) \ |
91 | (evsel->attr.type == PERF_TYPE_##t && \ | 91 | (evsel->attr.type == PERF_TYPE_##t && \ |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index a9f2d7e1204d..f5e38451fdc5 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
@@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, | |||
498 | struct cpu_map *cpus = NULL; | 498 | struct cpu_map *cpus = NULL; |
499 | struct thread_map *threads = NULL; | 499 | struct thread_map *threads = NULL; |
500 | PyObject *pcpus = NULL, *pthreads = NULL; | 500 | PyObject *pcpus = NULL, *pthreads = NULL; |
501 | int group = 0, overwrite = 0; | 501 | int group = 0, inherit = 0; |
502 | static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL}; | 502 | static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL}; |
503 | 503 | ||
504 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, | 504 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, |
505 | &pcpus, &pthreads, &group, &overwrite)) | 505 | &pcpus, &pthreads, &group, &inherit)) |
506 | return NULL; | 506 | return NULL; |
507 | 507 | ||
508 | if (pthreads != NULL) | 508 | if (pthreads != NULL) |
@@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, | |||
511 | if (pcpus != NULL) | 511 | if (pcpus != NULL) |
512 | cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; | 512 | cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; |
513 | 513 | ||
514 | if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) { | 514 | evsel->attr.inherit = inherit; |
515 | if (perf_evsel__open(evsel, cpus, threads, group) < 0) { | ||
515 | PyErr_SetFromErrno(PyExc_OSError); | 516 | PyErr_SetFromErrno(PyExc_OSError); |
516 | return NULL; | 517 | return NULL; |
517 | } | 518 | } |