aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/Makefile.perf1
-rw-r--r--tools/perf/bench/mem-memcpy.c4
-rw-r--r--tools/perf/bench/mem-memset.c4
-rw-r--r--tools/perf/builtin-sched.c4
-rw-r--r--tools/perf/tests/bp_signal.c4
-rw-r--r--tools/perf/tests/bp_signal_overflow.c4
-rw-r--r--tools/perf/tests/rdpmc.c4
-rw-r--r--tools/perf/util/cloexec.c57
-rw-r--r--tools/perf/util/cloexec.h6
-rw-r--r--tools/perf/util/evsel.c12
-rw-r--r--tools/perf/util/record.c9
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
376LIB_OBJS += $(OUTPUT)util/srcline.o 376LIB_OBJS += $(OUTPUT)util/srcline.o
377LIB_OBJS += $(OUTPUT)util/data.o 377LIB_OBJS += $(OUTPUT)util/data.o
378LIB_OBJS += $(OUTPUT)util/tsc.o 378LIB_OBJS += $(OUTPUT)util/tsc.o
379LIB_OBJS += $(OUTPUT)util/cloexec.o
379 380
380LIB_OBJS += $(OUTPUT)ui/setup.o 381LIB_OBJS += $(OUTPUT)ui/setup.o
381LIB_OBJS += $(OUTPUT)ui/helpline.o 382LIB_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
84static void init_cycle(void) 85static 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
84static void init_cycle(void) 85static 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
29static int fd1; 30static int fd1;
30static int fd2; 31static 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
28static int overflows; 29static 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
6static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
7
8static 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
46unsigned 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
4unsigned 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
1010fallback_missing_features: 1011fallback_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
8typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 9typedef 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;