fn test_perf_pmu_support()

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
}