Skip to main content

tuwunel_core/utils/sys/
usage.rs

1use nix::sys::resource::Usage;
2#[cfg(unix)]
3use nix::sys::resource::{UsageWho, getrusage};
4
5use crate::{Result, expected};
6
7pub fn virt() -> Result<usize> {
8	Ok(statm_bytes()?
9		.next()
10		.expect("incomplete statm contents"))
11}
12
13pub fn res() -> Result<usize> {
14	Ok(statm_bytes()?
15		.nth(1)
16		.expect("incomplete statm contents"))
17}
18
19pub fn shm() -> Result<usize> {
20	Ok(statm_bytes()?
21		.nth(2)
22		.expect("incomplete statm contents"))
23}
24
25pub fn code() -> Result<usize> {
26	Ok(statm_bytes()?
27		.nth(3)
28		.expect("incomplete statm contents"))
29}
30
31pub fn data() -> Result<usize> {
32	Ok(statm_bytes()?
33		.nth(5)
34		.expect("incomplete statm contents"))
35}
36
37#[inline]
38pub fn statm_bytes() -> Result<impl Iterator<Item = usize>> {
39	let page_size = super::page_size()?;
40
41	Ok(statm()?.map(move |pages| expected!(pages * page_size)))
42}
43
44#[cfg(target_os = "linux")]
45#[inline]
46pub fn statm() -> Result<impl Iterator<Item = usize>> {
47	use std::{fs::File, io::Read, str};
48
49	use crate::{Error, arrayvec::ArrayVec};
50
51	File::open("/proc/self/statm")
52		.map_err(Error::from)
53		.and_then(|mut fp| {
54			let mut buf = [0; 96];
55			let len = fp.read(&mut buf)?;
56			let vals = str::from_utf8(&buf[0..len])
57				.expect("non-utf8 content in statm")
58				.split_ascii_whitespace()
59				.map(|val| {
60					val.parse()
61						.expect("non-integer value in statm contents")
62				})
63				.collect::<ArrayVec<usize, 12>>();
64
65			Ok(vals.into_iter())
66		})
67}
68
69#[cfg(not(target_os = "linux"))]
70#[inline]
71pub fn statm() -> Result<impl Iterator<Item = usize>> { Ok([0, 0, 0, 0, 0, 0].into_iter()) }
72
73#[cfg(unix)]
74pub fn usage() -> Result<Usage> { getrusage(UsageWho::RUSAGE_SELF).map_err(Into::into) }
75
76#[cfg(not(unix))]
77pub fn usage() -> Result<Usage> { Ok(Usage::default()) }
78
79#[cfg(any(
80	target_os = "linux",
81	target_os = "freebsd",
82	target_os = "openbsd"
83))]
84pub fn thread_usage() -> Result<Usage> { getrusage(UsageWho::RUSAGE_THREAD).map_err(Into::into) }
85
86#[cfg(not(any(
87	target_os = "linux",
88	target_os = "freebsd",
89	target_os = "openbsd"
90)))]
91pub fn thread_usage() -> Result<Usage> {
92	unimplemented!("RUSAGE_THREAD available on this platform")
93}