#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use std::mem::{size_of, zeroed};
use std::os::raw::{c_int, c_void};
use std::ptr;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Mutex;
use crate::ported::crt::{CRT_fatalError, ColorElements};
use crate::ported::linux::platform::MemoryClass;
use crate::ported::signalspanel::SignalItem;
use crate::ported::darwin::darwinmachine::DarwinMachine;
#[cfg(target_arch = "x86_64")]
use crate::ported::darwin::platformhelpers::{
KernelVersion, Platform_CompareKernelVersion, Platform_isRunningTranslated,
};
use crate::ported::batterymeter::BatteryMeter_class;
use crate::ported::cpumeter::{
AllCPUs2Meter_class, AllCPUs4Meter_class, AllCPUs8Meter_class, AllCPUsMeter_class,
CPUMeter_class, LeftCPUs2Meter_class, LeftCPUs4Meter_class, LeftCPUs8Meter_class,
LeftCPUsMeter_class, RightCPUs2Meter_class, RightCPUs4Meter_class, RightCPUs8Meter_class,
RightCPUsMeter_class,
};
use crate::ported::datetimemeter::{ClockMeter_class, DateMeter_class, DateTimeMeter_class};
use crate::ported::hostnamemeter::HostnameMeter_class;
use crate::ported::loadaveragemeter::{LoadAverageMeter_class, LoadMeter_class};
#[cfg(test)]
use crate::ported::machine::Machine;
use crate::ported::memorymeter::MemoryMeter_class;
use crate::ported::meter::{BlankMeter_class, Meter, MeterClass};
use crate::ported::networkiometer::NetworkIOData;
use crate::ported::swapmeter::SwapMeter_class;
use crate::ported::sysarchmeter::SysArchMeter_class;
use crate::ported::tasksmeter::TasksMeter_class;
use crate::ported::uptimemeter::{SecondsUptimeMeter_class, UptimeMeter_class};
use crate::ported::xutils::saturatingSub;
const KERN_SUCCESS: c_int = 0;
const IFT_LOOP: u8 = 0x18;
const SYSTEM_CLOCK: c_int = 0;
#[repr(C)]
struct mach_timespec_t {
tv_sec: libc::c_uint,
tv_nsec: c_int,
}
extern "C" {
fn host_get_clock_service(
host: libc::mach_port_t,
clock_id: c_int,
clock_serv: *mut libc::mach_port_t,
) -> c_int;
fn clock_get_time(clock_serv: libc::mach_port_t, cur_time: *mut mach_timespec_t) -> c_int;
fn mach_port_deallocate(task: libc::mach_port_t, name: libc::mach_port_t) -> c_int;
}
static Platform_nanosecondsPerMachTickNumer: AtomicU64 = AtomicU64::new(1);
static Platform_nanosecondsPerMachTickDenom: AtomicU64 = AtomicU64::new(1);
static Platform_nanosecondsPerSchedulerTick: Mutex<f64> = Mutex::new(-1.0);
#[allow(deprecated)]
pub fn Platform_calculateNanosecondsPerMachTick(numer: &mut u64, denom: &mut u64) {
#[cfg(target_arch = "x86_64")]
{
let isRunningUnderRosetta2 = Platform_isRunningTranslated();
let isBuggedVersion = 0
<= Platform_CompareKernelVersion(KernelVersion {
major: 20,
minor: 0,
patch: 0,
});
if isRunningUnderRosetta2 && isBuggedVersion {
*numer = 125;
*denom = 3;
return;
}
}
let mut info: libc::mach_timebase_info_data_t = unsafe { zeroed() };
if unsafe { libc::mach_timebase_info(&mut info) } == KERN_SUCCESS {
*numer = info.numer as u64;
*denom = info.denom as u64;
return;
}
*numer = 1;
*denom = 1;
}
pub fn Platform_machTicksToNanoseconds(mach_ticks: u64) -> u64 {
let numer = Platform_nanosecondsPerMachTickNumer.load(Ordering::Relaxed);
let denom = Platform_nanosecondsPerMachTickDenom.load(Ordering::Relaxed);
let ticks_quot = mach_ticks / denom;
let ticks_rem = mach_ticks % denom;
let part1 = ticks_quot * numer;
let part2 = (ticks_rem * numer) / denom;
part1 + part2
}
pub fn Platform_init() -> bool {
let mut numer: u64 = 1;
let mut denom: u64 = 1;
Platform_calculateNanosecondsPerMachTick(&mut numer, &mut denom);
Platform_nanosecondsPerMachTickNumer.store(numer, Ordering::Relaxed);
Platform_nanosecondsPerMachTickDenom.store(denom, Ordering::Relaxed);
let scheduler_ticks_per_sec = unsafe { libc::sysconf(libc::_SC_CLK_TCK) };
if scheduler_ticks_per_sec < 1 {
CRT_fatalError("Unable to retrieve clock tick rate");
}
let nanos_per_sec = 1e9;
*Platform_nanosecondsPerSchedulerTick.lock().unwrap() =
nanos_per_sec / scheduler_ticks_per_sec as f64;
true
}
pub fn Platform_schedulerTicksToNanoseconds(scheduler_ticks: f64) -> f64 {
scheduler_ticks * *Platform_nanosecondsPerSchedulerTick.lock().unwrap()
}
pub fn Platform_done() {
}
pub fn Platform_setBindings() {
}
pub fn Platform_getUptime() -> c_int {
let mut bootTime: libc::timeval = unsafe { zeroed() };
let mut mib: [c_int; 2] = [libc::CTL_KERN, libc::KERN_BOOTTIME];
let mut size = size_of::<libc::timeval>();
let err = unsafe {
libc::sysctl(
mib.as_mut_ptr(),
2,
&mut bootTime as *mut libc::timeval as *mut c_void,
&mut size,
ptr::null_mut(),
0,
)
};
if err != 0 {
return -1;
}
let mut currTime: libc::timeval = unsafe { zeroed() };
unsafe { libc::gettimeofday(&mut currTime, ptr::null_mut()) };
(currTime.tv_sec - bootTime.tv_sec) as c_int
}
pub fn Platform_getLoadAverage(one: &mut f64, five: &mut f64, fifteen: &mut f64) {
let mut results = [0.0f64; 3];
if 3 == unsafe { libc::getloadavg(results.as_mut_ptr(), 3) } {
*one = results[0];
*five = results[1];
*fifteen = results[2];
} else {
*one = 0.0;
*five = 0.0;
*fifteen = 0.0;
}
}
pub static Platform_signals: &[SignalItem] = &[
SignalItem {
name: " 0 Cancel",
number: 0,
},
SignalItem {
name: " 1 SIGHUP",
number: 1,
},
SignalItem {
name: " 2 SIGINT",
number: 2,
},
SignalItem {
name: " 3 SIGQUIT",
number: 3,
},
SignalItem {
name: " 4 SIGILL",
number: 4,
},
SignalItem {
name: " 5 SIGTRAP",
number: 5,
},
SignalItem {
name: " 6 SIGABRT",
number: 6,
},
SignalItem {
name: " 6 SIGIOT",
number: 6,
},
SignalItem {
name: " 7 SIGEMT",
number: 7,
},
SignalItem {
name: " 8 SIGFPE",
number: 8,
},
SignalItem {
name: " 9 SIGKILL",
number: 9,
},
SignalItem {
name: "10 SIGBUS",
number: 10,
},
SignalItem {
name: "11 SIGSEGV",
number: 11,
},
SignalItem {
name: "12 SIGSYS",
number: 12,
},
SignalItem {
name: "13 SIGPIPE",
number: 13,
},
SignalItem {
name: "14 SIGALRM",
number: 14,
},
SignalItem {
name: "15 SIGTERM",
number: 15,
},
SignalItem {
name: "16 SIGURG",
number: 16,
},
SignalItem {
name: "17 SIGSTOP",
number: 17,
},
SignalItem {
name: "18 SIGTSTP",
number: 18,
},
SignalItem {
name: "19 SIGCONT",
number: 19,
},
SignalItem {
name: "20 SIGCHLD",
number: 20,
},
SignalItem {
name: "21 SIGTTIN",
number: 21,
},
SignalItem {
name: "22 SIGTTOU",
number: 22,
},
SignalItem {
name: "23 SIGIO",
number: 23,
},
SignalItem {
name: "24 SIGXCPU",
number: 24,
},
SignalItem {
name: "25 SIGXFSZ",
number: 25,
},
SignalItem {
name: "26 SIGVTALRM",
number: 26,
},
SignalItem {
name: "27 SIGPROF",
number: 27,
},
SignalItem {
name: "28 SIGWINCH",
number: 28,
},
SignalItem {
name: "29 SIGINFO",
number: 29,
},
SignalItem {
name: "30 SIGUSR1",
number: 30,
},
SignalItem {
name: "31 SIGUSR2",
number: 31,
},
];
pub const Platform_numberOfSignals: usize = Platform_signals.len();
pub fn Platform_getMaxPid() -> libc::pid_t {
99999
}
const CPU_METER_NICE: usize = 0;
const CPU_METER_NORMAL: usize = 1;
const CPU_METER_KERNEL: usize = 2;
const CPU_METER_FREQUENCY: usize = 8;
const CPU_METER_TEMPERATURE: usize = 9;
fn Platform_setCPUAverageValues(mtr: &mut Meter) -> f64 {
let host = mtr.host;
let (active_cpus, existing_cpus) = unsafe { ((*host).activeCPUs, (*host).existingCPUs) };
let mut sum_nice = 0.0;
let mut sum_normal = 0.0;
let mut sum_kernel = 0.0;
let mut sum_percent = 0.0;
for i in 1..=existing_cpus {
sum_percent += Platform_setCPUValues(mtr, i);
sum_nice += mtr.values[CPU_METER_NICE];
sum_normal += mtr.values[CPU_METER_NORMAL];
sum_kernel += mtr.values[CPU_METER_KERNEL];
}
mtr.values[CPU_METER_NICE] = sum_nice / active_cpus as f64;
mtr.values[CPU_METER_NORMAL] = sum_normal / active_cpus as f64;
mtr.values[CPU_METER_KERNEL] = sum_kernel / active_cpus as f64;
sum_percent / active_cpus as f64
}
pub fn Platform_setCPUValues(mtr: &mut Meter, cpu: u32) -> f64 {
if cpu == 0 {
return Platform_setCPUAverageValues(mtr);
}
let dhost = mtr.host as *const DarwinMachine;
let (prev, curr) = unsafe {
(
&*(*dhost).prev_load.add((cpu - 1) as usize),
&*(*dhost).curr_load.add((cpu - 1) as usize),
)
};
let mut total = 0.0;
for i in 0..libc::CPU_STATE_MAX as usize {
total += curr.cpu_ticks[i] as f64 - prev.cpu_ticks[i] as f64;
}
let delta = |state: c_int| {
curr.cpu_ticks[state as usize] as f64 - prev.cpu_ticks[state as usize] as f64
};
if total > 1e-6 {
mtr.values[CPU_METER_NICE] = delta(libc::CPU_STATE_NICE) * 100.0 / total;
mtr.values[CPU_METER_NORMAL] = delta(libc::CPU_STATE_USER) * 100.0 / total;
mtr.values[CPU_METER_KERNEL] = delta(libc::CPU_STATE_SYSTEM) * 100.0 / total;
} else {
mtr.values[CPU_METER_NICE] = 0.0;
mtr.values[CPU_METER_NORMAL] = 0.0;
mtr.values[CPU_METER_KERNEL] = 0.0;
}
mtr.curItems = 3;
let total_pct =
mtr.values[CPU_METER_NICE] + mtr.values[CPU_METER_NORMAL] + mtr.values[CPU_METER_KERNEL];
mtr.values[CPU_METER_FREQUENCY] = f64::NAN;
mtr.values[CPU_METER_TEMPERATURE] = f64::NAN;
total_pct.clamp(0.0, 100.0)
}
pub fn Platform_setGPUValues() {
todo!("port of Platform.c:363")
}
#[allow(non_upper_case_globals)] pub static Platform_meterTypes: &[&MeterClass] = &[
&CPUMeter_class,
&ClockMeter_class,
&DateMeter_class,
&DateTimeMeter_class,
&LoadAverageMeter_class,
&LoadMeter_class,
&MemoryMeter_class,
&SwapMeter_class,
&TasksMeter_class,
&BatteryMeter_class,
&HostnameMeter_class,
&SysArchMeter_class,
&UptimeMeter_class,
&SecondsUptimeMeter_class,
&AllCPUsMeter_class,
&AllCPUs2Meter_class,
&AllCPUs4Meter_class,
&AllCPUs8Meter_class,
&LeftCPUsMeter_class,
&RightCPUsMeter_class,
&LeftCPUs2Meter_class,
&RightCPUs2Meter_class,
&LeftCPUs4Meter_class,
&RightCPUs4Meter_class,
&LeftCPUs8Meter_class,
&RightCPUs8Meter_class,
&BlankMeter_class,
];
pub static Platform_memoryClasses: [MemoryClass; 6] = [
MemoryClass {
label: "wired",
countsAsUsed: true,
countsAsCache: false,
color: ColorElements::MEMORY_1,
},
MemoryClass {
label: "speculative",
countsAsUsed: true,
countsAsCache: true,
color: ColorElements::MEMORY_2,
},
MemoryClass {
label: "active",
countsAsUsed: true,
countsAsCache: false,
color: ColorElements::MEMORY_3,
},
MemoryClass {
label: "purgeable",
countsAsUsed: false,
countsAsCache: true,
color: ColorElements::MEMORY_4,
},
MemoryClass {
label: "compressed",
countsAsUsed: true,
countsAsCache: false,
color: ColorElements::MEMORY_5,
},
MemoryClass {
label: "inactive",
countsAsUsed: true,
countsAsCache: true,
color: ColorElements::MEMORY_6,
},
];
#[allow(non_upper_case_globals)] pub const Platform_numberOfMemoryClasses: usize = Platform_memoryClasses.len();
const MEMORY_CLASS_WIRED: usize = 0;
const MEMORY_CLASS_SPECULATIVE: usize = 1;
const MEMORY_CLASS_ACTIVE: usize = 2;
const MEMORY_CLASS_PURGEABLE: usize = 3;
const MEMORY_CLASS_COMPRESSED: usize = 4;
const MEMORY_CLASS_INACTIVE: usize = 5;
pub fn Platform_setMemoryValues(mtr: &mut Meter) {
let host = mtr.host;
let dhost = host as *const DarwinMachine;
let page_k = unsafe { libc::vm_page_size } as f64 / 1024.0;
let vm = unsafe { &(*dhost).vm_stats };
let external_page_count = vm.external_page_count;
let compressor_page_count = vm.compressor_page_count;
let show_cached = unsafe {
(*host)
.settings
.as_ref()
.is_some_and(|s| s.showCachedMemory)
};
mtr.total = (unsafe { (*dhost).host_info.max_mem } / 1024) as f64;
mtr.values[MEMORY_CLASS_WIRED] = page_k * vm.wire_count as f64;
if show_cached {
mtr.values[MEMORY_CLASS_SPECULATIVE] = page_k * vm.speculative_count as f64;
mtr.values[MEMORY_CLASS_ACTIVE] = page_k
* saturatingSub(
vm.active_count as u64,
vm.purgeable_count as u64 + external_page_count as u64,
) as f64;
mtr.values[MEMORY_CLASS_PURGEABLE] = page_k * vm.purgeable_count as f64;
} else {
mtr.values[MEMORY_CLASS_SPECULATIVE] = 0.0;
mtr.values[MEMORY_CLASS_ACTIVE] = page_k
* saturatingSub(
vm.speculative_count as u64 + vm.active_count as u64,
external_page_count as u64,
) as f64;
mtr.values[MEMORY_CLASS_PURGEABLE] = 0.0;
}
mtr.values[MEMORY_CLASS_COMPRESSED] = page_k * compressor_page_count as f64;
mtr.values[MEMORY_CLASS_INACTIVE] = page_k * vm.inactive_count as f64;
}
pub fn Platform_setSwapValues(mtr: &mut Meter) {
const SWAP_METER_USED: usize = 0;
let mut mib: [c_int; 2] = [libc::CTL_VM, libc::VM_SWAPUSAGE];
let mut swapused: libc::xsw_usage = unsafe { zeroed() };
let mut swlen = size_of::<libc::xsw_usage>();
unsafe {
libc::sysctl(
mib.as_mut_ptr(),
2,
&mut swapused as *mut libc::xsw_usage as *mut c_void,
&mut swlen,
ptr::null_mut(),
0,
);
}
mtr.total = (swapused.xsu_total / 1024) as f64;
mtr.values[SWAP_METER_USED] = (swapused.xsu_used / 1024) as f64;
}
pub fn Platform_setZfsArcValues() {
todo!("port of Platform.c:465")
}
pub fn Platform_setZfsCompressedArcValues() {
todo!("port of Platform.c:471")
}
pub fn Platform_getProcessEnv(pid: libc::pid_t) -> Option<String> {
let mut env: Option<String> = None;
let mut argmax: c_int = 0;
let mut bufsz = size_of::<c_int>();
let mut mib: [c_int; 3] = [libc::CTL_KERN, libc::KERN_ARGMAX, 0];
if unsafe {
libc::sysctl(
mib.as_mut_ptr(),
2,
&mut argmax as *mut c_int as *mut c_void,
&mut bufsz,
ptr::null_mut(),
0,
)
} == 0
{
let mut buf = vec![0u8; argmax as usize];
mib[0] = libc::CTL_KERN;
mib[1] = libc::KERN_PROCARGS2;
mib[2] = pid;
bufsz = argmax as usize;
if unsafe {
libc::sysctl(
mib.as_mut_ptr(),
3,
buf.as_mut_ptr() as *mut c_void,
&mut bufsz,
ptr::null_mut(),
0,
)
} == 0
&& bufsz > size_of::<c_int>()
{
let endp = bufsz;
let mut p = 0usize;
let mut argc = i32::from_ne_bytes([buf[0], buf[1], buf[2], buf[3]]);
p += size_of::<c_int>();
while p < endp && buf[p] != 0 {
p += 1;
}
if p < endp {
p += 1;
}
while p < endp && buf[p] == 0 {
p += 1;
}
while argc > 0 && p < endp {
argc -= 1;
while p < endp && buf[p] != 0 {
p += 1;
}
if p < endp {
p += 1;
}
}
while p < endp && buf[p] == 0 {
p += 1;
}
let mut bytes = buf[p..endp].to_vec();
bytes.push(0);
bytes.push(0);
env = Some(String::from_utf8_lossy(&bytes).into_owned());
}
}
env
}
pub fn Platform_getProcessLocks(
pid: libc::pid_t,
) -> Option<crate::ported::processlocksscreen::FileLocks_ProcessData> {
let _ = pid;
None
}
pub fn Platform_getFileDescriptors() {
todo!("port of Platform.c:533")
}
pub fn Platform_getDiskIO() {
todo!("port of Platform.c:537")
}
pub fn Platform_getNetworkIO(data: &mut NetworkIOData) -> bool {
let mut mib: [c_int; 6] = [
libc::CTL_NET,
libc::PF_ROUTE,
0,
0,
libc::NET_RT_IFLIST2,
0,
];
for retry in 0..4usize {
let mut len: usize = 0;
if unsafe {
libc::sysctl(
mib.as_mut_ptr(),
6,
ptr::null_mut(),
&mut len,
ptr::null_mut(),
0,
)
} < 0
|| len == 0
{
return false;
}
len += 16 * retry * retry * size_of::<libc::if_msghdr2>();
let mut buf = vec![0u8; len];
if unsafe {
libc::sysctl(
mib.as_mut_ptr(),
6,
buf.as_mut_ptr() as *mut c_void,
&mut len,
ptr::null_mut(),
0,
)
} < 0
{
let err = std::io::Error::last_os_error();
if err.raw_os_error() == Some(libc::ENOMEM) && retry < 3 {
continue;
} else {
return false;
}
}
let mut bytesReceived_sum: u64 = 0;
let mut packetsReceived_sum: u64 = 0;
let mut bytesTransmitted_sum: u64 = 0;
let mut packetsTransmitted_sum: u64 = 0;
let mut next = 0usize;
while next < len {
let ifm =
unsafe { ptr::read_unaligned(buf.as_ptr().add(next) as *const libc::if_msghdr) };
next += ifm.ifm_msglen as usize;
if ifm.ifm_type as c_int != libc::RTM_IFINFO2 {
continue;
}
let ifm2 = unsafe {
ptr::read_unaligned(
buf.as_ptr().add(next - ifm.ifm_msglen as usize) as *const libc::if_msghdr2
)
};
if ifm2.ifm_data.ifi_type != IFT_LOOP {
bytesReceived_sum += ifm2.ifm_data.ifi_ibytes;
packetsReceived_sum += ifm2.ifm_data.ifi_ipackets;
bytesTransmitted_sum += ifm2.ifm_data.ifi_obytes;
packetsTransmitted_sum += ifm2.ifm_data.ifi_opackets;
}
}
data.bytesReceived = bytesReceived_sum;
data.packetsReceived = packetsReceived_sum;
data.bytesTransmitted = bytesTransmitted_sum;
data.packetsTransmitted = packetsTransmitted_sum;
}
true
}
pub fn Platform_getBattery() {
todo!("port of Platform.c:684")
}
pub fn Platform_gettime_realtime(tv: &mut libc::timeval, msec: &mut u64) {
let mut ts: libc::timespec = unsafe { zeroed() };
if unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut ts) } == 0 {
tv.tv_sec = ts.tv_sec;
tv.tv_usec = (ts.tv_nsec / 1000) as libc::suseconds_t;
*msec = (ts.tv_sec as u64 * 1000) + (ts.tv_nsec as u64 / 1_000_000);
} else {
*tv = unsafe { zeroed() };
*msec = 0;
}
}
#[allow(deprecated)]
pub fn Platform_gettime_monotonic(msec: &mut u64) {
let mut cclock: libc::mach_port_t = 0;
let mut mts = mach_timespec_t {
tv_sec: 0,
tv_nsec: 0,
};
unsafe {
host_get_clock_service(libc::mach_host_self(), SYSTEM_CLOCK, &mut cclock);
clock_get_time(cclock, &mut mts);
mach_port_deallocate(libc::mach_task_self(), cclock);
}
*msec = (mts.tv_sec as u64 * 1000) + (mts.tv_nsec as u64 / 1000000);
}
pub fn Platform_getOSRelease() {
todo!("port of Platform.c:760")
}
pub fn Platform_getRelease() {
todo!("port of Platform.c:827")
}
pub fn Platform_dynamicMeters() -> *mut crate::ported::hashtable::Hashtable {
std::ptr::null_mut()
}
pub fn Platform_dynamicMetersDone(_table: *mut crate::ported::hashtable::Hashtable) {}
pub fn Platform_dynamicMeterInit(_meter: &mut crate::ported::meter::Meter) {}
pub fn Platform_dynamicMeterUpdateValues(_meter: &mut crate::ported::meter::Meter) {}
pub fn Platform_dynamicMeterDisplay(
_meter: &crate::ported::meter::Meter,
_out: &mut crate::ported::richstring::RichString,
) {
}
pub fn Platform_dynamicScreens() -> *mut crate::ported::hashtable::Hashtable {
std::ptr::null_mut()
}
pub fn Platform_dynamicScreensDone(_screens: *mut crate::ported::hashtable::Hashtable) {}
pub fn Platform_addDynamicScreenAvailableColumns(
_availableColumns: &mut crate::ported::panel::Panel,
_screen: &str,
) {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn setSwapValues_reads_system_swap() {
let mut m = Meter::empty();
m.values = vec![0.0; 3];
Platform_setSwapValues(&mut m);
assert!(m.total >= 0.0);
assert!(m.values[0] >= 0.0);
assert!(m.values[0] <= m.total);
}
#[test]
fn setMemoryValues_reads_vm_stats_from_host() {
use crate::ported::darwin::darwinmachine::{DarwinMachine_freeCPULoadInfo, Machine_new};
use crate::ported::machine::{ScreenSettings, Settings};
let mut dm = Machine_new(None, 0);
dm.super_.settings = Some(Settings {
showCachedMemory: true,
screens: vec![ScreenSettings::default()],
..Default::default()
});
let mut m = Meter::empty();
m.values = vec![0.0; 6];
m.host = &dm.super_ as *const Machine;
Platform_setMemoryValues(&mut m);
assert!(m.total > 0.0);
assert!(m.values[MEMORY_CLASS_WIRED] > 0.0);
assert!(m.values.iter().all(|&v| v >= 0.0));
DarwinMachine_freeCPULoadInfo(&mut dm.prev_load);
DarwinMachine_freeCPULoadInfo(&mut dm.curr_load);
}
#[test]
fn setCPUValues_computes_percentages_from_load_deltas() {
use crate::ported::darwin::darwinmachine::{DarwinMachine_freeCPULoadInfo, Machine_new};
let mut dm = Machine_new(None, 0);
let mut m = Meter::empty();
m.values = vec![0.0; 10]; m.host = &dm.super_ as *const Machine;
let avg = Platform_setCPUValues(&mut m, 0);
assert!((0.0..=100.0).contains(&avg));
assert!(m.values[CPU_METER_NICE].is_finite());
assert!(m.values[CPU_METER_NORMAL].is_finite());
assert!(m.values[CPU_METER_KERNEL].is_finite());
assert!(m.values[CPU_METER_FREQUENCY].is_nan());
let one = Platform_setCPUValues(&mut m, 1);
assert!((0.0..=100.0).contains(&one));
assert_eq!(m.curItems, 3);
DarwinMachine_freeCPULoadInfo(&mut dm.prev_load);
DarwinMachine_freeCPULoadInfo(&mut dm.curr_load);
}
#[test]
fn gettime_realtime_fills_tv_and_msec_consistently() {
let mut tv: libc::timeval = unsafe { zeroed() };
let mut msec: u64 = 0;
Platform_gettime_realtime(&mut tv, &mut msec);
assert!(msec > 0);
assert!(tv.tv_sec > 0);
assert!(tv.tv_usec >= 0 && (tv.tv_usec as i64) < 1_000_000);
assert_eq!((msec / 1000) as i64, tv.tv_sec as i64);
}
}