blob: e96c2972f8ea5736020ec226b0861eea90aed5d9 [file] [log] [blame]
// Take a look at the license at the top of the repository in the LICENSE file.
#[cfg(feature = "apple-sandbox")]
pub(crate) unsafe fn get_cpu_frequency() -> u64 {
0
}
#[cfg(not(feature = "apple-sandbox"))]
pub(crate) unsafe fn get_cpu_frequency() -> u64 {
use crate::sys::ffi;
use crate::sys::macos::utils::IOReleaser;
use crate::sys::utils::CFReleaser;
let matching = ffi::IOServiceMatching(b"AppleARMIODevice\0".as_ptr() as *const _);
if matching.is_null() {
sysinfo_debug!("IOServiceMatching call failed, `AppleARMIODevice` not found");
return 0;
}
// Starting from mac M1, the above call returns nothing for the CPU frequency
// so we try to get it from another source. This code comes from
// <https://github.com/giampaolo/psutil/pull/2222>.
let mut iterator: ffi::io_iterator_t = 0;
let result =
ffi::IOServiceGetMatchingServices(ffi::kIOMasterPortDefault, matching, &mut iterator);
if result != ffi::KIO_RETURN_SUCCESS {
sysinfo_debug!("Error: IOServiceGetMatchingServices() = {}", result);
return 0;
}
let iterator = match IOReleaser::new(iterator) {
Some(i) => i,
None => {
sysinfo_debug!(
"Error: IOServiceGetMatchingServices() succeeded but returned invalid descriptor"
);
return 0;
}
};
let mut name: ffi::io_name = std::mem::zeroed();
let entry = loop {
let entry = match IOReleaser::new(ffi::IOIteratorNext(iterator.inner())) {
Some(d) => d,
None => {
sysinfo_debug!("`pmgr` entry was not found in AppleARMIODevice service");
return 0;
}
};
let status = ffi::IORegistryEntryGetName(entry.inner(), name.as_mut_ptr());
if status != libc::KERN_SUCCESS {
continue;
} else if libc::strcmp(name.as_ptr(), b"pmgr\0".as_ptr() as *const _) == 0 {
break entry;
}
};
let node_name = match CFReleaser::new(ffi::CFStringCreateWithCStringNoCopy(
std::ptr::null(),
b"voltage-states5-sram\0".as_ptr() as *const _,
core_foundation_sys::string::kCFStringEncodingUTF8,
core_foundation_sys::base::kCFAllocatorNull as *mut _,
)) {
Some(n) => n,
None => {
sysinfo_debug!("CFStringCreateWithCStringNoCopy failed");
return 0;
}
};
let core_ref = match CFReleaser::new(ffi::IORegistryEntryCreateCFProperty(
entry.inner(),
node_name.inner(),
core_foundation_sys::base::kCFAllocatorDefault,
0,
)) {
Some(c) => c,
None => {
sysinfo_debug!("`voltage-states5-sram` property not found");
return 0;
}
};
let core_length = core_foundation_sys::data::CFDataGetLength(core_ref.inner() as *const _);
if core_length < 8 {
sysinfo_debug!("expected `voltage-states5-sram` buffer to have at least size 8");
return 0;
}
let mut max: u64 = 0;
core_foundation_sys::data::CFDataGetBytes(
core_ref.inner() as *const _,
core_foundation_sys::base::CFRange::init(core_length - 8, 4),
&mut max as *mut _ as *mut _,
);
max / 1_000_000
}