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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
use crate::process::Pid;
use crate::{backend, io};
use core::{fmt, hash};
/// `CpuSet` represents a bit-mask of CPUs.
///
/// `CpuSet`s are used by [`sched_setaffinity`] and [`sched_getaffinity`], for
/// example.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man3/CPU_SET.3.html
/// [`sched_setaffinity`]: crate::process::sched_setaffinity
/// [`sched_getaffinity`]: crate::process::sched_getaffinity
#[repr(C)]
#[derive(Clone, Copy)]
pub struct CpuSet {
cpu_set: backend::process::types::RawCpuSet,
}
impl CpuSet {
/// The maximum number of CPU in `CpuSet`.
pub const MAX_CPU: usize = backend::process::types::CPU_SETSIZE;
/// Create a new and empty `CpuSet`.
#[inline]
pub fn new() -> Self {
Self {
cpu_set: backend::process::types::raw_cpu_set_new(),
}
}
/// Test to see if a CPU is in the `CpuSet`.
///
/// `field` is the CPU id to test.
#[inline]
pub fn is_set(&self, field: usize) -> bool {
backend::process::cpu_set::CPU_ISSET(field, &self.cpu_set)
}
/// Add a CPU to `CpuSet`.
///
/// `field` is the CPU id to add.
#[inline]
pub fn set(&mut self, field: usize) {
backend::process::cpu_set::CPU_SET(field, &mut self.cpu_set)
}
/// Remove a CPU from `CpuSet`.
///
/// `field` is the CPU id to remove.
#[inline]
pub fn unset(&mut self, field: usize) {
backend::process::cpu_set::CPU_CLR(field, &mut self.cpu_set)
}
/// Count the number of CPUs set in the `CpuSet`.
#[cfg(linux_kernel)]
#[inline]
pub fn count(&self) -> u32 {
backend::process::cpu_set::CPU_COUNT(&self.cpu_set)
}
/// Zeroes the `CpuSet`.
#[inline]
pub fn clear(&mut self) {
backend::process::cpu_set::CPU_ZERO(&mut self.cpu_set)
}
}
impl Default for CpuSet {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl fmt::Debug for CpuSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "CpuSet {{")?;
let mut first = true;
for i in 0..Self::MAX_CPU {
if self.is_set(i) {
if first {
write!(f, " ")?;
first = false;
} else {
write!(f, ", ")?;
}
write!(f, "cpu{}", i)?;
}
}
write!(f, " }}")
}
}
impl hash::Hash for CpuSet {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
for i in 0..Self::MAX_CPU {
self.is_set(i).hash(state);
}
}
}
impl Eq for CpuSet {}
impl PartialEq for CpuSet {
fn eq(&self, other: &Self) -> bool {
backend::process::cpu_set::CPU_EQUAL(&self.cpu_set, &other.cpu_set)
}
}
/// `sched_setaffinity(pid, cpuset)`—Set a thread's CPU affinity mask.
///
/// `pid` is the thread ID to update. If pid is `None`, then the current thread
/// is updated.
///
/// The `CpuSet` argument specifies the set of CPUs on which the thread will be
/// eligible to run.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/sched_setaffinity.2.html
#[inline]
pub fn sched_setaffinity(pid: Option<Pid>, cpuset: &CpuSet) -> io::Result<()> {
backend::process::syscalls::sched_setaffinity(pid, &cpuset.cpu_set)
}
/// `sched_getaffinity(pid)`—Get a thread's CPU affinity mask.
///
/// `pid` is the thread ID to check. If pid is `None`, then the current thread
/// is checked.
///
/// Returns the set of CPUs on which the thread is eligible to run.
///
/// # References
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/sched_getaffinity.2.html
#[inline]
pub fn sched_getaffinity(pid: Option<Pid>) -> io::Result<CpuSet> {
let mut cpuset = CpuSet::new();
backend::process::syscalls::sched_getaffinity(pid, &mut cpuset.cpu_set).and(Ok(cpuset))
}
/// `sched_getcpu()`—Get the CPU that the current thread is currently on.
///
/// # References
/// - [Linux]
/// - [DragonFly BSD]
///
/// [Linux]: https://man7.org/linux/man-pages/man3/sched_getcpu.3.html
/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=sched_getcpu§ion=2
// FreeBSD added `sched_getcpu` in 13.0.
#[cfg(any(linux_kernel, target_os = "dragonfly"))]
#[inline]
pub fn sched_getcpu() -> usize {
backend::process::syscalls::sched_getcpu()
}