pub unsafe fn mmap_huge_pages(size: usize) -> *mut u8 {
let ptr = libc::mmap(
core::ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS | libc::MAP_HUGETLB,
-1,
0,
);
if ptr == libc::MAP_FAILED {
core::ptr::null_mut()
} else {
ptr as *mut u8
}
}
pub unsafe fn mlock_pages(ptr: *const u8, size: usize) -> bool {
libc::mlock(ptr as *const libc::c_void, size) == 0
}
pub unsafe fn prefault_pages(ptr: *mut u8, size: usize) {
for offset in (0..size).step_by(4096) {
core::ptr::write_volatile(ptr.add(offset), 0u8);
}
}
pub fn set_numa_preferred(node: usize) -> bool {
let max_node = core::mem::size_of::<libc::c_ulong>() * 8;
if node >= max_node {
return false;
}
let nodemask: libc::c_ulong = 1u64.wrapping_shl(node as u32) as libc::c_ulong;
let maxnode = core::mem::size_of::<libc::c_ulong>() * 8;
unsafe {
libc::syscall(
libc::SYS_set_mempolicy,
1i32, &nodemask as *const libc::c_ulong,
maxnode as libc::c_ulong,
) == 0
}
}
pub fn reset_numa_policy() -> bool {
unsafe {
libc::syscall(
libc::SYS_set_mempolicy,
0i32, core::ptr::null::<libc::c_ulong>(),
0 as libc::c_ulong,
) == 0
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::channel;
use crate::slot::Slot;
#[test]
fn slot_alignment_is_cache_line() {
assert_eq!(core::mem::align_of::<Slot<u64>>(), 64);
}
#[test]
fn test_prefault() {
let (mut pub_, subs) = channel::<u64>(64);
unsafe {
pub_.prefault();
}
let mut sub = subs.subscribe();
pub_.publish(42);
pub_.publish(43);
assert_eq!(sub.try_recv(), Ok(42));
assert_eq!(sub.try_recv(), Ok(43));
}
#[test]
fn test_mlock() {
let (pub_, _subs) = channel::<u64>(64);
let _result: bool = pub_.mlock();
}
#[test]
fn test_mmap_huge_pages_returns_ptr_or_null() {
let size = 2 * 1024 * 1024; let ptr = unsafe { mmap_huge_pages(size) };
if !ptr.is_null() {
unsafe {
libc::munmap(ptr as *mut libc::c_void, size);
}
}
}
#[test]
fn test_prefault_pages_standalone() {
let size = 8192; let ptr = unsafe {
libc::mmap(
core::ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
)
};
assert_ne!(ptr, libc::MAP_FAILED);
let ptr = ptr as *mut u8;
unsafe {
prefault_pages(ptr, size);
assert_eq!(core::ptr::read_volatile(ptr), 0u8);
assert_eq!(core::ptr::read_volatile(ptr.add(4096)), 0u8);
libc::munmap(ptr as *mut libc::c_void, size);
}
}
#[test]
fn test_mlock_pages_standalone() {
let size = 4096;
let ptr = unsafe {
libc::mmap(
core::ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
-1,
0,
)
};
assert_ne!(ptr, libc::MAP_FAILED);
let ptr = ptr as *mut u8;
let _result = unsafe { mlock_pages(ptr, size) };
unsafe {
libc::munmap(ptr as *mut libc::c_void, size);
}
}
#[test]
fn test_set_numa_preferred() {
let result = set_numa_preferred(0);
let _ = result;
reset_numa_policy();
}
#[test]
fn test_reset_numa_policy() {
assert!(reset_numa_policy());
}
}