13da5c369Sopenharmony_ci//! Configure the process resource limits. 23da5c369Sopenharmony_ciuse cfg_if::cfg_if; 33da5c369Sopenharmony_ciuse libc::{c_int, c_long, rusage}; 43da5c369Sopenharmony_ci 53da5c369Sopenharmony_ciuse crate::errno::Errno; 63da5c369Sopenharmony_ciuse crate::sys::time::TimeVal; 73da5c369Sopenharmony_ciuse crate::Result; 83da5c369Sopenharmony_cipub use libc::rlim_t; 93da5c369Sopenharmony_cipub use libc::RLIM_INFINITY; 103da5c369Sopenharmony_ciuse std::mem; 113da5c369Sopenharmony_ci 123da5c369Sopenharmony_cicfg_if! { 133da5c369Sopenharmony_ci if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ 143da5c369Sopenharmony_ci use libc::{__rlimit_resource_t, rlimit}; 153da5c369Sopenharmony_ci } else if #[cfg(any( 163da5c369Sopenharmony_ci target_os = "freebsd", 173da5c369Sopenharmony_ci target_os = "openbsd", 183da5c369Sopenharmony_ci target_os = "netbsd", 193da5c369Sopenharmony_ci target_os = "macos", 203da5c369Sopenharmony_ci target_os = "ios", 213da5c369Sopenharmony_ci target_os = "android", 223da5c369Sopenharmony_ci target_os = "dragonfly", 233da5c369Sopenharmony_ci all(target_os = "linux", not(target_env = "gnu")) 243da5c369Sopenharmony_ci ))]{ 253da5c369Sopenharmony_ci use libc::rlimit; 263da5c369Sopenharmony_ci } 273da5c369Sopenharmony_ci} 283da5c369Sopenharmony_ci 293da5c369Sopenharmony_cilibc_enum! { 303da5c369Sopenharmony_ci /// Types of process resources. 313da5c369Sopenharmony_ci /// 323da5c369Sopenharmony_ci /// The Resource enum is platform dependent. Check different platform 333da5c369Sopenharmony_ci /// manuals for more details. Some platform links have been provided for 343da5c369Sopenharmony_ci /// easier reference (non-exhaustive). 353da5c369Sopenharmony_ci /// 363da5c369Sopenharmony_ci /// * [Linux](https://man7.org/linux/man-pages/man2/getrlimit.2.html) 373da5c369Sopenharmony_ci /// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=setrlimit) 383da5c369Sopenharmony_ci /// * [NetBSD](https://man.netbsd.org/setrlimit.2) 393da5c369Sopenharmony_ci 403da5c369Sopenharmony_ci // linux-gnu uses u_int as resource enum, which is implemented in libc as 413da5c369Sopenharmony_ci // well. 423da5c369Sopenharmony_ci // 433da5c369Sopenharmony_ci // https://gcc.gnu.org/legacy-ml/gcc/2015-08/msg00441.html 443da5c369Sopenharmony_ci // https://github.com/rust-lang/libc/blob/master/src/unix/linux_like/linux/gnu/mod.rs 453da5c369Sopenharmony_ci #[cfg_attr(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")), repr(u32))] 463da5c369Sopenharmony_ci #[cfg_attr(any( 473da5c369Sopenharmony_ci target_os = "freebsd", 483da5c369Sopenharmony_ci target_os = "openbsd", 493da5c369Sopenharmony_ci target_os = "netbsd", 503da5c369Sopenharmony_ci target_os = "macos", 513da5c369Sopenharmony_ci target_os = "ios", 523da5c369Sopenharmony_ci target_os = "android", 533da5c369Sopenharmony_ci target_os = "dragonfly", 543da5c369Sopenharmony_ci all(target_os = "linux", not(any(target_env = "gnu", target_env = "uclibc"))) 553da5c369Sopenharmony_ci ), repr(i32))] 563da5c369Sopenharmony_ci #[non_exhaustive] 573da5c369Sopenharmony_ci pub enum Resource { 583da5c369Sopenharmony_ci #[cfg(not(any(target_os = "freebsd", target_os = "netbsd", target_os = "openbsd")))] 593da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 603da5c369Sopenharmony_ci /// The maximum amount (in bytes) of virtual memory the process is 613da5c369Sopenharmony_ci /// allowed to map. 623da5c369Sopenharmony_ci RLIMIT_AS, 633da5c369Sopenharmony_ci /// The largest size (in bytes) core(5) file that may be created. 643da5c369Sopenharmony_ci RLIMIT_CORE, 653da5c369Sopenharmony_ci /// The maximum amount of cpu time (in seconds) to be used by each 663da5c369Sopenharmony_ci /// process. 673da5c369Sopenharmony_ci RLIMIT_CPU, 683da5c369Sopenharmony_ci /// The maximum size (in bytes) of the data segment for a process 693da5c369Sopenharmony_ci RLIMIT_DATA, 703da5c369Sopenharmony_ci /// The largest size (in bytes) file that may be created. 713da5c369Sopenharmony_ci RLIMIT_FSIZE, 723da5c369Sopenharmony_ci /// The maximum number of open files for this process. 733da5c369Sopenharmony_ci RLIMIT_NOFILE, 743da5c369Sopenharmony_ci /// The maximum size (in bytes) of the stack segment for a process. 753da5c369Sopenharmony_ci RLIMIT_STACK, 763da5c369Sopenharmony_ci 773da5c369Sopenharmony_ci #[cfg(target_os = "freebsd")] 783da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 793da5c369Sopenharmony_ci /// The maximum number of kqueues this user id is allowed to create. 803da5c369Sopenharmony_ci RLIMIT_KQUEUES, 813da5c369Sopenharmony_ci 823da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 833da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 843da5c369Sopenharmony_ci /// A limit on the combined number of flock locks and fcntl leases that 853da5c369Sopenharmony_ci /// this process may establish. 863da5c369Sopenharmony_ci RLIMIT_LOCKS, 873da5c369Sopenharmony_ci 883da5c369Sopenharmony_ci #[cfg(any( 893da5c369Sopenharmony_ci target_os = "android", 903da5c369Sopenharmony_ci target_os = "freebsd", 913da5c369Sopenharmony_ci target_os = "openbsd", 923da5c369Sopenharmony_ci target_os = "linux", 933da5c369Sopenharmony_ci target_os = "netbsd" 943da5c369Sopenharmony_ci ))] 953da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 963da5c369Sopenharmony_ci /// The maximum size (in bytes) which a process may lock into memory 973da5c369Sopenharmony_ci /// using the mlock(2) system call. 983da5c369Sopenharmony_ci RLIMIT_MEMLOCK, 993da5c369Sopenharmony_ci 1003da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 1013da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1023da5c369Sopenharmony_ci /// A limit on the number of bytes that can be allocated for POSIX 1033da5c369Sopenharmony_ci /// message queues for the real user ID of the calling process. 1043da5c369Sopenharmony_ci RLIMIT_MSGQUEUE, 1053da5c369Sopenharmony_ci 1063da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 1073da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1083da5c369Sopenharmony_ci /// A ceiling to which the process's nice value can be raised using 1093da5c369Sopenharmony_ci /// setpriority or nice. 1103da5c369Sopenharmony_ci RLIMIT_NICE, 1113da5c369Sopenharmony_ci 1123da5c369Sopenharmony_ci #[cfg(any( 1133da5c369Sopenharmony_ci target_os = "android", 1143da5c369Sopenharmony_ci target_os = "freebsd", 1153da5c369Sopenharmony_ci target_os = "netbsd", 1163da5c369Sopenharmony_ci target_os = "openbsd", 1173da5c369Sopenharmony_ci target_os = "linux", 1183da5c369Sopenharmony_ci ))] 1193da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1203da5c369Sopenharmony_ci /// The maximum number of simultaneous processes for this user id. 1213da5c369Sopenharmony_ci RLIMIT_NPROC, 1223da5c369Sopenharmony_ci 1233da5c369Sopenharmony_ci #[cfg(target_os = "freebsd")] 1243da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1253da5c369Sopenharmony_ci /// The maximum number of pseudo-terminals this user id is allowed to 1263da5c369Sopenharmony_ci /// create. 1273da5c369Sopenharmony_ci RLIMIT_NPTS, 1283da5c369Sopenharmony_ci 1293da5c369Sopenharmony_ci #[cfg(any(target_os = "android", 1303da5c369Sopenharmony_ci target_os = "freebsd", 1313da5c369Sopenharmony_ci target_os = "netbsd", 1323da5c369Sopenharmony_ci target_os = "openbsd", 1333da5c369Sopenharmony_ci target_os = "linux", 1343da5c369Sopenharmony_ci ))] 1353da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1363da5c369Sopenharmony_ci /// When there is memory pressure and swap is available, prioritize 1373da5c369Sopenharmony_ci /// eviction of a process' resident pages beyond this amount (in bytes). 1383da5c369Sopenharmony_ci RLIMIT_RSS, 1393da5c369Sopenharmony_ci 1403da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 1413da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1423da5c369Sopenharmony_ci /// A ceiling on the real-time priority that may be set for this process 1433da5c369Sopenharmony_ci /// using sched_setscheduler and sched_set‐ param. 1443da5c369Sopenharmony_ci RLIMIT_RTPRIO, 1453da5c369Sopenharmony_ci 1463da5c369Sopenharmony_ci #[cfg(any(target_os = "linux"))] 1473da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1483da5c369Sopenharmony_ci /// A limit (in microseconds) on the amount of CPU time that a process 1493da5c369Sopenharmony_ci /// scheduled under a real-time scheduling policy may con‐ sume without 1503da5c369Sopenharmony_ci /// making a blocking system call. 1513da5c369Sopenharmony_ci RLIMIT_RTTIME, 1523da5c369Sopenharmony_ci 1533da5c369Sopenharmony_ci #[cfg(any(target_os = "android", target_os = "linux"))] 1543da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1553da5c369Sopenharmony_ci /// A limit on the number of signals that may be queued for the real 1563da5c369Sopenharmony_ci /// user ID of the calling process. 1573da5c369Sopenharmony_ci RLIMIT_SIGPENDING, 1583da5c369Sopenharmony_ci 1593da5c369Sopenharmony_ci #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] 1603da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1613da5c369Sopenharmony_ci /// The maximum size (in bytes) of socket buffer usage for this user. 1623da5c369Sopenharmony_ci RLIMIT_SBSIZE, 1633da5c369Sopenharmony_ci 1643da5c369Sopenharmony_ci #[cfg(target_os = "freebsd")] 1653da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1663da5c369Sopenharmony_ci /// The maximum size (in bytes) of the swap space that may be reserved 1673da5c369Sopenharmony_ci /// or used by all of this user id's processes. 1683da5c369Sopenharmony_ci RLIMIT_SWAP, 1693da5c369Sopenharmony_ci 1703da5c369Sopenharmony_ci #[cfg(target_os = "freebsd")] 1713da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 1723da5c369Sopenharmony_ci /// An alias for RLIMIT_AS. 1733da5c369Sopenharmony_ci RLIMIT_VMEM, 1743da5c369Sopenharmony_ci } 1753da5c369Sopenharmony_ci} 1763da5c369Sopenharmony_ci 1773da5c369Sopenharmony_ci/// Get the current processes resource limits 1783da5c369Sopenharmony_ci/// 1793da5c369Sopenharmony_ci/// The special value [`RLIM_INFINITY`] indicates that no limit will be 1803da5c369Sopenharmony_ci/// enforced. 1813da5c369Sopenharmony_ci/// 1823da5c369Sopenharmony_ci/// # Parameters 1833da5c369Sopenharmony_ci/// 1843da5c369Sopenharmony_ci/// * `resource`: The [`Resource`] that we want to get the limits of. 1853da5c369Sopenharmony_ci/// 1863da5c369Sopenharmony_ci/// # Examples 1873da5c369Sopenharmony_ci/// 1883da5c369Sopenharmony_ci/// ``` 1893da5c369Sopenharmony_ci/// # use nix::sys::resource::{getrlimit, Resource}; 1903da5c369Sopenharmony_ci/// 1913da5c369Sopenharmony_ci/// let (soft_limit, hard_limit) = getrlimit(Resource::RLIMIT_NOFILE).unwrap(); 1923da5c369Sopenharmony_ci/// println!("current soft_limit: {}", soft_limit); 1933da5c369Sopenharmony_ci/// println!("current hard_limit: {}", hard_limit); 1943da5c369Sopenharmony_ci/// ``` 1953da5c369Sopenharmony_ci/// 1963da5c369Sopenharmony_ci/// # References 1973da5c369Sopenharmony_ci/// 1983da5c369Sopenharmony_ci/// [getrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215) 1993da5c369Sopenharmony_ci/// 2003da5c369Sopenharmony_ci/// [`Resource`]: enum.Resource.html 2013da5c369Sopenharmony_cipub fn getrlimit(resource: Resource) -> Result<(rlim_t, rlim_t)> { 2023da5c369Sopenharmony_ci let mut old_rlim = mem::MaybeUninit::<rlimit>::uninit(); 2033da5c369Sopenharmony_ci 2043da5c369Sopenharmony_ci cfg_if! { 2053da5c369Sopenharmony_ci if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ 2063da5c369Sopenharmony_ci let res = unsafe { libc::getrlimit(resource as __rlimit_resource_t, old_rlim.as_mut_ptr()) }; 2073da5c369Sopenharmony_ci } else { 2083da5c369Sopenharmony_ci let res = unsafe { libc::getrlimit(resource as c_int, old_rlim.as_mut_ptr()) }; 2093da5c369Sopenharmony_ci } 2103da5c369Sopenharmony_ci } 2113da5c369Sopenharmony_ci 2123da5c369Sopenharmony_ci Errno::result(res).map(|_| { 2133da5c369Sopenharmony_ci let rlimit { rlim_cur, rlim_max } = unsafe { old_rlim.assume_init() }; 2143da5c369Sopenharmony_ci (rlim_cur, rlim_max) 2153da5c369Sopenharmony_ci }) 2163da5c369Sopenharmony_ci} 2173da5c369Sopenharmony_ci 2183da5c369Sopenharmony_ci/// Set the current processes resource limits 2193da5c369Sopenharmony_ci/// 2203da5c369Sopenharmony_ci/// # Parameters 2213da5c369Sopenharmony_ci/// 2223da5c369Sopenharmony_ci/// * `resource`: The [`Resource`] that we want to set the limits of. 2233da5c369Sopenharmony_ci/// * `soft_limit`: The value that the kernel enforces for the corresponding 2243da5c369Sopenharmony_ci/// resource. 2253da5c369Sopenharmony_ci/// * `hard_limit`: The ceiling for the soft limit. Must be lower or equal to 2263da5c369Sopenharmony_ci/// the current hard limit for non-root users. 2273da5c369Sopenharmony_ci/// 2283da5c369Sopenharmony_ci/// The special value [`RLIM_INFINITY`] indicates that no limit will be 2293da5c369Sopenharmony_ci/// enforced. 2303da5c369Sopenharmony_ci/// 2313da5c369Sopenharmony_ci/// # Examples 2323da5c369Sopenharmony_ci/// 2333da5c369Sopenharmony_ci/// ``` 2343da5c369Sopenharmony_ci/// # use nix::sys::resource::{setrlimit, Resource}; 2353da5c369Sopenharmony_ci/// 2363da5c369Sopenharmony_ci/// let soft_limit = 512; 2373da5c369Sopenharmony_ci/// let hard_limit = 1024; 2383da5c369Sopenharmony_ci/// setrlimit(Resource::RLIMIT_NOFILE, soft_limit, hard_limit).unwrap(); 2393da5c369Sopenharmony_ci/// ``` 2403da5c369Sopenharmony_ci/// 2413da5c369Sopenharmony_ci/// # References 2423da5c369Sopenharmony_ci/// 2433da5c369Sopenharmony_ci/// [setrlimit(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getrlimit.html#tag_16_215) 2443da5c369Sopenharmony_ci/// 2453da5c369Sopenharmony_ci/// [`Resource`]: enum.Resource.html 2463da5c369Sopenharmony_ci/// 2473da5c369Sopenharmony_ci/// Note: `setrlimit` provides a safe wrapper to libc's `setrlimit`. 2483da5c369Sopenharmony_cipub fn setrlimit( 2493da5c369Sopenharmony_ci resource: Resource, 2503da5c369Sopenharmony_ci soft_limit: rlim_t, 2513da5c369Sopenharmony_ci hard_limit: rlim_t, 2523da5c369Sopenharmony_ci) -> Result<()> { 2533da5c369Sopenharmony_ci let new_rlim = rlimit { 2543da5c369Sopenharmony_ci rlim_cur: soft_limit, 2553da5c369Sopenharmony_ci rlim_max: hard_limit, 2563da5c369Sopenharmony_ci }; 2573da5c369Sopenharmony_ci cfg_if! { 2583da5c369Sopenharmony_ci if #[cfg(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))]{ 2593da5c369Sopenharmony_ci let res = unsafe { libc::setrlimit(resource as __rlimit_resource_t, &new_rlim as *const rlimit) }; 2603da5c369Sopenharmony_ci }else{ 2613da5c369Sopenharmony_ci let res = unsafe { libc::setrlimit(resource as c_int, &new_rlim as *const rlimit) }; 2623da5c369Sopenharmony_ci } 2633da5c369Sopenharmony_ci } 2643da5c369Sopenharmony_ci 2653da5c369Sopenharmony_ci Errno::result(res).map(drop) 2663da5c369Sopenharmony_ci} 2673da5c369Sopenharmony_ci 2683da5c369Sopenharmony_cilibc_enum! { 2693da5c369Sopenharmony_ci /// Whose resource usage should be returned by [`getrusage`]. 2703da5c369Sopenharmony_ci #[repr(i32)] 2713da5c369Sopenharmony_ci #[non_exhaustive] 2723da5c369Sopenharmony_ci pub enum UsageWho { 2733da5c369Sopenharmony_ci /// Resource usage for the current process. 2743da5c369Sopenharmony_ci RUSAGE_SELF, 2753da5c369Sopenharmony_ci 2763da5c369Sopenharmony_ci /// Resource usage for all the children that have terminated and been waited for. 2773da5c369Sopenharmony_ci RUSAGE_CHILDREN, 2783da5c369Sopenharmony_ci 2793da5c369Sopenharmony_ci #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))] 2803da5c369Sopenharmony_ci #[cfg_attr(docsrs, doc(cfg(all())))] 2813da5c369Sopenharmony_ci /// Resource usage for the calling thread. 2823da5c369Sopenharmony_ci RUSAGE_THREAD, 2833da5c369Sopenharmony_ci } 2843da5c369Sopenharmony_ci} 2853da5c369Sopenharmony_ci 2863da5c369Sopenharmony_ci/// Output of `getrusage` with information about resource usage. Some of the fields 2873da5c369Sopenharmony_ci/// may be unused in some platforms, and will be always zeroed out. See their manuals 2883da5c369Sopenharmony_ci/// for details. 2893da5c369Sopenharmony_ci#[repr(transparent)] 2903da5c369Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 2913da5c369Sopenharmony_cipub struct Usage(rusage); 2923da5c369Sopenharmony_ci 2933da5c369Sopenharmony_ciimpl AsRef<rusage> for Usage { 2943da5c369Sopenharmony_ci fn as_ref(&self) -> &rusage { 2953da5c369Sopenharmony_ci &self.0 2963da5c369Sopenharmony_ci } 2973da5c369Sopenharmony_ci} 2983da5c369Sopenharmony_ci 2993da5c369Sopenharmony_ciimpl AsMut<rusage> for Usage { 3003da5c369Sopenharmony_ci fn as_mut(&mut self) -> &mut rusage { 3013da5c369Sopenharmony_ci &mut self.0 3023da5c369Sopenharmony_ci } 3033da5c369Sopenharmony_ci} 3043da5c369Sopenharmony_ci 3053da5c369Sopenharmony_ciimpl Usage { 3063da5c369Sopenharmony_ci /// Total amount of time spent executing in user mode. 3073da5c369Sopenharmony_ci pub fn user_time(&self) -> TimeVal { 3083da5c369Sopenharmony_ci TimeVal::from(self.0.ru_utime) 3093da5c369Sopenharmony_ci } 3103da5c369Sopenharmony_ci 3113da5c369Sopenharmony_ci /// Total amount of time spent executing in kernel mode. 3123da5c369Sopenharmony_ci pub fn system_time(&self) -> TimeVal { 3133da5c369Sopenharmony_ci TimeVal::from(self.0.ru_stime) 3143da5c369Sopenharmony_ci } 3153da5c369Sopenharmony_ci 3163da5c369Sopenharmony_ci /// The resident set size at its peak, in kilobytes. 3173da5c369Sopenharmony_ci pub fn max_rss(&self) -> c_long { 3183da5c369Sopenharmony_ci self.0.ru_maxrss 3193da5c369Sopenharmony_ci } 3203da5c369Sopenharmony_ci 3213da5c369Sopenharmony_ci /// Integral value expressed in kilobytes times ticks of execution indicating 3223da5c369Sopenharmony_ci /// the amount of text memory shared with other processes. 3233da5c369Sopenharmony_ci pub fn shared_integral(&self) -> c_long { 3243da5c369Sopenharmony_ci self.0.ru_ixrss 3253da5c369Sopenharmony_ci } 3263da5c369Sopenharmony_ci 3273da5c369Sopenharmony_ci /// Integral value expressed in kilobytes times ticks of execution indicating 3283da5c369Sopenharmony_ci /// the amount of unshared memory used by data. 3293da5c369Sopenharmony_ci pub fn unshared_data_integral(&self) -> c_long { 3303da5c369Sopenharmony_ci self.0.ru_idrss 3313da5c369Sopenharmony_ci } 3323da5c369Sopenharmony_ci 3333da5c369Sopenharmony_ci /// Integral value expressed in kilobytes times ticks of execution indicating 3343da5c369Sopenharmony_ci /// the amount of unshared memory used for stack space. 3353da5c369Sopenharmony_ci pub fn unshared_stack_integral(&self) -> c_long { 3363da5c369Sopenharmony_ci self.0.ru_isrss 3373da5c369Sopenharmony_ci } 3383da5c369Sopenharmony_ci 3393da5c369Sopenharmony_ci /// Number of page faults that were served without resorting to I/O, with pages 3403da5c369Sopenharmony_ci /// that have been allocated previously by the kernel. 3413da5c369Sopenharmony_ci pub fn minor_page_faults(&self) -> c_long { 3423da5c369Sopenharmony_ci self.0.ru_minflt 3433da5c369Sopenharmony_ci } 3443da5c369Sopenharmony_ci 3453da5c369Sopenharmony_ci /// Number of page faults that were served through I/O (i.e. swap). 3463da5c369Sopenharmony_ci pub fn major_page_faults(&self) -> c_long { 3473da5c369Sopenharmony_ci self.0.ru_majflt 3483da5c369Sopenharmony_ci } 3493da5c369Sopenharmony_ci 3503da5c369Sopenharmony_ci /// Number of times all of the memory was fully swapped out. 3513da5c369Sopenharmony_ci pub fn full_swaps(&self) -> c_long { 3523da5c369Sopenharmony_ci self.0.ru_nswap 3533da5c369Sopenharmony_ci } 3543da5c369Sopenharmony_ci 3553da5c369Sopenharmony_ci /// Number of times a read was done from a block device. 3563da5c369Sopenharmony_ci pub fn block_reads(&self) -> c_long { 3573da5c369Sopenharmony_ci self.0.ru_inblock 3583da5c369Sopenharmony_ci } 3593da5c369Sopenharmony_ci 3603da5c369Sopenharmony_ci /// Number of times a write was done to a block device. 3613da5c369Sopenharmony_ci pub fn block_writes(&self) -> c_long { 3623da5c369Sopenharmony_ci self.0.ru_oublock 3633da5c369Sopenharmony_ci } 3643da5c369Sopenharmony_ci 3653da5c369Sopenharmony_ci /// Number of IPC messages sent. 3663da5c369Sopenharmony_ci pub fn ipc_sends(&self) -> c_long { 3673da5c369Sopenharmony_ci self.0.ru_msgsnd 3683da5c369Sopenharmony_ci } 3693da5c369Sopenharmony_ci 3703da5c369Sopenharmony_ci /// Number of IPC messages received. 3713da5c369Sopenharmony_ci pub fn ipc_receives(&self) -> c_long { 3723da5c369Sopenharmony_ci self.0.ru_msgrcv 3733da5c369Sopenharmony_ci } 3743da5c369Sopenharmony_ci 3753da5c369Sopenharmony_ci /// Number of signals received. 3763da5c369Sopenharmony_ci pub fn signals(&self) -> c_long { 3773da5c369Sopenharmony_ci self.0.ru_nsignals 3783da5c369Sopenharmony_ci } 3793da5c369Sopenharmony_ci 3803da5c369Sopenharmony_ci /// Number of times a context switch was voluntarily invoked. 3813da5c369Sopenharmony_ci pub fn voluntary_context_switches(&self) -> c_long { 3823da5c369Sopenharmony_ci self.0.ru_nvcsw 3833da5c369Sopenharmony_ci } 3843da5c369Sopenharmony_ci 3853da5c369Sopenharmony_ci /// Number of times a context switch was imposed by the kernel (usually due to 3863da5c369Sopenharmony_ci /// time slice expiring or preemption by a higher priority process). 3873da5c369Sopenharmony_ci pub fn involuntary_context_switches(&self) -> c_long { 3883da5c369Sopenharmony_ci self.0.ru_nivcsw 3893da5c369Sopenharmony_ci } 3903da5c369Sopenharmony_ci} 3913da5c369Sopenharmony_ci 3923da5c369Sopenharmony_ci/// Get usage information for a process, its children or the current thread 3933da5c369Sopenharmony_ci/// 3943da5c369Sopenharmony_ci/// Real time information can be obtained for either the current process or (in some 3953da5c369Sopenharmony_ci/// systems) thread, but information about children processes is only provided for 3963da5c369Sopenharmony_ci/// those that have terminated and been waited for (see [`super::wait::wait`]). 3973da5c369Sopenharmony_ci/// 3983da5c369Sopenharmony_ci/// Some information may be missing depending on the platform, and the way information 3993da5c369Sopenharmony_ci/// is provided for children may also vary. Check the manuals for details. 4003da5c369Sopenharmony_ci/// 4013da5c369Sopenharmony_ci/// # References 4023da5c369Sopenharmony_ci/// 4033da5c369Sopenharmony_ci/// * [getrusage(2)](https://pubs.opengroup.org/onlinepubs/009696699/functions/getrusage.html) 4043da5c369Sopenharmony_ci/// * [Linux](https://man7.org/linux/man-pages/man2/getrusage.2.html) 4053da5c369Sopenharmony_ci/// * [FreeBSD](https://www.freebsd.org/cgi/man.cgi?query=getrusage) 4063da5c369Sopenharmony_ci/// * [NetBSD](https://man.netbsd.org/getrusage.2) 4073da5c369Sopenharmony_ci/// * [MacOS](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/getrusage.2.html) 4083da5c369Sopenharmony_ci/// 4093da5c369Sopenharmony_ci/// [`UsageWho`]: enum.UsageWho.html 4103da5c369Sopenharmony_ci/// 4113da5c369Sopenharmony_ci/// Note: `getrusage` provides a safe wrapper to libc's [`libc::getrusage`]. 4123da5c369Sopenharmony_cipub fn getrusage(who: UsageWho) -> Result<Usage> { 4133da5c369Sopenharmony_ci unsafe { 4143da5c369Sopenharmony_ci let mut rusage = mem::MaybeUninit::<rusage>::uninit(); 4153da5c369Sopenharmony_ci let res = libc::getrusage(who as c_int, rusage.as_mut_ptr()); 4163da5c369Sopenharmony_ci Errno::result(res).map(|_| Usage(rusage.assume_init())) 4173da5c369Sopenharmony_ci } 4183da5c369Sopenharmony_ci} 4193da5c369Sopenharmony_ci 4203da5c369Sopenharmony_ci#[cfg(test)] 4213da5c369Sopenharmony_cimod test { 4223da5c369Sopenharmony_ci use super::{getrusage, UsageWho}; 4233da5c369Sopenharmony_ci 4243da5c369Sopenharmony_ci #[test] 4253da5c369Sopenharmony_ci pub fn test_self_cpu_time() { 4263da5c369Sopenharmony_ci // Make sure some CPU time is used. 4273da5c369Sopenharmony_ci let mut numbers: Vec<i32> = (1..1_000_000).collect(); 4283da5c369Sopenharmony_ci numbers.iter_mut().for_each(|item| *item *= 2); 4293da5c369Sopenharmony_ci 4303da5c369Sopenharmony_ci // FIXME: this is here to help ensure the compiler does not optimize the whole 4313da5c369Sopenharmony_ci // thing away. Replace the assert with test::black_box once stabilized. 4323da5c369Sopenharmony_ci assert_eq!(numbers[100..200].iter().sum::<i32>(), 30_100); 4333da5c369Sopenharmony_ci 4343da5c369Sopenharmony_ci let usage = getrusage(UsageWho::RUSAGE_SELF) 4353da5c369Sopenharmony_ci .expect("Failed to call getrusage for SELF"); 4363da5c369Sopenharmony_ci let rusage = usage.as_ref(); 4373da5c369Sopenharmony_ci 4383da5c369Sopenharmony_ci let user = usage.user_time(); 4393da5c369Sopenharmony_ci assert!(user.tv_sec() > 0 || user.tv_usec() > 0); 4403da5c369Sopenharmony_ci assert_eq!(user.tv_sec(), rusage.ru_utime.tv_sec); 4413da5c369Sopenharmony_ci assert_eq!(user.tv_usec(), rusage.ru_utime.tv_usec); 4423da5c369Sopenharmony_ci } 4433da5c369Sopenharmony_ci} 444