use crate::law::NumaNodeId;
#[cfg(all(feature = "std", any(target_os = "linux", windows), not(miri)))]
use crate::topology::MAX_NUMA_NODE_IDS;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct CpuLocality {
processor: u32,
numa_node: NumaNodeId,
}
#[must_use]
#[inline]
pub fn current_processor() -> Option<u32> {
query_cpu_locality_os().map(|locality| locality.processor)
}
#[must_use]
#[inline]
pub fn try_current_numa_node() -> Option<NumaNodeId> {
query_cpu_locality_os().map(|locality| locality.numa_node)
}
#[inline]
pub(super) fn query_numa_node_or_default() -> NumaNodeId {
try_current_numa_node().unwrap_or(NumaNodeId::ZERO)
}
#[inline(never)]
fn query_cpu_locality_os() -> Option<CpuLocality> {
#[cfg(all(feature = "std", target_os = "linux", not(miri)))]
{
let mut cpu = 0u32;
let mut node = 0u32;
let status = unsafe {
libc::syscall(
libc::SYS_getcpu,
core::ptr::addr_of_mut!(cpu),
core::ptr::addr_of_mut!(node),
core::ptr::null_mut::<core::ffi::c_void>(),
)
};
if status == 0 && cpu < 32768 && (node as usize) < MAX_NUMA_NODE_IDS {
Some(CpuLocality {
processor: cpu,
numa_node: NumaNodeId::new(node),
})
} else {
None
}
}
#[cfg(all(feature = "std", windows, not(miri)))]
{
unsafe {
#[repr(C)]
#[derive(Clone, Copy)]
struct ProcessorNumber {
group: u16,
number: u8,
reserved: u8,
}
extern "system" {
fn GetCurrentProcessorNumberEx(proc_number: *mut ProcessorNumber);
fn GetNumaProcessorNodeEx(
processor: *const ProcessorNumber,
node_number: *mut u16,
) -> i32;
}
let mut proc_num = ProcessorNumber {
group: 0,
number: 0,
reserved: 0,
};
GetCurrentProcessorNumberEx(core::ptr::addr_of_mut!(proc_num));
let mut node = 0u16;
if GetNumaProcessorNodeEx(core::ptr::addr_of!(proc_num), core::ptr::addr_of_mut!(node))
!= 0
{
let system_processor = u32::from(proc_num.group) * 64 + u32::from(proc_num.number);
if system_processor < 32768 && (node as usize) < MAX_NUMA_NODE_IDS {
Some(CpuLocality {
processor: system_processor,
numa_node: NumaNodeId::new(u32::from(node)),
})
} else {
None
}
} else {
None
}
}
}
#[cfg(not(any(
all(feature = "std", target_os = "linux", not(miri)),
all(feature = "std", windows, not(miri))
)))]
{
None
}
}