1b8a62b91Sopenharmony_ciuse crate::process::Pid;
2b8a62b91Sopenharmony_ciuse crate::{backend, io};
3b8a62b91Sopenharmony_ci
4b8a62b91Sopenharmony_ci/// `CpuSet` represents a bit-mask of CPUs.
5b8a62b91Sopenharmony_ci///
6b8a62b91Sopenharmony_ci/// `CpuSet`s are used by [`sched_setaffinity`] and [`sched_getaffinity`], for
7b8a62b91Sopenharmony_ci/// example.
8b8a62b91Sopenharmony_ci///
9b8a62b91Sopenharmony_ci/// # References
10b8a62b91Sopenharmony_ci///  - [Linux]
11b8a62b91Sopenharmony_ci///
12b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man3/CPU_SET.3.html
13b8a62b91Sopenharmony_ci/// [`sched_setaffinity`]: crate::process::sched_setaffinity
14b8a62b91Sopenharmony_ci/// [`sched_getaffinity`]: crate::process::sched_getaffinity
15b8a62b91Sopenharmony_ci#[repr(C)]
16b8a62b91Sopenharmony_ci#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
17b8a62b91Sopenharmony_cipub struct CpuSet {
18b8a62b91Sopenharmony_ci    cpu_set: backend::process::types::RawCpuSet,
19b8a62b91Sopenharmony_ci}
20b8a62b91Sopenharmony_ci
21b8a62b91Sopenharmony_ciimpl CpuSet {
22b8a62b91Sopenharmony_ci    /// The maximum number of CPU in `CpuSet`.
23b8a62b91Sopenharmony_ci    pub const MAX_CPU: usize = backend::process::types::CPU_SETSIZE;
24b8a62b91Sopenharmony_ci
25b8a62b91Sopenharmony_ci    /// Create a new and empty `CpuSet`.
26b8a62b91Sopenharmony_ci    #[inline]
27b8a62b91Sopenharmony_ci    pub fn new() -> Self {
28b8a62b91Sopenharmony_ci        Self {
29b8a62b91Sopenharmony_ci            cpu_set: backend::process::types::raw_cpu_set_new(),
30b8a62b91Sopenharmony_ci        }
31b8a62b91Sopenharmony_ci    }
32b8a62b91Sopenharmony_ci
33b8a62b91Sopenharmony_ci    /// Test to see if a CPU is in the `CpuSet`.
34b8a62b91Sopenharmony_ci    ///
35b8a62b91Sopenharmony_ci    /// `field` is the CPU id to test.
36b8a62b91Sopenharmony_ci    #[inline]
37b8a62b91Sopenharmony_ci    pub fn is_set(&self, field: usize) -> bool {
38b8a62b91Sopenharmony_ci        backend::process::cpu_set::CPU_ISSET(field, &self.cpu_set)
39b8a62b91Sopenharmony_ci    }
40b8a62b91Sopenharmony_ci
41b8a62b91Sopenharmony_ci    /// Add a CPU to `CpuSet`.
42b8a62b91Sopenharmony_ci    ///
43b8a62b91Sopenharmony_ci    /// `field` is the CPU id to add.
44b8a62b91Sopenharmony_ci    #[inline]
45b8a62b91Sopenharmony_ci    pub fn set(&mut self, field: usize) {
46b8a62b91Sopenharmony_ci        backend::process::cpu_set::CPU_SET(field, &mut self.cpu_set)
47b8a62b91Sopenharmony_ci    }
48b8a62b91Sopenharmony_ci
49b8a62b91Sopenharmony_ci    /// Remove a CPU from `CpuSet`.
50b8a62b91Sopenharmony_ci    ///
51b8a62b91Sopenharmony_ci    /// `field` is the CPU id to remove.
52b8a62b91Sopenharmony_ci    #[inline]
53b8a62b91Sopenharmony_ci    pub fn unset(&mut self, field: usize) {
54b8a62b91Sopenharmony_ci        backend::process::cpu_set::CPU_CLR(field, &mut self.cpu_set)
55b8a62b91Sopenharmony_ci    }
56b8a62b91Sopenharmony_ci
57b8a62b91Sopenharmony_ci    /// Count the number of CPUs set in the `CpuSet`.
58b8a62b91Sopenharmony_ci    #[cfg(any(target_os = "android", target_os = "linux"))]
59b8a62b91Sopenharmony_ci    #[inline]
60b8a62b91Sopenharmony_ci    pub fn count(&self) -> u32 {
61b8a62b91Sopenharmony_ci        backend::process::cpu_set::CPU_COUNT(&self.cpu_set)
62b8a62b91Sopenharmony_ci    }
63b8a62b91Sopenharmony_ci
64b8a62b91Sopenharmony_ci    /// Zeroes the `CpuSet`.
65b8a62b91Sopenharmony_ci    #[inline]
66b8a62b91Sopenharmony_ci    pub fn clear(&mut self) {
67b8a62b91Sopenharmony_ci        backend::process::cpu_set::CPU_ZERO(&mut self.cpu_set)
68b8a62b91Sopenharmony_ci    }
69b8a62b91Sopenharmony_ci}
70b8a62b91Sopenharmony_ci
71b8a62b91Sopenharmony_ciimpl Default for CpuSet {
72b8a62b91Sopenharmony_ci    #[inline]
73b8a62b91Sopenharmony_ci    fn default() -> Self {
74b8a62b91Sopenharmony_ci        Self::new()
75b8a62b91Sopenharmony_ci    }
76b8a62b91Sopenharmony_ci}
77b8a62b91Sopenharmony_ci
78b8a62b91Sopenharmony_ci/// `sched_setaffinity(pid, cpuset)`—Set a thread's CPU affinity mask.
79b8a62b91Sopenharmony_ci///
80b8a62b91Sopenharmony_ci/// `pid` is the thread ID to update. If pid is `None`, then the current thread
81b8a62b91Sopenharmony_ci/// is updated.
82b8a62b91Sopenharmony_ci///
83b8a62b91Sopenharmony_ci/// The `CpuSet` argument specifies the set of CPUs on which the thread will
84b8a62b91Sopenharmony_ci/// be eligible to run.
85b8a62b91Sopenharmony_ci///
86b8a62b91Sopenharmony_ci/// # References
87b8a62b91Sopenharmony_ci///  - [Linux]
88b8a62b91Sopenharmony_ci///
89b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html
90b8a62b91Sopenharmony_ci#[inline]
91b8a62b91Sopenharmony_cipub fn sched_setaffinity(pid: Option<Pid>, cpuset: &CpuSet) -> io::Result<()> {
92b8a62b91Sopenharmony_ci    backend::process::syscalls::sched_setaffinity(pid, &cpuset.cpu_set)
93b8a62b91Sopenharmony_ci}
94b8a62b91Sopenharmony_ci
95b8a62b91Sopenharmony_ci/// `sched_getaffinity(pid)`—Get a thread's CPU affinity mask.
96b8a62b91Sopenharmony_ci///
97b8a62b91Sopenharmony_ci/// `pid` is the thread ID to check. If pid is `None`, then the current thread
98b8a62b91Sopenharmony_ci/// is checked.
99b8a62b91Sopenharmony_ci///
100b8a62b91Sopenharmony_ci/// Returns the set of CPUs on which the thread is eligible to run.
101b8a62b91Sopenharmony_ci///
102b8a62b91Sopenharmony_ci/// # References
103b8a62b91Sopenharmony_ci///  - [Linux]
104b8a62b91Sopenharmony_ci///
105b8a62b91Sopenharmony_ci/// [Linux]: https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html
106b8a62b91Sopenharmony_ci#[inline]
107b8a62b91Sopenharmony_cipub fn sched_getaffinity(pid: Option<Pid>) -> io::Result<CpuSet> {
108b8a62b91Sopenharmony_ci    let mut cpuset = CpuSet::new();
109b8a62b91Sopenharmony_ci    backend::process::syscalls::sched_getaffinity(pid, &mut cpuset.cpu_set).and(Ok(cpuset))
110b8a62b91Sopenharmony_ci}
111