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