use std::io;
use super::{Builder, CpuMask};
impl Builder {
pub fn worker_cores(mut self, cores: impl IntoIterator<Item = usize>) -> Self {
self.worker_cores = Some(cores.into_iter().collect());
self
}
pub fn blocking_cores(mut self, cores: impl IntoIterator<Item = usize>) -> Self {
self.blocking_cores = Some(cores.into_iter().collect());
self
}
}
fn process_cores() -> Vec<usize> {
let cores = super::allowed_cores();
if !cores.is_empty() {
return cores;
}
(0..std::thread::available_parallelism().map_or(1, usize::from)).collect()
}
pub(super) fn validate(setting: &str, cores: Option<&[usize]>) -> io::Result<()> {
let Some(cores) = cores else {
return Ok(());
};
if cores.is_empty() {
return Err(crate::config::refuse(setting, "empty", "at least one core"));
}
let allowed = process_cores();
if let Some(core) = cores.iter().find(|core| !allowed.contains(core)) {
return Err(crate::config::refuse(
setting,
format_args!("a list naming core {core}"),
format_args!("a list of the cores this process may run on ({allowed:?})"),
));
}
Ok(())
}
pub(super) fn mask_of(cores: &[usize]) -> Option<CpuMask> {
#[cfg(target_os = "linux")]
{
let mut set: libc::cpu_set_t = unsafe { core::mem::zeroed() };
for &core in cores.iter().filter(|&&c| c < libc::CPU_SETSIZE as usize) {
unsafe { libc::CPU_SET(core, &mut set) };
}
Some(set)
}
#[cfg(windows)]
{
Some(
cores
.iter()
.filter(|&&c| c < usize::BITS as usize)
.fold(0usize, |mask, &c| mask | (1 << c)),
)
}
#[cfg(not(any(target_os = "linux", windows)))]
{
let _ = cores;
None
}
}