in reverie-ptrace/src/perf.rs [511:541]
fn test_perf_pmu_support() -> bool {
// Do a raw perf_event_open because our default configuration has flags that
// might be the actual cause of the error, which we want to catch separately.
let evt = Event::Hardware(HardwareEvent::Instructions);
let mut attr = perf::perf_event_attr::default();
attr.size = core::mem::size_of_val(&attr) as u32;
attr.type_ = evt.attr_type();
attr.config = evt.attr_config();
attr.__bindgen_anon_1.sample_period = PerfCounter::DISABLE_SAMPLE_PERIOD;
attr.set_exclude_kernel(1); // lowers permission requirements
let pid: libc::pid_t = 0; // track this thread
let cpu: libc::c_int = -1; // across any CPU
let group_fd: libc::c_int = -1;
let flags = perf::PERF_FLAG_FD_CLOEXEC;
let res = Errno::result(unsafe {
libc::syscall(libc::SYS_perf_event_open, &attr, pid, cpu, group_fd, flags)
});
match res {
Ok(fd) => {
Errno::result(unsafe { libc::close(fd as libc::c_int) })
.expect("perf feature check: close(fd) failed");
return true;
}
Err(Errno::ENOENT) => info!("Perf feature check failed due to ENOENT"),
Err(Errno::EPERM) => info!("Perf feature check failed due to EPERM"),
Err(Errno::EACCES) => info!("Perf feature check failed due to EACCES"),
Err(e) => panic!("Unexpected error during perf feature check: {}", e),
}
false
}