darwin_libproc/
pid_rusage.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
use std::io;
use std::mem;

pub use darwin_libproc_sys::{
    rusage_info_v0, rusage_info_v1, rusage_info_v2, rusage_info_v3,
    rusage_info_v4,
};

mod private {
    pub trait Sealed {}
    impl Sealed for darwin_libproc_sys::rusage_info_v0 {}
    impl Sealed for darwin_libproc_sys::rusage_info_v1 {}
    impl Sealed for darwin_libproc_sys::rusage_info_v2 {}
    impl Sealed for darwin_libproc_sys::rusage_info_v3 {}
    impl Sealed for darwin_libproc_sys::rusage_info_v4 {}
}

/// `proc_pid_rusage` can return different versioned `rusage_info_v*` structs.
///
/// This sealed trait implemented for all possible variants
/// and used by [`pid_rusage`]
pub trait RusageFlavor: private::Sealed {
    #[doc(hidden)]
    fn flavor() -> libc::c_int;
}

impl RusageFlavor for rusage_info_v0 {
    fn flavor() -> libc::c_int {
        darwin_libproc_sys::RUSAGE_INFO_V0
    }
}

impl RusageFlavor for rusage_info_v1 {
    fn flavor() -> libc::c_int {
        darwin_libproc_sys::RUSAGE_INFO_V1
    }
}

impl RusageFlavor for rusage_info_v2 {
    fn flavor() -> libc::c_int {
        darwin_libproc_sys::RUSAGE_INFO_V2
    }
}

impl RusageFlavor for rusage_info_v3 {
    fn flavor() -> libc::c_int {
        darwin_libproc_sys::RUSAGE_INFO_V3
    }
}

impl RusageFlavor for rusage_info_v4 {
    fn flavor() -> libc::c_int {
        darwin_libproc_sys::RUSAGE_INFO_V4
    }
}

/// Return resource usage information for the given pid, which can be a live process or a zombie.
pub fn pid_rusage<T: RusageFlavor>(pid: libc::pid_t) -> io::Result<T> {
    let mut rusage = mem::MaybeUninit::<T>::uninit();
    let result = unsafe {
        darwin_libproc_sys::proc_pid_rusage(
            pid,
            T::flavor(),
            rusage.as_mut_ptr() as *mut _,
        )
    };

    if result < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(unsafe { rusage.assume_init() })
    }
}