1f6edb53cSAdrian Hunter #include <sched.h> 257480d2cSYann Droneaud #include "util.h" 357480d2cSYann Droneaud #include "../perf.h" 457480d2cSYann Droneaud #include "cloexec.h" 557480d2cSYann Droneaud #include "asm/bug.h" 66e81c74cSMasami Hiramatsu #include "debug.h" 757480d2cSYann Droneaud 857480d2cSYann Droneaud static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 957480d2cSYann Droneaud 10*e1e455f4SVinson Lee int __weak sched_getcpu(void) 11*e1e455f4SVinson Lee { 12*e1e455f4SVinson Lee errno = ENOSYS; 13*e1e455f4SVinson Lee return -1; 14*e1e455f4SVinson Lee } 15*e1e455f4SVinson Lee 1657480d2cSYann Droneaud static int perf_flag_probe(void) 1757480d2cSYann Droneaud { 1857480d2cSYann Droneaud /* use 'safest' configuration as used in perf_evsel__fallback() */ 1957480d2cSYann Droneaud struct perf_event_attr attr = { 20038fa0b9SJiri Olsa .type = PERF_TYPE_SOFTWARE, 2157480d2cSYann Droneaud .config = PERF_COUNT_SW_CPU_CLOCK, 22a5b0153cSAdrian Hunter .exclude_kernel = 1, 2357480d2cSYann Droneaud }; 2457480d2cSYann Droneaud int fd; 2557480d2cSYann Droneaud int err; 26f6edb53cSAdrian Hunter int cpu; 27f6edb53cSAdrian Hunter pid_t pid = -1; 286e81c74cSMasami Hiramatsu char sbuf[STRERR_BUFSIZE]; 2957480d2cSYann Droneaud 30f6edb53cSAdrian Hunter cpu = sched_getcpu(); 31f6edb53cSAdrian Hunter if (cpu < 0) 32f6edb53cSAdrian Hunter cpu = 0; 33f6edb53cSAdrian Hunter 3448536c91SAdrian Hunter /* 3548536c91SAdrian Hunter * Using -1 for the pid is a workaround to avoid gratuitous jump label 3648536c91SAdrian Hunter * changes. 3748536c91SAdrian Hunter */ 38f6edb53cSAdrian Hunter while (1) { 3957480d2cSYann Droneaud /* check cloexec flag */ 40f6edb53cSAdrian Hunter fd = sys_perf_event_open(&attr, pid, cpu, -1, 4157480d2cSYann Droneaud PERF_FLAG_FD_CLOEXEC); 42f6edb53cSAdrian Hunter if (fd < 0 && pid == -1 && errno == EACCES) { 43f6edb53cSAdrian Hunter pid = 0; 44f6edb53cSAdrian Hunter continue; 45f6edb53cSAdrian Hunter } 46f6edb53cSAdrian Hunter break; 47f6edb53cSAdrian Hunter } 4857480d2cSYann Droneaud err = errno; 4957480d2cSYann Droneaud 5057480d2cSYann Droneaud if (fd >= 0) { 5157480d2cSYann Droneaud close(fd); 5257480d2cSYann Droneaud return 1; 5357480d2cSYann Droneaud } 5457480d2cSYann Droneaud 5563914acaSJiri Olsa WARN_ONCE(err != EINVAL && err != EBUSY, 5657480d2cSYann Droneaud "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 576e81c74cSMasami Hiramatsu err, strerror_r(err, sbuf, sizeof(sbuf))); 5857480d2cSYann Droneaud 5957480d2cSYann Droneaud /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 6048536c91SAdrian Hunter while (1) { 61f6edb53cSAdrian Hunter fd = sys_perf_event_open(&attr, pid, cpu, -1, 0); 6248536c91SAdrian Hunter if (fd < 0 && pid == -1 && errno == EACCES) { 6348536c91SAdrian Hunter pid = 0; 6448536c91SAdrian Hunter continue; 6548536c91SAdrian Hunter } 6648536c91SAdrian Hunter break; 6748536c91SAdrian Hunter } 6857480d2cSYann Droneaud err = errno; 6957480d2cSYann Droneaud 7048536c91SAdrian Hunter if (fd >= 0) 7148536c91SAdrian Hunter close(fd); 7248536c91SAdrian Hunter 7363914acaSJiri Olsa if (WARN_ONCE(fd < 0 && err != EBUSY, 7457480d2cSYann Droneaud "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 756e81c74cSMasami Hiramatsu err, strerror_r(err, sbuf, sizeof(sbuf)))) 7657480d2cSYann Droneaud return -1; 7757480d2cSYann Droneaud 7857480d2cSYann Droneaud return 0; 7957480d2cSYann Droneaud } 8057480d2cSYann Droneaud 8157480d2cSYann Droneaud unsigned long perf_event_open_cloexec_flag(void) 8257480d2cSYann Droneaud { 8357480d2cSYann Droneaud static bool probed; 8457480d2cSYann Droneaud 8557480d2cSYann Droneaud if (!probed) { 8657480d2cSYann Droneaud if (perf_flag_probe() <= 0) 8757480d2cSYann Droneaud flag = 0; 8857480d2cSYann Droneaud probed = true; 8957480d2cSYann Droneaud } 9057480d2cSYann Droneaud 9157480d2cSYann Droneaud return flag; 9257480d2cSYann Droneaud } 93