hcl/
mapped_page.rs
1use std::cell::UnsafeCell;
5use std::fs::File;
6use std::io;
7use std::os::fd::AsRawFd;
8use std::ptr::NonNull;
9
10pub(crate) struct MappedPage<T>(NonNull<UnsafeCell<T>>);
11
12impl<T> MappedPage<T> {
13 pub fn new(fd: &File, pg_off: i64) -> io::Result<Self> {
14 assert!(size_of::<T>() <= 4096);
16
17 let ptr = unsafe {
19 let page_size = libc::sysconf(libc::_SC_PAGESIZE);
20 libc::mmap(
21 std::ptr::null_mut(),
22 page_size as usize,
23 libc::PROT_READ | libc::PROT_WRITE,
24 libc::MAP_SHARED,
25 fd.as_raw_fd(),
26 pg_off * page_size,
27 )
28 };
29 if ptr == libc::MAP_FAILED {
30 return Err(io::Error::last_os_error());
31 }
32
33 Ok(Self(NonNull::new(ptr).unwrap().cast()))
34 }
35
36 pub fn as_ptr(&self) -> *mut T {
37 UnsafeCell::raw_get(self.0.as_ptr())
38 }
39
40 pub fn as_ref(&self) -> &UnsafeCell<T> {
41 unsafe { self.0.as_ref() }
44 }
45}
46
47impl<T> std::fmt::Debug for MappedPage<T> {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 f.debug_tuple("MappedPage").field(&self.0).finish()
50 }
51}
52
53impl<T> Drop for MappedPage<T> {
54 fn drop(&mut self) {
55 unsafe {
57 libc::munmap(
58 self.0.as_ptr().cast(),
59 libc::sysconf(libc::_SC_PAGESIZE) as usize,
60 );
61 }
62 }
63}
64
65unsafe impl<T> Send for MappedPage<T> {}
67unsafe impl<T> Sync for MappedPage<T> {}