aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2011-04-14 10:20:14 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-04-15 11:52:28 -0400
commit5d2cd90922c778908bd0cd669e572a5b5eafd737 (patch)
tree0467726f17165b6e2461521e9cca4f54c959d6d6 /tools/perf
parentdb9a9cbc8142eed008e242e389938689c6feb1ba (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')
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/builtin-stat.c7
-rw-r--r--tools/perf/builtin-test.c10
-rw-r--r--tools/perf/builtin-top.c3
-rw-r--r--tools/perf/util/evlist.c14
-rw-r--r--tools/perf/util/evsel.c27
-rw-r--r--tools/perf/util/evsel.h6
-rw-r--r--tools/perf/util/python.c9
8 files changed, 41 insertions, 42 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 17d1dcb3c667..416538248a4b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
163 struct perf_event_attr *attr = &evsel->attr; 163 struct perf_event_attr *attr = &evsel->attr;
164 int track = !evsel->idx; /* only the first counter needs these */ 164 int track = !evsel->idx; /* only the first counter needs these */
165 165
166 attr->inherit = !no_inherit;
166 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
167 PERF_FORMAT_TOTAL_TIME_RUNNING | 168 PERF_FORMAT_TOTAL_TIME_RUNNING |
168 PERF_FORMAT_ID; 169 PERF_FORMAT_ID;
@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist)
251{ 252{
252 struct perf_evsel *pos; 253 struct perf_evsel *pos;
253 254
255 if (evlist->cpus->map[0] < 0)
256 no_inherit = true;
257
254 list_for_each_entry(pos, &evlist->entries, node) { 258 list_for_each_entry(pos, &evlist->entries, node) {
255 struct perf_event_attr *attr = &pos->attr; 259 struct perf_event_attr *attr = &pos->attr;
256 /* 260 /*
@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist)
271retry_sample_id: 275retry_sample_id:
272 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 276 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
273try_again: 277try_again:
274 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, 278 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
275 !no_inherit) < 0) {
276 int err = errno; 279 int err = errno;
277 280
278 if (err == EPERM || err == EACCES) { 281 if (err == EPERM || err == EACCES) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e2109f9b43eb..03f0e45f1479 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
168 PERF_FORMAT_TOTAL_TIME_RUNNING; 168 PERF_FORMAT_TOTAL_TIME_RUNNING;
169 169
170 attr->inherit = !no_inherit;
171
170 if (system_wide) 172 if (system_wide)
171 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false); 173 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
172 174
173 attr->inherit = !no_inherit;
174 if (target_pid == -1 && target_tid == -1) { 175 if (target_pid == -1 && target_tid == -1) {
175 attr->disabled = 1; 176 attr->disabled = 1;
176 attr->enable_on_exec = 1; 177 attr->enable_on_exec = 1;
177 } 178 }
178 179
179 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false); 180 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
180} 181}
181 182
182/* 183/*
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 1b2106c58f66..11e3c8458362 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -290,7 +290,7 @@ static int test__open_syscall_event(void)
290 goto out_thread_map_delete; 290 goto out_thread_map_delete;
291 } 291 }
292 292
293 if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) { 293 if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
294 pr_debug("failed to open counter: %s, " 294 pr_debug("failed to open counter: %s, "
295 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 295 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
296 strerror(errno)); 296 strerror(errno));
@@ -303,7 +303,7 @@ static int test__open_syscall_event(void)
303 } 303 }
304 304
305 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { 305 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
306 pr_debug("perf_evsel__open_read_on_cpu\n"); 306 pr_debug("perf_evsel__read_on_cpu\n");
307 goto out_close_fd; 307 goto out_close_fd;
308 } 308 }
309 309
@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
365 goto out_thread_map_delete; 365 goto out_thread_map_delete;
366 } 366 }
367 367
368 if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) { 368 if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
369 pr_debug("failed to open counter: %s, " 369 pr_debug("failed to open counter: %s, "
370 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 370 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
371 strerror(errno)); 371 strerror(errno));
@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void)
418 continue; 418 continue;
419 419
420 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { 420 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
421 pr_debug("perf_evsel__open_read_on_cpu\n"); 421 pr_debug("perf_evsel__read_on_cpu\n");
422 err = -1; 422 err = -1;
423 break; 423 break;
424 } 424 }
@@ -529,7 +529,7 @@ static int test__basic_mmap(void)
529 529
530 perf_evlist__add(evlist, evsels[i]); 530 perf_evlist__add(evlist, evsels[i]);
531 531
532 if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) { 532 if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
533 pr_debug("failed to open counter: %s, " 533 pr_debug("failed to open counter: %s, "
534 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 534 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
535 strerror(errno)); 535 strerror(errno));
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fc1273e976c5..7e3d6e310bf8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist)
845 } 845 }
846 846
847 attr->mmap = 1; 847 attr->mmap = 1;
848 attr->inherit = inherit;
848try_again: 849try_again:
849 if (perf_evsel__open(counter, top.evlist->cpus, 850 if (perf_evsel__open(counter, top.evlist->cpus,
850 top.evlist->threads, group, inherit) < 0) { 851 top.evlist->threads, group) < 0) {
851 int err = errno; 852 int err = errno;
852 853
853 if (err == EPERM || err == EACCES) { 854 if (err == EPERM || err == EACCES) {
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
253static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot, 254static 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
177static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 177static 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
255int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 242int 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
269int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 256int 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
275int perf_evsel__open_per_thread(struct perf_evsel *evsel, 262int 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
281static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 268static 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);
81void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 81void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
82 82
83int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 83int 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);
85int perf_evsel__open_per_thread(struct perf_evsel *evsel, 85int 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);
87int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 87int 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 }