Skip to main content

dope_core/platform/
affinity.rs

1use std::iter;
2
3use dope_sys::thread::{Thread as _, affinity};
4use o3::base::marker::ThreadBound;
5
6use crate::{Backend, Errno};
7
8/// Result of binding the calling thread to one logical CPU.
9///
10/// The receipt is confined to the thread that performed the binding. A later
11/// affinity change can replace that binding.
12#[repr(transparent)]
13pub struct Binding {
14    cpu: Cpu,
15    thread: ThreadBound,
16}
17
18impl Binding {
19    pub fn bind(cpu: Cpu) -> Result<Self, Error> {
20        Backend::bind(cpu.0).map_err(Error::from_native)?;
21        Ok(Self {
22            cpu,
23            thread: ThreadBound::NEW,
24        })
25    }
26
27    pub fn cpu(&self) -> Cpu {
28        self.cpu
29    }
30}
31
32const _: () = {
33    assert!(std::mem::size_of::<Binding>() == std::mem::size_of::<Cpu>());
34    assert!(std::mem::align_of::<Binding>() == std::mem::align_of::<Cpu>());
35};
36
37/// A CPU proven present in a native affinity discovery result.
38#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
39#[repr(transparent)]
40pub struct Cpu(affinity::raw::Cpu);
41
42impl Cpu {
43    pub fn current() -> Result<
44        impl DoubleEndedIterator<Item = Self> + ExactSizeIterator + iter::FusedIterator,
45        Error,
46    > {
47        Backend::current()
48            .map(|cpus| cpus.map(Self))
49            .map_err(Error::from_native)
50    }
51    pub const fn raw(self) -> u16 {
52        self.0.raw()
53    }
54    pub const fn matches(self, index: Index) -> bool {
55        self.raw() == index.0
56    }
57}
58
59impl From<Cpu> for u64 {
60    fn from(cpu: Cpu) -> Self {
61        u64::from(cpu.0)
62    }
63}
64
65#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
66#[repr(transparent)]
67pub struct Index(u16);
68
69impl From<u16> for Index {
70    fn from(index: u16) -> Self {
71        Self(index)
72    }
73}
74
75#[derive(Clone, Copy, Debug, PartialEq, Eq)]
76pub enum Error {
77    DiscoveryUnsupported,
78    BindingUnsupported { cpu: Cpu },
79    BindingRange { cpu: Cpu, maximum: u16 },
80    Current(Errno),
81    Bind { cpu: Cpu, fault: Errno },
82}
83
84impl Error {
85    fn from_native(error: affinity::Error) -> Self {
86        match error {
87            affinity::Error::DiscoveryUnsupported => Self::DiscoveryUnsupported,
88            affinity::Error::BindingUnsupported { cpu } => {
89                Self::BindingUnsupported { cpu: Cpu(cpu) }
90            }
91            affinity::Error::BindingRange { cpu, maximum } => Self::BindingRange {
92                cpu: Cpu(cpu),
93                maximum,
94            },
95            affinity::Error::Current(error) => Self::Current(error),
96            affinity::Error::Bind { cpu, fault } => Self::Bind {
97                cpu: Cpu(cpu),
98                fault,
99            },
100        }
101    }
102}