use std::io;
#[cfg(unix)]
pub fn alloc_shared(size: usize) -> Result<*mut u8, io::Error> {
let ptr = unsafe {
libc::mmap(
std::ptr::null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED | libc::MAP_ANONYMOUS,
-1,
0,
)
};
if ptr == libc::MAP_FAILED {
return Err(io::Error::last_os_error());
}
Ok(ptr as *mut u8)
}
#[cfg(unix)]
pub unsafe fn free_shared(ptr: *mut u8, size: usize) {
unsafe {
libc::munmap(ptr as *mut libc::c_void, size);
}
}
#[cfg(not(unix))]
pub fn alloc_shared(size: usize) -> Result<*mut u8, io::Error> {
Err(io::Error::new(
io::ErrorKind::Unsupported,
"shared memory requires unix",
))
}
#[cfg(not(unix))]
pub unsafe fn free_shared(_ptr: *mut u8, _size: usize) {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_alloc_write_read_free() {
let size = 4096;
let ptr = alloc_shared(size).expect("alloc_shared failed");
assert!(!ptr.is_null());
unsafe {
*ptr = 42;
*ptr.add(size - 1) = 99;
assert_eq!(*ptr, 42);
assert_eq!(*ptr.add(size - 1), 99);
free_shared(ptr, size);
}
}
#[test]
fn test_zeroed_on_alloc() {
let size = 1024;
let ptr = alloc_shared(size).expect("alloc_shared failed");
unsafe {
for i in 0..size {
assert_eq!(*ptr.add(i), 0);
}
free_shared(ptr, size);
}
}
}