diff --git a/runtime/ops/os/mod.rs b/runtime/ops/os/mod.rs index 043dec7000..bbadee993a 100644 --- a/runtime/ops/os/mod.rs +++ b/runtime/ops/os/mod.rs @@ -380,6 +380,53 @@ fn rss() -> usize { task_info.resident_size as usize } +#[cfg(target_os = "openbsd")] +fn rss() -> usize { + // Uses OpenBSD's KERN_PROC_PID sysctl(2) + // to retrieve information about the current + // process, part of which is the RSS (p_vm_rssize) + + // SAFETY: libc call (get PID of own process) + let pid = unsafe { libc::getpid() }; + // SAFETY: libc call (get system page size) + let pagesize = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize; + // KERN_PROC_PID returns a struct libc::kinfo_proc + let mut kinfoproc = std::mem::MaybeUninit::::uninit(); + let mut size = std::mem::size_of_val(&kinfoproc) as libc::size_t; + let mut mib = [ + libc::CTL_KERN, + libc::KERN_PROC, + libc::KERN_PROC_PID, + pid, + // mib is an array of integers, size is of type size_t + // conversion is safe, because the size of a libc::kinfo_proc + // structure will not exceed i32::MAX + size.try_into().unwrap(), + 1, + ]; + // SAFETY: libc call, mib has been statically initialized, + // kinfoproc is a valid pointer to a libc::kinfo_proc struct + let res = unsafe { + libc::sysctl( + mib.as_mut_ptr(), + mib.len() as _, + kinfoproc.as_mut_ptr() as *mut libc::c_void, + &mut size, + std::ptr::null_mut(), + 0, + ) + }; + + if res == 0 { + // SAFETY: sysctl returns 0 on success and kinfoproc is initialized + // p_vm_rssize contains size in pages -> multiply with pagesize to + // get size in bytes. + pagesize * unsafe { (*kinfoproc.as_mut_ptr()).p_vm_rssize as usize } + } else { + 0 + } +} + #[cfg(windows)] fn rss() -> usize { use winapi::shared::minwindef::DWORD;