diff options
-rw-r--r-- | tools/perf/Makefile.perf | 1 | ||||
-rw-r--r-- | tools/perf/bench/mem-memcpy.c | 4 | ||||
-rw-r--r-- | tools/perf/bench/mem-memset.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/bp_signal.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/bp_signal_overflow.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/rdpmc.c | 4 | ||||
-rw-r--r-- | tools/perf/util/cloexec.c | 57 | ||||
-rw-r--r-- | tools/perf/util/cloexec.h | 6 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 12 | ||||
-rw-r--r-- | tools/perf/util/record.c | 9 |
11 files changed, 97 insertions, 12 deletions
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 3308b22a1660..2240974b7745 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -376,6 +376,7 @@ LIB_OBJS += $(OUTPUT)util/record.o | |||
376 | LIB_OBJS += $(OUTPUT)util/srcline.o | 376 | LIB_OBJS += $(OUTPUT)util/srcline.o |
377 | LIB_OBJS += $(OUTPUT)util/data.o | 377 | LIB_OBJS += $(OUTPUT)util/data.o |
378 | LIB_OBJS += $(OUTPUT)util/tsc.o | 378 | LIB_OBJS += $(OUTPUT)util/tsc.o |
379 | LIB_OBJS += $(OUTPUT)util/cloexec.o | ||
379 | 380 | ||
380 | LIB_OBJS += $(OUTPUT)ui/setup.o | 381 | LIB_OBJS += $(OUTPUT)ui/setup.o |
381 | LIB_OBJS += $(OUTPUT)ui/helpline.o | 382 | LIB_OBJS += $(OUTPUT)ui/helpline.o |
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c index e622c3e96efc..2465141b554b 100644 --- a/tools/perf/bench/mem-memcpy.c +++ b/tools/perf/bench/mem-memcpy.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "../util/util.h" | 10 | #include "../util/util.h" |
11 | #include "../util/parse-options.h" | 11 | #include "../util/parse-options.h" |
12 | #include "../util/header.h" | 12 | #include "../util/header.h" |
13 | #include "../util/cloexec.h" | ||
13 | #include "bench.h" | 14 | #include "bench.h" |
14 | #include "mem-memcpy-arch.h" | 15 | #include "mem-memcpy-arch.h" |
15 | 16 | ||
@@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = { | |||
83 | 84 | ||
84 | static void init_cycle(void) | 85 | static void init_cycle(void) |
85 | { | 86 | { |
86 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); | 87 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, |
88 | perf_event_open_cloexec_flag()); | ||
87 | 89 | ||
88 | if (cycle_fd < 0 && errno == ENOSYS) | 90 | if (cycle_fd < 0 && errno == ENOSYS) |
89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 91 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); |
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c index 2a65468619f0..75fc3e65fb2a 100644 --- a/tools/perf/bench/mem-memset.c +++ b/tools/perf/bench/mem-memset.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "../util/util.h" | 10 | #include "../util/util.h" |
11 | #include "../util/parse-options.h" | 11 | #include "../util/parse-options.h" |
12 | #include "../util/header.h" | 12 | #include "../util/header.h" |
13 | #include "../util/cloexec.h" | ||
13 | #include "bench.h" | 14 | #include "bench.h" |
14 | #include "mem-memset-arch.h" | 15 | #include "mem-memset-arch.h" |
15 | 16 | ||
@@ -83,7 +84,8 @@ static struct perf_event_attr cycle_attr = { | |||
83 | 84 | ||
84 | static void init_cycle(void) | 85 | static void init_cycle(void) |
85 | { | 86 | { |
86 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0); | 87 | cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, |
88 | perf_event_open_cloexec_flag()); | ||
87 | 89 | ||
88 | if (cycle_fd < 0 && errno == ENOSYS) | 90 | if (cycle_fd < 0 && errno == ENOSYS) |
89 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 91 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index b7f555add0c8..f83c08c0dd87 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include "util/header.h" | 10 | #include "util/header.h" |
11 | #include "util/session.h" | 11 | #include "util/session.h" |
12 | #include "util/tool.h" | 12 | #include "util/tool.h" |
13 | #include "util/cloexec.h" | ||
13 | 14 | ||
14 | #include "util/parse-options.h" | 15 | #include "util/parse-options.h" |
15 | #include "util/trace-event.h" | 16 | #include "util/trace-event.h" |
@@ -434,7 +435,8 @@ static int self_open_counters(void) | |||
434 | attr.type = PERF_TYPE_SOFTWARE; | 435 | attr.type = PERF_TYPE_SOFTWARE; |
435 | attr.config = PERF_COUNT_SW_TASK_CLOCK; | 436 | attr.config = PERF_COUNT_SW_TASK_CLOCK; |
436 | 437 | ||
437 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | 438 | fd = sys_perf_event_open(&attr, 0, -1, -1, |
439 | perf_event_open_cloexec_flag()); | ||
438 | 440 | ||
439 | if (fd < 0) | 441 | if (fd < 0) |
440 | pr_err("Error: sys_perf_event_open() syscall returned " | 442 | pr_err("Error: sys_perf_event_open() syscall returned " |
diff --git a/tools/perf/tests/bp_signal.c b/tools/perf/tests/bp_signal.c index aba095489193..a02b035fd5aa 100644 --- a/tools/perf/tests/bp_signal.c +++ b/tools/perf/tests/bp_signal.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "tests.h" | 25 | #include "tests.h" |
26 | #include "debug.h" | 26 | #include "debug.h" |
27 | #include "perf.h" | 27 | #include "perf.h" |
28 | #include "cloexec.h" | ||
28 | 29 | ||
29 | static int fd1; | 30 | static int fd1; |
30 | static int fd2; | 31 | static int fd2; |
@@ -78,7 +79,8 @@ static int bp_event(void *fn, int setup_signal) | |||
78 | pe.exclude_kernel = 1; | 79 | pe.exclude_kernel = 1; |
79 | pe.exclude_hv = 1; | 80 | pe.exclude_hv = 1; |
80 | 81 | ||
81 | fd = sys_perf_event_open(&pe, 0, -1, -1, 0); | 82 | fd = sys_perf_event_open(&pe, 0, -1, -1, |
83 | perf_event_open_cloexec_flag()); | ||
82 | if (fd < 0) { | 84 | if (fd < 0) { |
83 | pr_debug("failed opening event %llx\n", pe.config); | 85 | pr_debug("failed opening event %llx\n", pe.config); |
84 | return TEST_FAIL; | 86 | return TEST_FAIL; |
diff --git a/tools/perf/tests/bp_signal_overflow.c b/tools/perf/tests/bp_signal_overflow.c index 44ac82179708..e76537724491 100644 --- a/tools/perf/tests/bp_signal_overflow.c +++ b/tools/perf/tests/bp_signal_overflow.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "tests.h" | 24 | #include "tests.h" |
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "perf.h" | 26 | #include "perf.h" |
27 | #include "cloexec.h" | ||
27 | 28 | ||
28 | static int overflows; | 29 | static int overflows; |
29 | 30 | ||
@@ -91,7 +92,8 @@ int test__bp_signal_overflow(void) | |||
91 | pe.exclude_kernel = 1; | 92 | pe.exclude_kernel = 1; |
92 | pe.exclude_hv = 1; | 93 | pe.exclude_hv = 1; |
93 | 94 | ||
94 | fd = sys_perf_event_open(&pe, 0, -1, -1, 0); | 95 | fd = sys_perf_event_open(&pe, 0, -1, -1, |
96 | perf_event_open_cloexec_flag()); | ||
95 | if (fd < 0) { | 97 | if (fd < 0) { |
96 | pr_debug("failed opening event %llx\n", pe.config); | 98 | pr_debug("failed opening event %llx\n", pe.config); |
97 | return TEST_FAIL; | 99 | return TEST_FAIL; |
diff --git a/tools/perf/tests/rdpmc.c b/tools/perf/tests/rdpmc.c index e59143fd9e71..c04d1f268576 100644 --- a/tools/perf/tests/rdpmc.c +++ b/tools/perf/tests/rdpmc.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "perf.h" | 6 | #include "perf.h" |
7 | #include "debug.h" | 7 | #include "debug.h" |
8 | #include "tests.h" | 8 | #include "tests.h" |
9 | #include "cloexec.h" | ||
9 | 10 | ||
10 | #if defined(__x86_64__) || defined(__i386__) | 11 | #if defined(__x86_64__) || defined(__i386__) |
11 | 12 | ||
@@ -104,7 +105,8 @@ static int __test__rdpmc(void) | |||
104 | sa.sa_sigaction = segfault_handler; | 105 | sa.sa_sigaction = segfault_handler; |
105 | sigaction(SIGSEGV, &sa, NULL); | 106 | sigaction(SIGSEGV, &sa, NULL); |
106 | 107 | ||
107 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | 108 | fd = sys_perf_event_open(&attr, 0, -1, -1, |
109 | perf_event_open_cloexec_flag()); | ||
108 | if (fd < 0) { | 110 | if (fd < 0) { |
109 | pr_err("Error: sys_perf_event_open() syscall returned " | 111 | pr_err("Error: sys_perf_event_open() syscall returned " |
110 | "with %d (%s)\n", fd, strerror(errno)); | 112 | "with %d (%s)\n", fd, strerror(errno)); |
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c new file mode 100644 index 000000000000..c5d05ec17220 --- /dev/null +++ b/tools/perf/util/cloexec.c | |||
@@ -0,0 +1,57 @@ | |||
1 | #include "util.h" | ||
2 | #include "../perf.h" | ||
3 | #include "cloexec.h" | ||
4 | #include "asm/bug.h" | ||
5 | |||
6 | static unsigned long flag = PERF_FLAG_FD_CLOEXEC; | ||
7 | |||
8 | static int perf_flag_probe(void) | ||
9 | { | ||
10 | /* use 'safest' configuration as used in perf_evsel__fallback() */ | ||
11 | struct perf_event_attr attr = { | ||
12 | .type = PERF_COUNT_SW_CPU_CLOCK, | ||
13 | .config = PERF_COUNT_SW_CPU_CLOCK, | ||
14 | }; | ||
15 | int fd; | ||
16 | int err; | ||
17 | |||
18 | /* check cloexec flag */ | ||
19 | fd = sys_perf_event_open(&attr, 0, -1, -1, | ||
20 | PERF_FLAG_FD_CLOEXEC); | ||
21 | err = errno; | ||
22 | |||
23 | if (fd >= 0) { | ||
24 | close(fd); | ||
25 | return 1; | ||
26 | } | ||
27 | |||
28 | WARN_ONCE(err != EINVAL, | ||
29 | "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", | ||
30 | err, strerror(err)); | ||
31 | |||
32 | /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ | ||
33 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | ||
34 | err = errno; | ||
35 | |||
36 | if (WARN_ONCE(fd < 0, | ||
37 | "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", | ||
38 | err, strerror(err))) | ||
39 | return -1; | ||
40 | |||
41 | close(fd); | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | unsigned long perf_event_open_cloexec_flag(void) | ||
47 | { | ||
48 | static bool probed; | ||
49 | |||
50 | if (!probed) { | ||
51 | if (perf_flag_probe() <= 0) | ||
52 | flag = 0; | ||
53 | probed = true; | ||
54 | } | ||
55 | |||
56 | return flag; | ||
57 | } | ||
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h new file mode 100644 index 000000000000..94a5a7d829d5 --- /dev/null +++ b/tools/perf/util/cloexec.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __PERF_CLOEXEC_H | ||
2 | #define __PERF_CLOEXEC_H | ||
3 | |||
4 | unsigned long perf_event_open_cloexec_flag(void); | ||
5 | |||
6 | #endif /* __PERF_CLOEXEC_H */ | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 90f58cdd0fb0..21a373ebea22 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -29,6 +29,7 @@ static struct { | |||
29 | bool sample_id_all; | 29 | bool sample_id_all; |
30 | bool exclude_guest; | 30 | bool exclude_guest; |
31 | bool mmap2; | 31 | bool mmap2; |
32 | bool cloexec; | ||
32 | } perf_missing_features; | 33 | } perf_missing_features; |
33 | 34 | ||
34 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 35 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
@@ -994,7 +995,7 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
994 | struct thread_map *threads) | 995 | struct thread_map *threads) |
995 | { | 996 | { |
996 | int cpu, thread; | 997 | int cpu, thread; |
997 | unsigned long flags = 0; | 998 | unsigned long flags = PERF_FLAG_FD_CLOEXEC; |
998 | int pid = -1, err; | 999 | int pid = -1, err; |
999 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; | 1000 | enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; |
1000 | 1001 | ||
@@ -1003,11 +1004,13 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
1003 | return -ENOMEM; | 1004 | return -ENOMEM; |
1004 | 1005 | ||
1005 | if (evsel->cgrp) { | 1006 | if (evsel->cgrp) { |
1006 | flags = PERF_FLAG_PID_CGROUP; | 1007 | flags |= PERF_FLAG_PID_CGROUP; |
1007 | pid = evsel->cgrp->fd; | 1008 | pid = evsel->cgrp->fd; |
1008 | } | 1009 | } |
1009 | 1010 | ||
1010 | fallback_missing_features: | 1011 | fallback_missing_features: |
1012 | if (perf_missing_features.cloexec) | ||
1013 | flags &= ~(unsigned long)PERF_FLAG_FD_CLOEXEC; | ||
1011 | if (perf_missing_features.mmap2) | 1014 | if (perf_missing_features.mmap2) |
1012 | evsel->attr.mmap2 = 0; | 1015 | evsel->attr.mmap2 = 0; |
1013 | if (perf_missing_features.exclude_guest) | 1016 | if (perf_missing_features.exclude_guest) |
@@ -1076,7 +1079,10 @@ try_fallback: | |||
1076 | if (err != -EINVAL || cpu > 0 || thread > 0) | 1079 | if (err != -EINVAL || cpu > 0 || thread > 0) |
1077 | goto out_close; | 1080 | goto out_close; |
1078 | 1081 | ||
1079 | if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { | 1082 | if (!perf_missing_features.cloexec && (flags & PERF_FLAG_FD_CLOEXEC)) { |
1083 | perf_missing_features.cloexec = true; | ||
1084 | goto fallback_missing_features; | ||
1085 | } else if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { | ||
1080 | perf_missing_features.mmap2 = true; | 1086 | perf_missing_features.mmap2 = true; |
1081 | goto fallback_missing_features; | 1087 | goto fallback_missing_features; |
1082 | } else if (!perf_missing_features.exclude_guest && | 1088 | } else if (!perf_missing_features.exclude_guest && |
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c index 165723152cfb..fe8079edbdc1 100644 --- a/tools/perf/util/record.c +++ b/tools/perf/util/record.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "parse-events.h" | 4 | #include "parse-events.h" |
5 | #include <api/fs/fs.h> | 5 | #include <api/fs/fs.h> |
6 | #include "util.h" | 6 | #include "util.h" |
7 | #include "cloexec.h" | ||
7 | 8 | ||
8 | typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); | 9 | typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); |
9 | 10 | ||
@@ -11,6 +12,7 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) | |||
11 | { | 12 | { |
12 | struct perf_evlist *evlist; | 13 | struct perf_evlist *evlist; |
13 | struct perf_evsel *evsel; | 14 | struct perf_evsel *evsel; |
15 | unsigned long flags = perf_event_open_cloexec_flag(); | ||
14 | int err = -EAGAIN, fd; | 16 | int err = -EAGAIN, fd; |
15 | 17 | ||
16 | evlist = perf_evlist__new(); | 18 | evlist = perf_evlist__new(); |
@@ -22,14 +24,14 @@ static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) | |||
22 | 24 | ||
23 | evsel = perf_evlist__first(evlist); | 25 | evsel = perf_evlist__first(evlist); |
24 | 26 | ||
25 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); | 27 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); |
26 | if (fd < 0) | 28 | if (fd < 0) |
27 | goto out_delete; | 29 | goto out_delete; |
28 | close(fd); | 30 | close(fd); |
29 | 31 | ||
30 | fn(evsel); | 32 | fn(evsel); |
31 | 33 | ||
32 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); | 34 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, flags); |
33 | if (fd < 0) { | 35 | if (fd < 0) { |
34 | if (errno == EINVAL) | 36 | if (errno == EINVAL) |
35 | err = -EINVAL; | 37 | err = -EINVAL; |
@@ -219,7 +221,8 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str) | |||
219 | cpu = evlist->cpus->map[0]; | 221 | cpu = evlist->cpus->map[0]; |
220 | } | 222 | } |
221 | 223 | ||
222 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); | 224 | fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, |
225 | perf_event_open_cloexec_flag()); | ||
223 | if (fd >= 0) { | 226 | if (fd >= 0) { |
224 | close(fd); | 227 | close(fd); |
225 | ret = true; | 228 | ret = true; |