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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/// Set a thread's CPU affinity mask.
///
/// # Example
///
/// ```
/// use core::mem::size_of;
///
/// const SET_BITS: usize = 16;
/// #[repr(C)]
/// #[derive(Debug, Clone, Copy, PartialEq)]
/// struct CPUSet {
/// pub bits: [usize; SET_BITS],
/// }
///
/// impl Default for CPUSet {
/// fn default() -> Self {
/// CPUSet {
/// bits: [0; SET_BITS],
/// }
/// }
/// }
///
/// impl CPUSet {
/// #[inline]
/// pub const fn size() -> usize {
/// SET_BITS * size_of::<usize>()
/// }
///
/// #[inline]
/// pub const fn bits_size() -> usize {
/// CPUSet::size() * 8
/// }
///
/// pub fn set(&mut self, pos: usize) -> Result<(), nc::Errno> {
/// if pos >= CPUSet::bits_size() {
/// return Err(nc::EINVAL);
/// }
/// let bit_pos = pos / 8 / size_of::<usize>();
/// self.bits[bit_pos] |= 1 << (pos % (8 * size_of::<usize>()));
/// Ok(())
/// }
///
/// pub fn clear(&mut self, pos: usize) -> Result<(), nc::Errno> {
/// if pos >= CPUSet::bits_size() {
/// return Err(nc::EINVAL);
/// }
/// let bit_pos = pos / 8 / size_of::<usize>();
/// self.bits[bit_pos] &= !(1 << (pos % (8 * size_of::<usize>())));
/// Ok(())
/// }
///
/// pub fn is_set(&self, pos: usize) -> Result<bool, nc::Errno> {
/// if pos >= CPUSet::bits_size() {
/// return Err(nc::EINVAL);
/// }
/// let bit_pos = pos / 8 / size_of::<usize>();
/// let ret = self.bits[bit_pos] & (1 << (pos % (8 * size_of::<usize>())));
///
/// Ok(ret != 0)
/// }
///
/// pub fn as_ptr(&self) -> &[usize] {
/// &self.bits
/// }
///
/// pub fn as_mut_ptr(&mut self) -> &mut [usize] {
/// &mut self.bits
/// }
/// }
///
/// fn main() {
/// let mut set = CPUSet::default();
/// assert!(set.set(1).is_ok());
/// println!("set(1): {:?}", set.is_set(1));
/// assert!(set.set(2).is_ok());
/// assert!(set.clear(2).is_ok());
/// println!("set(2): {:?}", set.is_set(2));
///
/// let ret = unsafe { nc::sched_setaffinity(0, CPUSet::size(), set.as_ptr()) };
/// assert!(ret.is_ok());
///
/// let mut set2 = CPUSet::default();
/// let ret = unsafe { nc::sched_getaffinity(0, CPUSet::size(), set2.as_mut_ptr()) };
/// assert!(ret.is_ok());
/// assert_eq!(set, set2);
/// }
/// ```
pub unsafe fn sched_setaffinity(pid: pid_t, len: usize, user_mask: &[usize]) -> Result<(), Errno> {
let pid = pid as usize;
let user_mask_ptr = user_mask.as_ptr() as usize;
syscall3(SYS_SCHED_SETAFFINITY, pid, len, user_mask_ptr).map(drop)
}