use crate::cpu_info::CpuInfo;
use std::ffi::{c_char, c_int, c_void, CStr};
extern "C" {
fn sysctlbyname(
name: *const c_char,
oldp: *mut c_void,
oldlenp: *mut usize,
newp: *mut c_void,
newlen: usize,
) -> c_int;
}
#[cfg(target_vendor = "apple")]
pub fn read_cpu_info() -> Option<CpuInfo> {
const MACHDEP_CPU_CORE_COUNT: *const c_char =
unsafe { CStr::from_bytes_with_nul_unchecked(b"machdep.cpu.core_count\0").as_ptr() };
const MACHDEP_CPU_BRAND_STRING: *const c_char =
unsafe { CStr::from_bytes_with_nul_unchecked(b"machdep.cpu.brand_string\0").as_ptr() };
read_cpu_info_bsd(MACHDEP_CPU_CORE_COUNT, MACHDEP_CPU_BRAND_STRING)
}
#[cfg(not(target_vendor = "apple"))]
pub fn read_cpu_info() -> Option<CpuInfo> {
const HW_NCPU: *const c_char =
unsafe { CStr::from_bytes_with_nul_unchecked(b"hw.ncpu\0").as_ptr() };
const HW_MODEL: *const c_char =
unsafe { CStr::from_bytes_with_nul_unchecked(b"hw.model\0").as_ptr() };
read_cpu_info_bsd(HW_NCPU, HW_MODEL)
}
fn read_cpu_info_bsd(
name_core_count: *const c_char,
name_brand_string: *const c_char,
) -> Option<CpuInfo> {
let mut core_count: i32 = 0;
unsafe {
let mut size = std::mem::size_of::<i32>();
let res = sysctlbyname(
name_core_count,
&mut core_count as *mut i32 as _,
&mut size,
std::ptr::null_mut(),
0,
);
if res != 0 {
return None;
}
let res = sysctlbyname(
name_brand_string,
std::ptr::null_mut(),
&mut size,
std::ptr::null_mut(),
0,
);
if res != 0 {
return None;
}
let mut buffer = vec![0u8; size + 1];
let res = sysctlbyname(
name_brand_string,
buffer.as_mut_ptr() as _,
&mut size,
std::ptr::null_mut(),
0,
);
if res != 0 {
return None;
}
Some(CpuInfo {
core_count: core_count as _,
name: CStr::from_ptr(buffer.as_ptr() as _)
.to_string_lossy()
.into(),
})
}
}