use core::num::NonZeroU32;
use core::ptr;
use core::sync::atomic;
use rustix::fd::OwnedFd;
use rustix::io;
use rustix::mm::{Advice, MapFlags, ProtFlags};
pub(crate) mod private {
pub trait Sealed {}
}
pub(crate) struct Mmap {
addr: ptr::NonNull<core::ffi::c_void>,
len: usize,
}
impl Mmap {
pub fn new(fd: &OwnedFd, offset: u64, len: usize) -> io::Result<Mmap> {
unsafe {
let addr = rustix::mm::mmap(
ptr::null_mut(),
len,
ProtFlags::READ | ProtFlags::WRITE,
MapFlags::SHARED | MapFlags::POPULATE,
fd,
offset,
)?;
let addr = ptr::NonNull::new_unchecked(addr);
Ok(Mmap { addr, len })
}
}
pub fn dontfork(&self) -> io::Result<()> {
unsafe {
rustix::mm::madvise(self.addr.as_ptr(), self.len, Advice::LinuxDontFork)?;
}
Ok(())
}
#[inline]
pub fn as_mut_ptr(&self) -> *mut core::ffi::c_void {
self.addr.as_ptr()
}
#[inline]
pub unsafe fn offset(&self, offset: u32) -> *mut core::ffi::c_void {
self.as_mut_ptr().add(offset as usize)
}
}
impl Drop for Mmap {
fn drop(&mut self) {
unsafe {
rustix::mm::munmap(self.addr.as_ptr(), self.len).unwrap();
}
}
}
#[inline(always)]
pub(crate) unsafe fn unsync_load(u: *const atomic::AtomicU32) -> u32 {
*u.cast::<u32>()
}
#[inline]
pub(crate) const fn cast_ptr<T>(n: &T) -> *const T {
n
}
#[allow(unconditional_panic, clippy::out_of_bounds_indexing)]
pub(crate) const fn unwrap_u32(t: Option<u32>) -> u32 {
match t {
Some(v) => v,
None => [][1],
}
}
#[allow(unconditional_panic, clippy::out_of_bounds_indexing)]
pub(crate) const fn unwrap_nonzero(t: Option<NonZeroU32>) -> NonZeroU32 {
match t {
Some(v) => v,
None => [][1],
}
}