-
Notifications
You must be signed in to change notification settings - Fork 666
/
mman.rs
242 lines (207 loc) · 9.21 KB
/
mman.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
use {Errno, Error, Result, NixPath};
use fcntl::OFlag;
use libc::{self, c_void, size_t, off_t, mode_t};
use sys::stat::Mode;
use std::os::unix::io::RawFd;
pub use self::consts::*;
libc_bitflags!{
pub flags ProtFlags: libc::c_int {
PROT_NONE,
PROT_READ,
PROT_WRITE,
PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSUP,
}
}
#[cfg(any(target_os = "linux", target_os = "android"))]
mod consts {
use libc::{self, c_int};
libc_bitflags!{
pub flags MapFlags: c_int {
MAP_FILE,
MAP_SHARED,
MAP_PRIVATE,
MAP_FIXED,
MAP_ANON,
MAP_ANONYMOUS,
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
MAP_32BIT,
MAP_GROWSDOWN,
MAP_DENYWRITE,
MAP_EXECUTABLE,
MAP_LOCKED,
MAP_NORESERVE,
MAP_POPULATE,
MAP_NONBLOCK,
MAP_STACK,
MAP_HUGETLB,
}
}
pub type MmapAdvise = c_int;
pub const MADV_NORMAL : MmapAdvise = 0; /* No further special treatment. */
pub const MADV_RANDOM : MmapAdvise = 1; /* Expect random page references. */
pub const MADV_SEQUENTIAL : MmapAdvise = 2; /* Expect sequential page references. */
pub const MADV_WILLNEED : MmapAdvise = 3; /* Will need these pages. */
pub const MADV_DONTNEED : MmapAdvise = 4; /* Don't need these pages. */
pub const MADV_REMOVE : MmapAdvise = 9; /* Remove these pages and resources. */
pub const MADV_DONTFORK : MmapAdvise = 10; /* Do not inherit across fork. */
pub const MADV_DOFORK : MmapAdvise = 11; /* Do inherit across fork. */
pub const MADV_MERGEABLE : MmapAdvise = 12; /* KSM may merge identical pages. */
pub const MADV_UNMERGEABLE: MmapAdvise = 13; /* KSM may not merge identical pages. */
pub const MADV_HUGEPAGE : MmapAdvise = 14; /* Worth backing with hugepages. */
pub const MADV_NOHUGEPAGE : MmapAdvise = 15; /* Not worth backing with hugepages. */
pub const MADV_DONTDUMP : MmapAdvise = 16; /* Explicity exclude from the core dump, overrides the coredump filter bits. */
pub const MADV_DODUMP : MmapAdvise = 17; /* Clear the MADV_DONTDUMP flag. */
pub const MADV_HWPOISON : MmapAdvise = 100; /* Poison a page for testing. */
libc_bitflags!{
pub flags MsFlags: c_int {
MS_ASYNC,
MS_INVALIDATE,
MS_SYNC,
}
}
pub const MAP_FAILED: isize = -1;
}
#[cfg(any(target_os = "macos",
target_os = "ios"))]
mod consts {
use libc::{self, c_int};
libc_bitflags!{
pub flags MapFlags: c_int {
MAP_FILE,
MAP_SHARED,
MAP_PRIVATE,
MAP_FIXED,
MAP_ANON,
MAP_NOCACHE,
MAP_JIT,
}
}
pub type MmapAdvise = c_int;
pub const MADV_NORMAL : MmapAdvise = 0; /* No further special treatment. */
pub const MADV_RANDOM : MmapAdvise = 1; /* Expect random page references. */
pub const MADV_SEQUENTIAL : MmapAdvise = 2; /* Expect sequential page references. */
pub const MADV_WILLNEED : MmapAdvise = 3; /* Will need these pages. */
pub const MADV_DONTNEED : MmapAdvise = 4; /* Don't need these pages. */
pub const MADV_FREE : MmapAdvise = 5; /* pages unneeded, discard contents */
pub const MADV_ZERO_WIRED_PAGES: MmapAdvise = 6; /* zero the wired pages that have not been unwired before the entry is deleted */
pub const MADV_FREE_REUSABLE : MmapAdvise = 7; /* pages can be reused (by anyone) */
pub const MADV_FREE_REUSE : MmapAdvise = 8; /* caller wants to reuse those pages */
pub const MADV_CAN_REUSE : MmapAdvise = 9;
libc_bitflags!{
pub flags MsFlags: c_int {
MS_ASYNC, /* [MF|SIO] return immediately */
MS_INVALIDATE, /* [MF|SIO] invalidate all cached data */
MS_KILLPAGES, /* invalidate pages, leave mapped */
MS_DEACTIVATE, /* deactivate pages, leave mapped */
MS_SYNC, /* [MF|SIO] msync synchronously */
}
}
pub const MAP_FAILED: isize = -1;
}
#[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))]
mod consts {
use libc::{self, c_int};
libc_bitflags!{
pub flags MapFlags: c_int {
MAP_FILE,
MAP_SHARED,
MAP_PRIVATE,
MAP_FIXED,
MAP_RENAME,
MAP_NORESERVE,
MAP_HASSEMAPHORE,
#[cfg(not(any(target_os = "openbsd", target_os = "netbsd")))]
MAP_STACK,
#[cfg(target_os = "netbsd")]
MAP_WIRED,
#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
MAP_NOSYNC,
MAP_ANON,
}
}
pub type MmapAdvise = c_int;
pub const MADV_NORMAL : MmapAdvise = 0; /* No further special treatment. */
pub const MADV_RANDOM : MmapAdvise = 1; /* Expect random page references. */
pub const MADV_SEQUENTIAL : MmapAdvise = 2; /* Expect sequential page references. */
pub const MADV_WILLNEED : MmapAdvise = 3; /* Will need these pages. */
pub const MADV_DONTNEED : MmapAdvise = 4; /* Don't need these pages. */
pub const MADV_FREE : MmapAdvise = 5; /* pages unneeded, discard contents */
pub const MADV_NOSYNC : MmapAdvise = 6; /* try to avoid flushes to physical media*/
pub const MADV_AUTOSYNC : MmapAdvise = 7; /* refert to default flushing strategy */
pub const MADV_NOCORE : MmapAdvise = 8; /* do not include these pages in a core file */
pub const MADV_CORE : MmapAdvise = 9; /* revert to including pages in a core file */
#[cfg(not(target_os = "dragonfly"))]
pub const MADV_PROTECT : MmapAdvise = 10; /* protect process from pageout kill */
#[cfg(target_os = "dragonfly")]
pub const MADV_INVAL : MmapAdvise = 10; /* virt page tables have changed, inval pmap */
#[cfg(target_os = "dragonfly")]
pub const MADV_SETMAP : MmapAdvise = 11; /* set page table directory page for map */
bitflags!{
pub flags MsFlags: c_int {
const MS_ASYNC = libc::MS_ASYNC, /* [MF|SIO] return immediately */
const MS_INVALIDATE = libc::MS_INVALIDATE, /* [MF|SIO] invalidate all cached data */
#[cfg(not(target_os = "dragonfly"))]
const MS_KILLPAGES = 0x0004, /* invalidate pages, leave mapped */
#[cfg(not(target_os = "dragonfly"))]
const MS_DEACTIVATE = 0x0004, /* deactivate pages, leave mapped */
const MS_SYNC = libc::MS_SYNC, /* [MF|SIO] msync synchronously */
}
}
pub const MAP_FAILED: isize = -1;
}
mod ffi {
use libc::{c_void, size_t, c_int, c_char, mode_t};
pub use libc::{mmap, munmap};
#[allow(improper_ctypes)]
extern {
pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int;
pub fn shm_unlink(name: *const c_char) -> c_int;
pub fn mlock(addr: *const c_void, len: size_t) -> c_int;
pub fn munlock(addr: *const c_void, len: size_t) -> c_int;
pub fn madvise (addr: *const c_void, len: size_t, advice: c_int) -> c_int;
pub fn msync (addr: *const c_void, len: size_t, flags: c_int) -> c_int;
}
}
pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
Errno::result(ffi::mlock(addr, length)).map(drop)
}
pub fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
Errno::result(unsafe { ffi::munlock(addr, length) }).map(drop)
}
/// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically
/// a higher-level abstraction will hide the unsafe interactions with the mmap'd region.
pub fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
let ret = unsafe { ffi::mmap(addr, length, prot.bits(), flags.bits(), fd, offset) };
if ret as isize == MAP_FAILED {
Err(Error::Sys(Errno::last()))
} else {
Ok(ret)
}
}
pub fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
Errno::result(unsafe { ffi::munmap(addr, len) }).map(drop)
}
pub fn madvise(addr: *const c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
Errno::result(unsafe { ffi::madvise(addr, length, advise) }).map(drop)
}
pub fn msync(addr: *const c_void, length: size_t, flags: MsFlags) -> Result<()> {
Errno::result(unsafe { ffi::msync(addr, length, flags.bits()) }).map(drop)
}
pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
let ret = try!(name.with_nix_path(|cstr| {
unsafe {
ffi::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as mode_t)
}
}));
Errno::result(ret)
}
pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
let ret = try!(name.with_nix_path(|cstr| {
unsafe { ffi::shm_unlink(cstr.as_ptr()) }
}));
Errno::result(ret).map(drop)
}