95 lines
2.2 KiB
Rust

use std::{
ffi::c_void,
io,
ops::{Deref, DerefMut},
os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd},
ptr::null_mut,
};
use crate::sys;
pub struct SharedMemoryImpl {
fd: OwnedFd,
size: usize,
}
pub struct FileMappingImpl {
fd: OwnedFd,
pointer: *mut c_void,
size: usize,
}
impl sys::SharedMemory for SharedMemoryImpl {
type Mapping = FileMappingImpl;
fn map(self) -> io::Result<Self::Mapping> {
<FileMappingImpl as sys::FileMapping>::map(self.fd, self.size)
}
fn new(size: usize) -> io::Result<Self> {
let fd = unsafe { libc::memfd_create(c"cross-shm".as_ptr(), libc::MFD_CLOEXEC) };
if fd < 0 {
return Err(io::Error::last_os_error());
}
let fd = unsafe { OwnedFd::from_raw_fd(fd) };
if unsafe { libc::ftruncate(fd.as_raw_fd(), size as i64) } != 0 {
return Err(io::Error::last_os_error());
}
Ok(Self { fd, size })
}
}
impl AsRawFd for SharedMemoryImpl {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
impl sys::FileMapping for FileMappingImpl {
fn map<F: Into<OwnedFd>>(file: F, size: usize) -> io::Result<Self> {
let fd: OwnedFd = file.into();
let pointer = unsafe {
libc::mmap(
null_mut(),
size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED,
fd.as_raw_fd(),
0,
)
};
if pointer == libc::MAP_FAILED {
return Err(io::Error::last_os_error());
}
Ok(Self { fd, pointer, size })
}
}
impl Drop for FileMappingImpl {
fn drop(&mut self) {
unsafe {
libc::munmap(self.pointer, self.size);
}
}
}
impl Deref for FileMappingImpl {
type Target = [u8];
fn deref(&self) -> &Self::Target {
unsafe { core::slice::from_raw_parts(self.pointer.cast(), self.size) }
}
}
impl DerefMut for FileMappingImpl {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { core::slice::from_raw_parts_mut(self.pointer.cast(), self.size) }
}
}
impl AsRawFd for FileMappingImpl {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}