#![allow(non_camel_case_types)]
use std::mem;
use std::ptr;
use std::ffi::CStr;
use mach::kern_return::{self, kern_return_t};
use mach::traps::mach_task_self;
use mach::mach_port;
use mach::vm_types::{natural_t, integer_t};
use mach::message::mach_msg_type_number_t;
use mach::mach_types::host_t;
use heim_common::sys::macos;
use heim_common::prelude::*;
const PROCESSOR_CPU_LOAD_INFO: libc::c_int = 2;
const HOST_CPU_LOAD_INFO: libc::c_int = 3;
const HOST_VM_INFO: libc::c_int = 2;
type processor_flavor_t = libc::c_int;
type processor_info_array_t = *mut integer_t;
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)]
pub struct host_cpu_load_info {
pub user: natural_t,
pub system: natural_t,
pub idle: natural_t,
pub nice: natural_t,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)]
pub struct processor_cpu_load_info {
pub user: natural_t,
pub system: natural_t,
pub idle: natural_t,
pub nice: natural_t,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Hash, PartialOrd, PartialEq, Eq, Ord)]
pub struct vmmeter {
pub v_swtch: libc::c_uint,
pub v_trap: libc::c_uint,
pub v_syscall: libc::c_uint,
pub v_intr: libc::c_uint,
pub v_soft: libc::c_uint,
pub v_faults: libc::c_uint,
pub v_lookups: libc::c_uint,
pub v_hits: libc::c_uint,
pub v_vm_faults: libc::c_uint,
pub v_cow_faults: libc::c_uint,
pub v_swpin: libc::c_uint,
pub v_swpout: libc::c_uint,
pub v_pswpin: libc::c_uint,
pub v_pswpout: libc::c_uint,
pub v_pageins: libc::c_uint,
pub v_pageouts: libc::c_uint,
pub v_pgpgin: libc::c_uint,
pub v_pgpgout: libc::c_uint,
pub v_intrans: libc::c_uint,
pub v_reactivated: libc::c_uint,
pub v_rev: libc::c_uint,
pub v_scan: libc::c_uint,
pub v_dfree: libc::c_uint,
pub v_pfree: libc::c_uint,
pub v_zfod: libc::c_uint,
pub v_nzfod: libc::c_uint,
pub v_page_size: libc::c_uint,
pub v_kernel_pages: libc::c_uint,
pub v_free_target: libc::c_uint,
pub v_free_min: libc::c_uint,
pub v_free_count: libc::c_uint,
pub v_wire_count: libc::c_uint,
pub v_active_count: libc::c_uint,
pub v_inactive_target: libc::c_uint,
pub v_inactive_count: libc::c_uint,
}
extern "C" {
fn host_processor_info(
host: host_t,
flavor: processor_flavor_t,
out_processor_count: *mut natural_t,
out_processor_info: *mut processor_info_array_t,
out_processor_infoCnt: *const mach_msg_type_number_t,
) -> kern_return_t;
}
#[allow(trivial_casts)]
pub unsafe fn cpu_load_info() -> Result<host_cpu_load_info> {
let port = macos::mach_host_self();
let mut stats = host_cpu_load_info::default();
let count = mem::size_of::<host_cpu_load_info>() / mem::size_of::<integer_t>();
let result = macos::host_statistics64(
port,
HOST_CPU_LOAD_INFO,
&mut stats as *mut _ as macos::host_info64_t,
&count as *const _ as *const mach_msg_type_number_t,
);
let port_result = mach_port::mach_port_deallocate(mach_task_self(), port);
if port_result != kern_return::KERN_SUCCESS {
return Err(Error::last_os_error());
}
if result != kern_return::KERN_SUCCESS {
Err(Error::last_os_error())
} else {
Ok(stats)
}
}
#[allow(trivial_casts)]
pub unsafe fn processor_load_info() -> Result<Vec<processor_cpu_load_info>> {
let port = macos::mach_host_self();
let mut stats: Vec<processor_cpu_load_info> = Vec::with_capacity(1);
let count = mem::size_of::<processor_cpu_load_info>() / mem::size_of::<integer_t>();
let mut result_count: natural_t = 0;
let result = host_processor_info(
port,
PROCESSOR_CPU_LOAD_INFO,
&mut result_count,
&mut stats.as_mut_ptr() as *mut _ as *mut processor_info_array_t,
&count as *const _ as *const mach_msg_type_number_t
);
let port_result = mach_port::mach_port_deallocate(mach_task_self(), port);
if port_result != kern_return::KERN_SUCCESS {
return Err(Error::last_os_error());
}
if result != kern_return::KERN_SUCCESS {
Err(Error::last_os_error())
} else {
stats.set_len(result_count as usize);
Ok(stats)
}
}
#[allow(trivial_casts)]
pub unsafe fn vm_meter() -> Result<vmmeter> {
let port = macos::mach_host_self();
let mut stats = vmmeter::default();
let count = mem::size_of::<vmmeter>() / mem::size_of::<integer_t>();
let result = macos::host_statistics(
port,
HOST_VM_INFO,
&mut stats as *mut _ as macos::host_info_t,
&count as *const _ as *const mach_msg_type_number_t,
);
let port_result = mach_port::mach_port_deallocate(mach_task_self(), port);
if port_result != kern_return::KERN_SUCCESS {
return Err(Error::last_os_error());
}
if result != kern_return::KERN_SUCCESS {
Err(Error::last_os_error())
} else {
Ok(stats)
}
}
#[allow(trivial_casts)]
unsafe fn frequency(key: &[u8]) -> Result<u64> {
let str = CStr::from_bytes_with_nul_unchecked(key);
let mut value = 0u64;
let mut length = mem::size_of::<u64>();
let result = libc::sysctlbyname(
str.as_ptr(),
&mut value as *mut _ as *mut libc::c_void,
&mut length,
ptr::null_mut(),
0,
);
if result == 0 {
Ok(value)
} else {
Err(Error::last_os_error())
}
}
pub fn cpu_frequency() -> Result<u64> {
unsafe {
frequency(b"hw.cpufrequency\0")
}
}
pub fn cpu_frequency_max() -> Result<u64> {
unsafe {
frequency(b"hw.cpufrequency_max\0")
}
}
pub fn cpu_frequency_min() -> Result<u64> {
unsafe {
frequency(b"hw.cpufrequency_min\0")
}
}