include!("common.rs");
use core::ptr;
#[allow(non_camel_case_types)]
mod ffi {
pub(crate) use super::c_types::{c_char, c_int, c_size_t, c_void};
extern "C" {
pub(crate) fn sysctlbyname(
name: *const c_char,
old_p: *mut c_void,
old_len_p: *mut c_size_t,
new_p: *mut c_void,
new_len: c_size_t,
) -> c_int;
}
}
unsafe fn sysctlbyname32(name: &[u8]) -> Option<u32> {
const OUT_LEN: ffi::c_size_t = core::mem::size_of::<u32>() as ffi::c_size_t;
debug_assert_eq!(name.last(), Some(&0), "{:?}", name);
debug_assert_eq!(name.iter().filter(|&&v| v == 0).count(), 1, "{:?}", name);
let mut out = 0_u32;
let mut out_len = OUT_LEN;
let res = unsafe {
ffi::sysctlbyname(
name.as_ptr().cast::<ffi::c_char>(),
(&mut out as *mut u32).cast::<ffi::c_void>(),
&mut out_len,
ptr::null_mut(),
0,
)
};
if res != 0 {
return None;
}
debug_assert_eq!(out_len, OUT_LEN);
Some(out)
}
#[cold]
fn _detect(info: &mut CpuInfo) {
if unsafe {
sysctlbyname32(b"hw.optional.arm.FEAT_LSE\0").unwrap_or(0) != 0
|| sysctlbyname32(b"hw.optional.armv8_1_atomics\0").unwrap_or(0) != 0
} {
info.set(CpuInfo::HAS_LSE);
}
if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE2\0").unwrap_or(0) != 0 } {
info.set(CpuInfo::HAS_LSE2);
}
#[cfg(test)]
{
if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LSE128\0").unwrap_or(0) != 0 } {
info.set(CpuInfo::HAS_LSE128);
}
if unsafe { sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC3\0").unwrap_or(0) != 0 } {
info.set(CpuInfo::HAS_RCPC3);
}
}
}
#[allow(
clippy::alloc_instead_of_core,
clippy::std_instead_of_alloc,
clippy::std_instead_of_core,
clippy::undocumented_unsafe_blocks,
clippy::wildcard_imports
)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_macos() {
unsafe {
assert_eq!(sysctlbyname32(b"hw.optional.armv8_1_atomics\0"), Some(1));
assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LSE\0"), Some(1));
assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LSE2\0"), Some(1));
assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LSE128\0"), None);
assert_eq!(std::io::Error::last_os_error().kind(), std::io::ErrorKind::NotFound);
assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC\0"), Some(1));
assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC2\0"), Some(1));
assert_eq!(sysctlbyname32(b"hw.optional.arm.FEAT_LRCPC3\0"), None);
assert_eq!(std::io::Error::last_os_error().kind(), std::io::ErrorKind::NotFound);
}
}
#[allow(
clippy::cast_possible_wrap,
clippy::cast_sign_loss,
clippy::no_effect_underscore_binding
)]
const _: fn() = || {
use test_helper::{libc, sys};
let mut _sysctlbyname: unsafe extern "C" fn(
*const ffi::c_char,
*mut ffi::c_void,
*mut ffi::c_size_t,
*mut ffi::c_void,
ffi::c_size_t,
) -> ffi::c_int = ffi::sysctlbyname;
_sysctlbyname = libc::sysctlbyname;
_sysctlbyname = sys::sysctlbyname;
};
}