linux_taskstats/
model.rs

1use crate::c_headers;
2use crate::taskstats;
3use std::mem;
4use std::time::Duration;
5
6// https://stackoverflow.com/questions/53619695/calculating-maximum-value-of-a-set-of-constant-expressions-at-compile-time
7const fn const_max(a: usize, b: usize) -> usize {
8    [a, b][(a < b) as usize]
9}
10
11pub const TASKSTATS_SIZE: usize = const_max(
12    mem::size_of::<taskstats>(),
13    mem::size_of::<c_headers::taskstats>(),
14);
15
16/// The taskstats representation for a task.
17/// This struct remaps commonly used `struct taskstats` fields for primarily:
18/// * Access values with rust's primitive types
19/// * Better structured organization of group of fields
20/// * Support serialization
21///
22/// There are more (but may not much interested) fields in the original
23/// `struct taskstats` and they are accessible through obtaining the original
24/// struct by `TaskStats#inner()`.
25#[derive(Clone, Copy, Debug)]
26pub struct TaskStats {
27    pub(crate) inner_buf: [u8; TASKSTATS_SIZE],
28    /// The target task ID
29    pub tid: u32,
30    /// Staticstics related to CPU time
31    pub cpu: Cpu,
32    /// Statistics related to memory, vm
33    pub memory: Memory,
34    /// Staticstics related to I/O at syscall surface
35    pub io: Io,
36    /// Statistics related to I/O at block device level
37    pub blkio: BlkIo,
38    /// Statistics related to context switches
39    pub ctx_switches: ContextSwitches,
40    /// Statistics related to scheduling delay (delay accounting)
41    pub delays: Delays,
42}
43
44/// Staticstics related to CPU time
45#[derive(Debug, Clone, Copy)]
46pub struct Cpu {
47    /// User CPU time
48    pub utime_total: Duration,
49    /// System CPU time
50    pub stime_total: Duration,
51    /// Wall-clock running time
52    pub real_time_total: Duration,
53    /// Virtual running time
54    pub virtual_time_total: Duration,
55}
56
57/// Statistics related to memory, vm
58#[derive(Debug, Clone, Copy)]
59pub struct Memory {
60    /// Accumulated RSS usage in duration of a task, in MBytes-usecs
61    pub rss_total: u64,
62    /// Accumulated virtual memory usage in duration of a task
63    pub virt_total: u64,
64    /// Minor faults count
65    pub minor_faults: u64,
66    /// Major faults count
67    pub major_faults: u64,
68}
69
70/// Staticstics related to I/O at syscall surface
71#[derive(Debug, Clone, Copy)]
72pub struct Io {
73    /// Bytes read
74    pub read_bytes: u64,
75    /// Bytes written
76    pub write_bytes: u64,
77    /// Number of read syscalls
78    pub read_syscalls: u64,
79    /// Number of write syscalls
80    pub write_syscalls: u64,
81}
82
83/// Statistics related to I/O at block device level
84#[derive(Debug, Clone, Copy)]
85pub struct BlkIo {
86    /// Bytes read
87    pub read_bytes: u64,
88    /// Bytes written
89    pub write_bytes: u64,
90    /// Bytes of cancelled writes
91    pub cancelled_write_bytes: u64,
92}
93
94/// Statistics related to context switches
95#[derive(Debug, Clone, Copy)]
96pub struct ContextSwitches {
97    /// Count of voluntary context switches
98    pub voluntary: u64,
99    /// Count of non-voluntary context switches
100    pub non_voluntary: u64,
101}
102
103/// Statistics related to scheduling delay (delay accounting)
104#[derive(Debug, Clone, Copy)]
105pub struct Delays {
106    /// Delay waiting for cpu, while runnable
107    pub cpu: DelayStat,
108    /// Delay waiting for synchronous block I/O to complete
109    pub blkio: DelayStat,
110    /// Delay waiting for page fault I/O (swap in only)
111    pub swapin: DelayStat,
112    /// Delay waiting for memory reclaim
113    pub freepages: DelayStat,
114}
115
116#[derive(Debug, Clone, Copy)]
117pub struct DelayStat {
118    /// Number of delay values recorded
119    pub count: u64,
120    /// Cumulative total delay
121    pub delay_total: Duration,
122}
123
124impl From<&[u8]> for TaskStats {
125    fn from(buf: &[u8]) -> Self {
126        let mut inner_buf = [0u8; TASKSTATS_SIZE];
127        inner_buf.copy_from_slice(&buf[..TASKSTATS_SIZE]);
128        let ts = unsafe { &*(inner_buf.as_ptr() as *const _ as *const taskstats) };
129        TaskStats {
130            tid: ts.ac_pid,
131            cpu: Cpu {
132                utime_total: Duration::from_micros(ts.ac_utime),
133                stime_total: Duration::from_micros(ts.ac_stime),
134                real_time_total: Duration::from_nanos(ts.cpu_run_real_total),
135                virtual_time_total: Duration::from_nanos(ts.cpu_run_virtual_total),
136            },
137            memory: Memory {
138                rss_total: ts.coremem,
139                virt_total: ts.virtmem,
140                minor_faults: ts.ac_minflt,
141                major_faults: ts.ac_majflt,
142            },
143            io: Io {
144                read_bytes: ts.read_char,
145                write_bytes: ts.write_char,
146                read_syscalls: ts.read_syscalls,
147                write_syscalls: ts.write_syscalls,
148            },
149            blkio: BlkIo {
150                read_bytes: ts.read_bytes,
151                write_bytes: ts.write_bytes,
152                cancelled_write_bytes: ts.cancelled_write_bytes,
153            },
154            ctx_switches: ContextSwitches {
155                voluntary: ts.nvcsw,
156                non_voluntary: ts.nivcsw,
157            },
158            delays: Delays {
159                cpu: DelayStat {
160                    count: ts.cpu_count,
161                    delay_total: Duration::from_nanos(ts.cpu_delay_total),
162                },
163                blkio: DelayStat {
164                    count: ts.blkio_count,
165                    delay_total: Duration::from_nanos(ts.blkio_delay_total),
166                },
167                swapin: DelayStat {
168                    count: ts.swapin_count,
169                    delay_total: Duration::from_nanos(ts.swapin_delay_total),
170                },
171                freepages: DelayStat {
172                    count: ts.freepages_count,
173                    delay_total: Duration::from_nanos(ts.freepages_delay_total),
174                },
175            },
176            inner_buf,
177        }
178    }
179}
180
181impl TaskStats {
182    /// Return inner representation of taskstats.
183    ///
184    /// The returned value is an instance of `struct taskstats` that was
185    /// received from kernel.
186    /// `TaskStats` remaps most of its fields into rust-friendly types and
187    /// structure, so this inner object should be referred only when the user
188    /// wants to access more information than available in remapped fields.
189    pub fn inner(&self) -> &taskstats {
190        unsafe { &*(self.inner_buf.as_ptr() as *const _ as *const taskstats) }
191    }
192}