]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/perf/util/cloexec.c
ASoC: simple-card: Add a NULL pointer check in asoc_simple_card_dai_link_of
[karo-tx-linux.git] / tools / perf / util / cloexec.c
1 #include <sched.h>
2 #include "util.h"
3 #include "../perf.h"
4 #include "cloexec.h"
5 #include "asm/bug.h"
6 #include "debug.h"
7
8 static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
9
10 static int perf_flag_probe(void)
11 {
12         /* use 'safest' configuration as used in perf_evsel__fallback() */
13         struct perf_event_attr attr = {
14                 .type = PERF_TYPE_SOFTWARE,
15                 .config = PERF_COUNT_SW_CPU_CLOCK,
16                 .exclude_kernel = 1,
17         };
18         int fd;
19         int err;
20         int cpu;
21         pid_t pid = -1;
22         char sbuf[STRERR_BUFSIZE];
23
24         cpu = sched_getcpu();
25         if (cpu < 0)
26                 cpu = 0;
27
28         while (1) {
29                 /* check cloexec flag */
30                 fd = sys_perf_event_open(&attr, pid, cpu, -1,
31                                          PERF_FLAG_FD_CLOEXEC);
32                 if (fd < 0 && pid == -1 && errno == EACCES) {
33                         pid = 0;
34                         continue;
35                 }
36                 break;
37         }
38         err = errno;
39
40         if (fd >= 0) {
41                 close(fd);
42                 return 1;
43         }
44
45         WARN_ONCE(err != EINVAL && err != EBUSY,
46                   "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
47                   err, strerror_r(err, sbuf, sizeof(sbuf)));
48
49         /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
50         fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
51         err = errno;
52
53         if (WARN_ONCE(fd < 0 && err != EBUSY,
54                       "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
55                       err, strerror_r(err, sbuf, sizeof(sbuf))))
56                 return -1;
57
58         close(fd);
59
60         return 0;
61 }
62
63 unsigned long perf_event_open_cloexec_flag(void)
64 {
65         static bool probed;
66
67         if (!probed) {
68                 if (perf_flag_probe() <= 0)
69                         flag = 0;
70                 probed = true;
71         }
72
73         return flag;
74 }