cgroups_rs/systemd/
cpuset.rs1use bit_vec::BitVec;
7
8use crate::systemd::error::{Error, Result};
9use crate::systemd::{ALLOWED_CPUS, ALLOWED_MEMORY_NODES, CPUSET_SYSTEMD_VERSION};
10
11const BYTE_IN_BITS: usize = 8;
12
13pub fn cpus(cpus: &str, systemd_version: usize) -> Result<(&'static str, Vec<u8>)> {
15 if systemd_version < CPUSET_SYSTEMD_VERSION {
16 return Err(Error::ObsoleteSystemd);
17 }
18
19 let mask = convert_list_to_mask(cpus)?;
20
21 Ok((ALLOWED_CPUS, mask))
22}
23
24pub fn mems(mems: &str, systemd_version: usize) -> Result<(&'static str, Vec<u8>)> {
26 if systemd_version < CPUSET_SYSTEMD_VERSION {
27 return Err(Error::ObsoleteSystemd);
28 }
29
30 let mask = convert_list_to_mask(mems)?;
31
32 Ok((ALLOWED_MEMORY_NODES, mask))
33}
34
35fn convert_list_to_mask(list: &str) -> Result<Vec<u8>> {
45 let mut bit_vec = BitVec::from_elem(8, false);
46
47 let local_idx =
48 |index: usize| -> usize { index / BYTE_IN_BITS * BYTE_IN_BITS + 7 - index % BYTE_IN_BITS };
49
50 for part1 in list.split(',') {
51 let range: Vec<&str> = part1.split('-').collect();
52 match range.len() {
53 1 => {
55 let left: usize = range[0].parse().map_err(|_| Error::InvalidArgument)?;
56
57 while left >= bit_vec.len() {
58 bit_vec.grow(BYTE_IN_BITS, false);
59 }
60 bit_vec.set(local_idx(left), true);
61 }
62 2 => {
64 let left: usize = range[0].parse().map_err(|_| Error::InvalidArgument)?;
65 let right: usize = range[1].parse().map_err(|_| Error::InvalidArgument)?;
66
67 while right >= bit_vec.len() {
68 bit_vec.grow(BYTE_IN_BITS, false);
69 }
70
71 for index in left..=right {
72 bit_vec.set(local_idx(index), true);
73 }
74 }
75 _ => {
76 return Err(Error::InvalidArgument);
77 }
78 }
79 }
80
81 let mut mask = bit_vec.to_bytes();
82 mask.reverse();
83
84 Ok(mask)
85}
86
87#[cfg(test)]
88mod tests {
89 use crate::systemd::cpuset::convert_list_to_mask;
90
91 #[test]
92 fn test_convert_list_to_mask() {
93 let mask = convert_list_to_mask("2-4").unwrap();
94 assert_eq!(vec![0b00011100_u8], mask);
95
96 let mask = convert_list_to_mask("1,7").unwrap();
97 assert_eq!(vec![0b10000010_u8], mask);
98
99 let mask = convert_list_to_mask("0-4,9").unwrap();
100 assert_eq!(vec![0b00000010_u8, 0b00011111_u8], mask);
101
102 assert!(convert_list_to_mask("1-3-4").is_err());
103
104 assert!(convert_list_to_mask("1-3,,").is_err());
105 }
106}