Contributors: 8
Author |
Tokens |
Token Proportion |
Commits |
Commit Proportion |
Yann Droneaud |
177 |
44.81% |
1 |
5.56% |
Adrian Hunter |
106 |
26.84% |
3 |
16.67% |
Arnaldo Carvalho de Melo |
53 |
13.42% |
7 |
38.89% |
Masami Hiramatsu |
23 |
5.82% |
1 |
5.56% |
Vinson Lee |
16 |
4.05% |
1 |
5.56% |
Jiri Olsa |
11 |
2.78% |
3 |
16.67% |
Alexey Budankov |
8 |
2.03% |
1 |
5.56% |
Greg Kroah-Hartman |
1 |
0.25% |
1 |
5.56% |
Total |
395 |
|
18 |
|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
// SPDX-License-Identifier: GPL-2.0
#include <errno.h>
#include <sched.h>
#include "util.h" // for sched_getcpu()
#include "../perf-sys.h"
#include "cloexec.h"
#include "event.h"
#include "asm/bug.h"
#include "debug.h"
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/string.h>
static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
int __weak sched_getcpu(void)
{
#ifdef __NR_getcpu
unsigned cpu;
int err = syscall(__NR_getcpu, &cpu, NULL, NULL);
if (!err)
return cpu;
#else
errno = ENOSYS;
#endif
return -1;
}
static int perf_flag_probe(void)
{
/* use 'safest' configuration as used in evsel__fallback() */
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_CPU_CLOCK,
.exclude_kernel = 1,
};
int fd;
int err;
int cpu;
pid_t pid = -1;
char sbuf[STRERR_BUFSIZE];
cpu = sched_getcpu();
if (cpu < 0)
cpu = 0;
/*
* Using -1 for the pid is a workaround to avoid gratuitous jump label
* changes.
*/
while (1) {
/* check cloexec flag */
fd = sys_perf_event_open(&attr, pid, cpu, -1,
PERF_FLAG_FD_CLOEXEC);
if (fd < 0 && pid == -1 && errno == EACCES) {
pid = 0;
continue;
}
break;
}
err = errno;
if (fd >= 0) {
close(fd);
return 1;
}
WARN_ONCE(err != EINVAL && err != EBUSY && err != EACCES,
"perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
err, str_error_r(err, sbuf, sizeof(sbuf)));
/* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
while (1) {
fd = sys_perf_event_open(&attr, pid, cpu, -1, 0);
if (fd < 0 && pid == -1 && errno == EACCES) {
pid = 0;
continue;
}
break;
}
err = errno;
if (fd >= 0)
close(fd);
if (WARN_ONCE(fd < 0 && err != EBUSY && err != EACCES,
"perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
err, str_error_r(err, sbuf, sizeof(sbuf))))
return -1;
return 0;
}
unsigned long perf_event_open_cloexec_flag(void)
{
static bool probed;
if (!probed) {
if (perf_flag_probe() <= 0)
flag = 0;
probed = true;
}
return flag;
}