diff options
Diffstat (limited to 'runtime/ops/os/sys_info.rs')
-rw-r--r-- | runtime/ops/os/sys_info.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/runtime/ops/os/sys_info.rs b/runtime/ops/os/sys_info.rs index 40de7cc4b..ecb40b9a0 100644 --- a/runtime/ops/os/sys_info.rs +++ b/runtime/ops/os/sys_info.rs @@ -300,3 +300,65 @@ pub fn mem_info() -> Option<MemInfo> { Some(mem_info) } + +pub fn os_uptime() -> u64 { + #[cfg(target_os = "linux")] + { + let mut info = std::mem::MaybeUninit::uninit(); + // SAFETY: `info` is a valid pointer to a `libc::sysinfo` struct. + let res = unsafe { libc::sysinfo(info.as_mut_ptr()) }; + if res == 0 { + // SAFETY: `sysinfo` initializes the struct. + let info = unsafe { info.assume_init() }; + return info.uptime as u64; + } + } + + #[cfg(any( + target_vendor = "apple", + target_os = "freebsd", + target_os = "openbsd" + ))] + { + use std::mem; + use std::time::Duration; + use std::time::SystemTime; + let mut request = [libc::CTL_KERN, libc::KERN_BOOTTIME]; + // SAFETY: `boottime` is only accessed if sysctl() succeeds + // and agrees with the `size` set by sysctl(). + let mut boottime: libc::timeval = unsafe { mem::zeroed() }; + let mut size: libc::size_t = mem::size_of_val(&boottime) as libc::size_t; + // SAFETY: `sysctl` is thread-safe. + let res = unsafe { + libc::sysctl( + &mut request[0], + 2, + &mut boottime as *mut libc::timeval as *mut libc::c_void, + &mut size, + std::ptr::null_mut(), + 0, + ) + }; + if res == 0 { + return SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .map(|d| { + (d - Duration::new( + boottime.tv_sec as u64, + boottime.tv_usec as u32 * 1000, + )) + .as_secs() + }) + .unwrap_or_default(); + } + } + + #[cfg(target_family = "windows")] + unsafe { + // Windows is the only one that returns `uptime` in milisecond precision, + // so we need to get the seconds out of it to be in sync with other envs. + return unsafe { winapi::um::sysinfoapi::GetTickCount64() as u64 / 1000 }; + } + + 0 +} |