use crate::ibverbs::device::Device;
use std::io;
impl<'a> Device<'a> {
pub fn bind_thread_to_numa(&self) -> io::Result<()> {
let dev = self
.name()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid device name"))?;
let numa = get_numa_node(dev)?;
set_numa_node(numa)?;
log::debug!("Task bound to numa node {numa}");
Ok(())
}
pub fn bind_thread_to_numa_strict(&self) -> io::Result<()> {
let dev = self
.name()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "invalid device name"))?;
let numa = get_numa_node(dev)?;
set_numa_node_strict(numa)?;
log::debug!("Task bound to numa node {numa}");
Ok(())
}
}
pub fn set_numa_node(node: i32) -> io::Result<()> {
let res = unsafe { numa_run_on_node(node) };
if res != 0 {
return Err(io::Error::last_os_error());
}
unsafe { numa_set_localalloc() };
Ok(())
}
pub fn set_numa_node_strict(node: i32) -> io::Result<()> {
let res = unsafe { numa_run_on_node(node) };
if res != 0 {
return Err(io::Error::last_os_error());
}
unsafe { numa_set_bind_policy(1) };
unsafe { numa_set_localalloc() };
Ok(())
}
#[link(name = "numa")]
unsafe extern "C" {
fn numa_run_on_node(node: std::os::raw::c_int) -> std::os::raw::c_int;
fn numa_set_localalloc();
fn numa_set_bind_policy(strict: std::os::raw::c_int);
}
fn get_numa_node(dev: &str) -> io::Result<i32> {
let numa_path = format!("/sys/class/infiniband/{dev}/device/numa_node");
let s = std::fs::read_to_string(numa_path)?;
let node = s
.trim()
.parse::<i32>()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
if node < 0 {
Err(io::Error::new(
io::ErrorKind::NotFound,
format!("numa node for {dev} not found"),
))
} else {
Ok(node)
}
}