1use std::io::{self, Error};
2use std::ptr;
3use std::sync::atomic::{AtomicUsize, Ordering};
4
5#[cfg(any(target_os = "linux", target_os = "android"))]
6const MAP_POPULATE: libc::c_int = libc::MAP_POPULATE;
7
8#[cfg(not(any(target_os = "linux", target_os = "android")))]
9const MAP_POPULATE: libc::c_int = 0;
10
11#[cfg(any(
12 target_os = "linux",
13 target_os = "android",
14 target_vendor = "apple",
15 target_os = "netbsd",
16 target_os = "solaris",
17 target_os = "illumos",
18))]
19const MAP_NORESERVE: libc::c_int = libc::MAP_NORESERVE;
20
21#[cfg(not(any(
22 target_os = "linux",
23 target_os = "android",
24 target_vendor = "apple",
25 target_os = "netbsd",
26 target_os = "solaris",
27 target_os = "illumos",
28)))]
29const MAP_NORESERVE: libc::c_int = 0;
30
31pub fn page_size() -> usize {
33 static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
34
35 match PAGE_SIZE.load(Ordering::Relaxed) {
36 0 => {
37 #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
38 let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize };
39 PAGE_SIZE.store(page_size, Ordering::Relaxed);
40 page_size
41 }
42 page_size => page_size,
43 }
44}
45
46pub struct MmapInner {
47 ptr: *mut libc::c_void,
48 len: usize,
49}
50
51impl MmapInner {
52 pub unsafe fn map_anon(
58 hint_addr: usize,
59 len: usize,
60 populate: bool,
61 no_reserve: bool,
62 ) -> io::Result<Self> {
63 let populate = if populate { MAP_POPULATE } else { 0 };
64 let no_reserve = if no_reserve { MAP_NORESERVE } else { 0 };
65
66 let addr = if hint_addr == 0 {
67 ptr::null_mut()
68 } else {
69 hint_addr as *mut libc::c_void
70 };
71
72 let flags = libc::MAP_PRIVATE | libc::MAP_ANON | populate | no_reserve;
74 let prot = libc::PROT_READ | libc::PROT_WRITE;
75
76 let ptr = unsafe { libc::mmap(addr, len, prot, flags, -1, 0) };
77
78 if ptr == libc::MAP_FAILED {
79 return Err(Error::last_os_error());
80 }
81
82 Ok(Self { ptr, len })
88 }
89
90 pub const fn ptr(&self) -> *mut u8 {
91 self.ptr.cast::<u8>()
92 }
93
94 pub const fn len(&self) -> usize {
95 self.len
96 }
97
98 pub const unsafe fn from_raw(ptr: *mut u8, len: usize) -> Self {
100 Self {
101 ptr: ptr.cast::<libc::c_void>(),
102 len,
103 }
104 }
105}
106
107impl Drop for MmapInner {
108 fn drop(&mut self) {
109 if self.len > 0 {
110 unsafe {
111 libc::munmap(self.ptr, self.len);
112 }
113 }
114 }
115}
116
117unsafe impl Send for MmapInner {}
118unsafe impl Sync for MmapInner {}