xref: /openbmc/linux/tools/perf/util/cloexec.c (revision 3932b9ca)
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 }
58