#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CpuMask(BitMask);
impl Default for CpuMask
{
#[inline(always)]
fn default() -> Self
{
Self::allocate()
}
}
impl Mask<CpuIndex> for CpuMask
{
#[inline(always)]
fn allocate() -> Self
{
CpuMask(BitMask(unsafe { numa_allocate_cpumask() }))
}
#[inline(always)]
fn all() -> Self
{
CpuMask(BitMask(unsafe { numa_all_cpus_ptr })).clone()
}
#[inline(always)]
fn parse_string(string: &CStr) -> Self
{
CpuMask(BitMask(unsafe { numa_parse_cpustring(string.as_ptr()) }))
}
#[inline(always)]
fn parse_string_all(string: &CStr) -> Self
{
CpuMask(BitMask(unsafe { numa_parse_cpustring_all(string.as_ptr()) }))
}
#[inline(always)]
#[doc(hidden)]
fn bit_mask(&self) -> &BitMask
{
&self.0
}
}
impl CpuMask
{
#[inline(always)]
pub fn get_run_node_mask() -> CpuMask
{
CpuMask(BitMask(unsafe { numa_get_run_node_mask() }))
}
#[inline(always)]
pub fn run_on_node_mask(&self)
{
match unsafe { numa_run_on_node_mask(self.bitmask()) }
{
0 => (),
-1 => match errno().0
{
unexpected @ _ => panic!("numa_run_on_node_mask set errno {} but the man pages helpfully don't tell us what errors to expect", unexpected),
},
unexpected @ _ => panic!("Did not expect numa_run_on_node_mask to return {}", unexpected),
}
}
#[inline(always)]
pub fn bind(&self)
{
unsafe { numa_bind(self.bitmask()) }
}
pub fn sched_get_affinity_for_current_thread() -> Self
{
let all_nodes = Self::allocate();
let result = all_nodes.sched_get_affinity_for_task(0);
if result.is_err()
{
panic!("sched_get_affinity failed for current thread");
}
all_nodes
}
pub fn sched_get_affinity_for_task(&self, task_id: pid_t) -> Result<usize, ErrorKind>
{
match unsafe { numa_sched_getaffinity(task_id, self.bitmask()) }
{
size_of_cpumask_t if size_of_cpumask_t >= 0 => Ok(size_of_cpumask_t as usize),
-1 => match errno().0
{
::libc::EFAULT => panic!("EFAULT for numa_sched_getaffinity"),
::libc::EINVAL => panic!("? no processors or mask too small ? Great. Can't distinguish. numa_sched_getaffinity. EINVAL."),
::libc::ESRCH => Err(ErrorKind::NotFound),
unexpected @ _ => panic!("Did not expect numa_move_pages to set errno {}", unexpected),
},
unexpected @ _ => panic!("Did not expect numa_sched_getaffinity to return {}", unexpected),
}
}
pub fn sched_set_affinity_for_current_thread(&self) -> bool
{
match self.sched_set_affinity_for_task(0)
{
Ok(_) => true,
Err(err) =>
{
match err
{
ErrorKind::Other => false,
ErrorKind::PermissionDenied | ErrorKind::NotFound => panic!("sched_get_affinity_for_task for self (task_id 0) should not produce an ErrorKind of {:?}", err),
_ => panic!("Unexpected ErrorKind {:?}", err),
}
}
}
}
pub fn sched_set_affinity_for_task(&self, task_id: pid_t) -> Result<(), ErrorKind>
{
match unsafe { numa_sched_setaffinity(task_id, self.bitmask()) }
{
0 => Ok(()),
-1 => match errno().0
{
::libc::EFAULT => panic!("EFAULT for numa_sched_setaffinity"),
::libc::EINVAL => Err(ErrorKind::Other),
::libc::EPERM => Err(ErrorKind::PermissionDenied),
::libc::ESRCH => Err(ErrorKind::NotFound),
unexpected @ _ => panic!("Did not expect numa_move_pages to set errno {}", unexpected),
},
unexpected @ _ => panic!("Did not expect numa_sched_getaffinity to return {}", unexpected),
}
}
#[inline(always)]
fn bitmask(&self) -> *mut bitmask
{
(self.0).0
}
}