diff options
Diffstat (limited to 'vendor/sysinfo-0.26.7/src/apple/macos/system.rs')
-rw-r--r-- | vendor/sysinfo-0.26.7/src/apple/macos/system.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/vendor/sysinfo-0.26.7/src/apple/macos/system.rs b/vendor/sysinfo-0.26.7/src/apple/macos/system.rs new file mode 100644 index 000000000..949532234 --- /dev/null +++ b/vendor/sysinfo-0.26.7/src/apple/macos/system.rs @@ -0,0 +1,136 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#[allow(deprecated)] +use libc::{mach_timebase_info, mach_timebase_info_data_t}; + +use libc::{ + host_processor_info, mach_port_t, munmap, natural_t, processor_cpu_load_info, + processor_cpu_load_info_t, sysconf, vm_page_size, PROCESSOR_CPU_LOAD_INFO, _SC_CLK_TCK, +}; +use std::ptr::null_mut; + +unsafe fn free_cpu_load_info(cpu_load: &mut processor_cpu_load_info_t) { + if !cpu_load.is_null() { + munmap(*cpu_load as _, vm_page_size); + *cpu_load = null_mut(); + } +} + +pub(crate) struct SystemTimeInfo { + timebase_to_ns: f64, + clock_per_sec: f64, + old_cpu_load: processor_cpu_load_info_t, + old_cpu_count: natural_t, +} + +unsafe impl Send for SystemTimeInfo {} +unsafe impl Sync for SystemTimeInfo {} + +impl SystemTimeInfo { + #[allow(deprecated)] // Everything related to mach_timebase_info_data_t + pub fn new(port: mach_port_t) -> Option<Self> { + unsafe { + let clock_ticks_per_sec = sysconf(_SC_CLK_TCK); + + // FIXME: Maybe check errno here? Problem is that if errno is not 0 before this call, + // we will get an error which isn't related... + // if let Some(er) = std::io::Error::last_os_error().raw_os_error() { + // if err != 0 { + // println!("==> {:?}", er); + // sysinfo_debug!("Failed to get _SC_CLK_TCK value, using old CPU tick measure system"); + // return None; + // } + // } + + let mut info = mach_timebase_info_data_t { numer: 0, denom: 0 }; + if mach_timebase_info(&mut info) != libc::KERN_SUCCESS { + sysinfo_debug!("mach_timebase_info failed, using default value of 1"); + info.numer = 1; + info.denom = 1; + } + + let mut old_cpu_load = null_mut(); + let old_cpu_count = match Self::update_ticks(port, &mut old_cpu_load) { + Some(c) => c, + None => { + sysinfo_debug!("host_processor_info failed, using old CPU tick measure system"); + return None; + } + }; + + let nano_per_seconds = 1_000_000_000.; + sysinfo_debug!(""); + Some(Self { + timebase_to_ns: info.numer as f64 / info.denom as f64, + clock_per_sec: nano_per_seconds / clock_ticks_per_sec as f64, + old_cpu_load, + old_cpu_count, + }) + } + } + + fn update_ticks( + port: mach_port_t, + cpu_load: &mut processor_cpu_load_info_t, + ) -> Option<natural_t> { + let mut info_size = std::mem::size_of::<processor_cpu_load_info_t>() as _; + let mut cpu_count = 0; + + unsafe { + free_cpu_load_info(cpu_load); + + if host_processor_info( + port, + PROCESSOR_CPU_LOAD_INFO, + &mut cpu_count, + cpu_load as *mut _ as *mut _, + &mut info_size, + ) != 0 + { + sysinfo_debug!("host_processor_info failed, not updating CPU ticks usage..."); + None + } else if cpu_count < 1 || cpu_load.is_null() { + None + } else { + Some(cpu_count) + } + } + } + + pub fn get_time_interval(&mut self, port: mach_port_t) -> f64 { + let mut total = 0; + let mut new_cpu_load = null_mut(); + + let new_cpu_count = match Self::update_ticks(port, &mut new_cpu_load) { + Some(c) => c, + None => return 0., + }; + let cpu_count = std::cmp::min(self.old_cpu_count, new_cpu_count); + unsafe { + for i in 0..cpu_count { + let new_load: &processor_cpu_load_info = &*new_cpu_load.offset(i as _); + let old_load: &processor_cpu_load_info = &*self.old_cpu_load.offset(i as _); + for (new, old) in new_load.cpu_ticks.iter().zip(old_load.cpu_ticks.iter()) { + if new > old { + total += new - old; + } + } + } + + free_cpu_load_info(&mut self.old_cpu_load); + self.old_cpu_load = new_cpu_load; + self.old_cpu_count = new_cpu_count; + + // Now we convert the ticks to nanoseconds: + total as f64 / self.timebase_to_ns * self.clock_per_sec / cpu_count as f64 + } + } +} + +impl Drop for SystemTimeInfo { + fn drop(&mut self) { + unsafe { + free_cpu_load_info(&mut self.old_cpu_load); + } + } +} |