nix/sys/mman.rs
1//! Memory management declarations.
2
3use crate::errno::Errno;
4#[cfg(not(target_os = "android"))]
5use crate::NixPath;
6use crate::Result;
7#[cfg(not(target_os = "android"))]
8#[cfg(feature = "fs")]
9use crate::{fcntl::OFlag, sys::stat::Mode};
10use libc::{self, c_int, c_void, off_t, size_t};
11use std::ptr::NonNull;
12use std::{
13 num::NonZeroUsize,
14 os::unix::io::{AsFd, AsRawFd},
15};
16
17libc_bitflags! {
18 /// Desired memory protection of a memory mapping.
19 pub struct ProtFlags: c_int {
20 /// Pages cannot be accessed.
21 PROT_NONE;
22 /// Pages can be read.
23 PROT_READ;
24 /// Pages can be written.
25 PROT_WRITE;
26 /// Pages can be executed
27 PROT_EXEC;
28 /// Apply protection up to the end of a mapping that grows upwards.
29 #[cfg(linux_android)]
30 PROT_GROWSDOWN;
31 /// Apply protection down to the beginning of a mapping that grows downwards.
32 #[cfg(linux_android)]
33 PROT_GROWSUP;
34 }
35}
36
37libc_bitflags! {
38 /// Additional parameters for [`mmap`].
39 pub struct MapFlags: c_int {
40 /// Compatibility flag. Ignored.
41 #[cfg(not(any(target_os = "solaris", target_os = "redox")))]
42 MAP_FILE;
43 /// Share this mapping. Mutually exclusive with `MAP_PRIVATE`.
44 MAP_SHARED;
45 /// Force mmap to check and fail on unknown flags. This also enables `MAP_SYNC`.
46 #[cfg(target_os = "linux")]
47 MAP_SHARED_VALIDATE;
48 /// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`.
49 MAP_PRIVATE;
50 /// Place the mapping at exactly the address specified in `addr`.
51 MAP_FIXED;
52 /// Place the mapping at exactly the address specified in `addr`, but never clobber an existing range.
53 #[cfg(target_os = "linux")]
54 MAP_FIXED_NOREPLACE;
55 /// To be used with `MAP_FIXED`, to forbid the system
56 /// to select a different address than the one specified.
57 #[cfg(target_os = "freebsd")]
58 MAP_EXCL;
59 /// Synonym for `MAP_ANONYMOUS`.
60 MAP_ANON;
61 /// The mapping is not backed by any file.
62 MAP_ANONYMOUS;
63 /// Put the mapping into the first 2GB of the process address space.
64 #[cfg(any(all(linux_android,
65 any(target_arch = "x86", target_arch = "x86_64")),
66 all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
67 all(target_os = "linux", target_env = "ohos", target_arch = "x86_64"),
68 all(target_os = "freebsd", target_pointer_width = "64")))]
69 MAP_32BIT;
70 /// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
71 #[cfg(linux_android)]
72 MAP_GROWSDOWN;
73 /// Compatibility flag. Ignored.
74 #[cfg(linux_android)]
75 MAP_DENYWRITE;
76 /// Compatibility flag. Ignored.
77 #[cfg(linux_android)]
78 MAP_EXECUTABLE;
79 /// Mark the mmaped region to be locked in the same way as `mlock(2)`.
80 #[cfg(linux_android)]
81 MAP_LOCKED;
82 /// Do not reserve swap space for this mapping.
83 ///
84 /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
85 #[cfg(not(any(freebsdlike, target_os = "aix", target_os = "hurd", target_os = "redox")))]
86 MAP_NORESERVE;
87 /// Populate page tables for a mapping.
88 #[cfg(linux_android)]
89 MAP_POPULATE;
90 /// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead.
91 #[cfg(linux_android)]
92 MAP_NONBLOCK;
93 /// Allocate the mapping using "huge pages."
94 #[cfg(linux_android)]
95 MAP_HUGETLB;
96 /// Make use of 64KB huge page (must be supported by the system)
97 #[cfg(target_os = "linux")]
98 MAP_HUGE_64KB;
99 /// Make use of 512KB huge page (must be supported by the system)
100 #[cfg(target_os = "linux")]
101 MAP_HUGE_512KB;
102 /// Make use of 1MB huge page (must be supported by the system)
103 #[cfg(target_os = "linux")]
104 MAP_HUGE_1MB;
105 /// Make use of 2MB huge page (must be supported by the system)
106 #[cfg(target_os = "linux")]
107 MAP_HUGE_2MB;
108 /// Make use of 8MB huge page (must be supported by the system)
109 #[cfg(target_os = "linux")]
110 MAP_HUGE_8MB;
111 /// Make use of 16MB huge page (must be supported by the system)
112 #[cfg(target_os = "linux")]
113 MAP_HUGE_16MB;
114 /// Make use of 32MB huge page (must be supported by the system)
115 #[cfg(target_os = "linux")]
116 MAP_HUGE_32MB;
117 /// Make use of 256MB huge page (must be supported by the system)
118 #[cfg(target_os = "linux")]
119 MAP_HUGE_256MB;
120 /// Make use of 512MB huge page (must be supported by the system)
121 #[cfg(target_os = "linux")]
122 MAP_HUGE_512MB;
123 /// Make use of 1GB huge page (must be supported by the system)
124 #[cfg(target_os = "linux")]
125 MAP_HUGE_1GB;
126 /// Make use of 2GB huge page (must be supported by the system)
127 #[cfg(target_os = "linux")]
128 MAP_HUGE_2GB;
129 /// Make use of 16GB huge page (must be supported by the system)
130 #[cfg(target_os = "linux")]
131 MAP_HUGE_16GB;
132
133 /// Lock the mapped region into memory as with `mlock(2)`.
134 #[cfg(target_os = "netbsd")]
135 MAP_WIRED;
136 /// Causes dirtied data in the specified range to be flushed to disk only when necessary.
137 #[cfg(freebsdlike)]
138 MAP_NOSYNC;
139 /// Rename private pages to a file.
140 ///
141 /// This was removed in FreeBSD 11 and is unused in DragonFlyBSD.
142 #[cfg(netbsdlike)]
143 MAP_RENAME;
144 /// Region may contain semaphores.
145 #[cfg(any(freebsdlike, netbsdlike))]
146 MAP_HASSEMAPHORE;
147 /// Region grows down, like a stack.
148 #[cfg(any(linux_android, freebsdlike, netbsdlike))]
149 MAP_STACK;
150 /// Do not write through the page caches, write directly to the file. Used for Direct Access (DAX) enabled file systems.
151 // Available on Linux glibc and musl, MIPS* target excluded.
152 #[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64", target_arch = "mips32r6", target_arch = "mips64r6")), not(target_env = "uclibc")))]
153 MAP_SYNC;
154 /// Pages in this mapping are not retained in the kernel's memory cache.
155 #[cfg(apple_targets)]
156 MAP_NOCACHE;
157 /// Allows the W/X bit on the page, it's necessary on aarch64 architecture.
158 #[cfg(apple_targets)]
159 MAP_JIT;
160 /// Allows to use large pages, underlying alignment based on size.
161 #[cfg(target_os = "freebsd")]
162 MAP_ALIGNED_SUPER;
163 /// Pages will be discarded in the core dumps.
164 #[cfg(target_os = "openbsd")]
165 MAP_CONCEAL;
166 /// Attempt to place the mapping at exactly the address specified in `addr`.
167 /// it's a default behavior on OpenBSD.
168 #[cfg(netbsdlike)]
169 MAP_TRYFIXED;
170 }
171}
172
173impl MapFlags {
174 /// Create `MAP_HUGETLB` with provided size of huge page.
175 ///
176 /// Under the hood it computes `MAP_HUGETLB | (huge_page_size_log2 << libc::MAP_HUGE_SHIFT`).
177 /// `huge_page_size_log2` denotes logarithm of huge page size to use and should be
178 /// between 16 and 63 (inclusively).
179 ///
180 /// ```
181 /// # use nix::sys::mman::MapFlags;
182 /// let f = MapFlags::map_hugetlb_with_size_log2(30).unwrap();
183 /// assert_eq!(f, MapFlags::MAP_HUGETLB | MapFlags::MAP_HUGE_1GB);
184 /// ```
185 #[cfg(any(linux_android, target_os = "fuchsia"))]
186 pub fn map_hugetlb_with_size_log2(
187 huge_page_size_log2: u32,
188 ) -> Option<Self> {
189 if (16..=63).contains(&huge_page_size_log2) {
190 let flag = libc::MAP_HUGETLB
191 | (huge_page_size_log2 << libc::MAP_HUGE_SHIFT) as i32;
192 Some(Self(flag.into()))
193 } else {
194 None
195 }
196 }
197}
198
199#[cfg(any(target_os = "linux", target_os = "netbsd"))]
200libc_bitflags! {
201 /// Options for [`mremap`].
202 pub struct MRemapFlags: c_int {
203 /// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
204 #[cfg(target_os = "linux")]
205 MREMAP_MAYMOVE;
206 /// Place the mapping at exactly the address specified in `new_address`.
207 #[cfg(target_os = "linux")]
208 MREMAP_FIXED;
209 /// Works in conjunction with `MREMAP_MAYMOVE` but does not unmap `old_address`.
210 /// Note that, in this case, `old_size` and `new_size` must be the same.
211 #[cfg(target_os = "linux")]
212 MREMAP_DONTUNMAP;
213 /// Place the mapping at exactly the address specified in `new_address`.
214 #[cfg(target_os = "netbsd")]
215 MAP_FIXED;
216 /// Allows to duplicate the mapping to be able to apply different flags on the copy.
217 #[cfg(target_os = "netbsd")]
218 MAP_REMAPDUP;
219 }
220}
221
222libc_enum! {
223 /// Usage information for a range of memory to allow for performance optimizations by the kernel.
224 ///
225 /// Used by [`madvise`].
226 #[repr(i32)]
227 #[non_exhaustive]
228 pub enum MmapAdvise {
229 /// No further special treatment. This is the default.
230 MADV_NORMAL,
231 /// Expect random page references.
232 MADV_RANDOM,
233 /// Expect sequential page references.
234 MADV_SEQUENTIAL,
235 /// Expect access in the near future.
236 MADV_WILLNEED,
237 /// Do not expect access in the near future.
238 MADV_DONTNEED,
239 /// Free up a given range of pages and its associated backing store.
240 #[cfg(linux_android)]
241 MADV_REMOVE,
242 /// Do not make pages in this range available to the child after a `fork(2)`.
243 #[cfg(linux_android)]
244 MADV_DONTFORK,
245 /// Undo the effect of `MADV_DONTFORK`.
246 #[cfg(linux_android)]
247 MADV_DOFORK,
248 /// Poison the given pages.
249 ///
250 /// Subsequent references to those pages are treated like hardware memory corruption.
251 #[cfg(linux_android)]
252 MADV_HWPOISON,
253 /// Enable Kernel Samepage Merging (KSM) for the given pages.
254 #[cfg(linux_android)]
255 MADV_MERGEABLE,
256 /// Undo the effect of `MADV_MERGEABLE`
257 #[cfg(linux_android)]
258 MADV_UNMERGEABLE,
259 /// Preserve the memory of each page but offline the original page.
260 #[cfg(any(target_os = "android",
261 all(target_os = "linux", any(
262 target_arch = "aarch64",
263 target_arch = "arm",
264 target_arch = "powerpc",
265 target_arch = "powerpc64",
266 target_arch = "s390x",
267 target_arch = "x86",
268 target_arch = "x86_64",
269 target_arch = "sparc64"))))]
270 MADV_SOFT_OFFLINE,
271 /// Enable Transparent Huge Pages (THP) for pages in the given range.
272 #[cfg(linux_android)]
273 MADV_HUGEPAGE,
274 /// Undo the effect of `MADV_HUGEPAGE`.
275 #[cfg(linux_android)]
276 MADV_NOHUGEPAGE,
277 /// Exclude the given range from a core dump.
278 #[cfg(linux_android)]
279 MADV_DONTDUMP,
280 /// Undo the effect of an earlier `MADV_DONTDUMP`.
281 #[cfg(linux_android)]
282 MADV_DODUMP,
283 /// Specify that the application no longer needs the pages in the given range.
284 #[cfg(not(any(target_os = "aix", target_os = "hurd", target_os = "cygwin", target_os = "redox")))]
285 MADV_FREE,
286 /// Request that the system not flush the current range to disk unless it needs to.
287 #[cfg(freebsdlike)]
288 MADV_NOSYNC,
289 /// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range.
290 #[cfg(freebsdlike)]
291 MADV_AUTOSYNC,
292 /// Region is not included in a core file.
293 #[cfg(freebsdlike)]
294 MADV_NOCORE,
295 /// Include region in a core file
296 #[cfg(freebsdlike)]
297 MADV_CORE,
298 /// This process should not be killed when swap space is exhausted.
299 #[cfg(any(target_os = "freebsd"))]
300 MADV_PROTECT,
301 /// Invalidate the hardware page table for the given region.
302 #[cfg(target_os = "dragonfly")]
303 MADV_INVAL,
304 /// Set the offset of the page directory page to `value` for the virtual page table.
305 #[cfg(target_os = "dragonfly")]
306 MADV_SETMAP,
307 /// Indicates that the application will not need the data in the given range.
308 #[cfg(apple_targets)]
309 MADV_ZERO_WIRED_PAGES,
310 /// Pages can be reused (by anyone).
311 #[cfg(apple_targets)]
312 MADV_FREE_REUSABLE,
313 /// Caller wants to reuse those pages.
314 #[cfg(apple_targets)]
315 MADV_FREE_REUSE,
316 // Darwin doesn't document this flag's behavior.
317 #[cfg(apple_targets)]
318 #[allow(missing_docs)]
319 MADV_CAN_REUSE,
320 /// Reclaim the address range when applicable.
321 #[cfg(linux_android)]
322 MADV_PAGEOUT,
323 /// Deactivate the address range when applicable.
324 #[cfg(linux_android)]
325 MADV_COLD,
326 /// After fork, the adress range is zero filled.
327 #[cfg(linux_android)]
328 MADV_WIPEONFORK,
329 /// Undo `MADV_WIPEONFORK` when it applied.
330 #[cfg(linux_android)]
331 MADV_KEEPONFORK,
332 /// Pre-load the address range for reading to reduce page-fault latency.
333 #[cfg(linux_android)]
334 MADV_POPULATE_READ,
335 /// Pre-fault the address range for writing to reduce page-fault
336 /// latency on subsequent writes.
337 #[cfg(linux_android)]
338 MADV_POPULATE_WRITE,
339 }
340}
341
342libc_bitflags! {
343 /// Configuration flags for [`msync`].
344 pub struct MsFlags: c_int {
345 /// Schedule an update but return immediately.
346 MS_ASYNC;
347 /// Invalidate all cached data.
348 MS_INVALIDATE;
349 /// Invalidate pages, but leave them mapped.
350 #[cfg(apple_targets)]
351 MS_KILLPAGES;
352 /// Deactivate pages, but leave them mapped.
353 #[cfg(apple_targets)]
354 MS_DEACTIVATE;
355 /// Perform an update and wait for it to complete.
356 MS_SYNC;
357 }
358}
359
360#[cfg(not(any(target_os = "haiku", target_os = "cygwin", target_os = "redox")))]
361libc_bitflags! {
362 /// Flags for [`mlockall`].
363 pub struct MlockAllFlags: c_int {
364 /// Lock pages that are currently mapped into the address space of the process.
365 MCL_CURRENT;
366 /// Lock pages which will become mapped into the address space of the process in the future.
367 MCL_FUTURE;
368 }
369}
370
371/// Locks all memory pages that contain part of the address range with `length`
372/// bytes starting at `addr`.
373///
374/// Locked pages never move to the swap area.
375///
376/// # Safety
377///
378/// `addr` must meet all the requirements described in the [`mlock(2)`] man page.
379///
380/// [`mlock(2)`]: https://man7.org/linux/man-pages/man2/mlock.2.html
381pub unsafe fn mlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
382 unsafe { Errno::result(libc::mlock(addr.as_ptr(), length)).map(drop) }
383}
384
385/// Unlocks all memory pages that contain part of the address range with
386/// `length` bytes starting at `addr`.
387///
388/// # Safety
389///
390/// `addr` must meet all the requirements described in the [`munlock(2)`] man
391/// page.
392///
393/// [`munlock(2)`]: https://man7.org/linux/man-pages/man2/munlock.2.html
394pub unsafe fn munlock(addr: NonNull<c_void>, length: size_t) -> Result<()> {
395 unsafe { Errno::result(libc::munlock(addr.as_ptr(), length)).map(drop) }
396}
397
398/// Locks all memory pages mapped into this process' address space.
399///
400/// Locked pages never move to the swap area. For more information, see [`mlockall(2)`].
401///
402/// [`mlockall(2)`]: https://man7.org/linux/man-pages/man2/mlockall.2.html
403#[cfg(not(any(target_os = "haiku", target_os = "cygwin", target_os = "redox")))]
404pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
405 unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
406}
407
408/// Unlocks all memory pages mapped into this process' address space.
409///
410/// For more information, see [`munlockall(2)`].
411///
412/// [`munlockall(2)`]: https://man7.org/linux/man-pages/man2/munlockall.2.html
413#[cfg(not(any(target_os = "haiku", target_os = "cygwin", target_os = "redox")))]
414pub fn munlockall() -> Result<()> {
415 unsafe { Errno::result(libc::munlockall()) }.map(drop)
416}
417
418/// Allocate memory, or map files or devices into memory
419///
420/// For anonymous mappings (`MAP_ANON`/`MAP_ANONYMOUS`), see [mmap_anonymous].
421///
422/// # Safety
423///
424/// See the [`mmap(2)`] man page for detailed requirements.
425///
426/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
427pub unsafe fn mmap<F: AsFd>(
428 addr: Option<NonZeroUsize>,
429 length: NonZeroUsize,
430 prot: ProtFlags,
431 flags: MapFlags,
432 f: F,
433 offset: off_t,
434) -> Result<NonNull<c_void>> {
435 let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void);
436
437 let fd = f.as_fd().as_raw_fd();
438 let ret = unsafe {
439 libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), fd, offset)
440 };
441
442 if std::ptr::eq(ret, libc::MAP_FAILED) {
443 Err(Errno::last())
444 } else {
445 // SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
446 // will be non-null here.
447 Ok(unsafe { NonNull::new_unchecked(ret) })
448 }
449}
450
451/// Create an anonymous memory mapping.
452///
453/// This function is a wrapper around [`mmap`]:
454/// `mmap(ptr, len, prot, MAP_ANONYMOUS | flags, -1, 0)`.
455///
456/// # Safety
457///
458/// See the [`mmap(2)`] man page for detailed requirements.
459///
460/// [`mmap(2)`]: https://man7.org/linux/man-pages/man2/mmap.2.html
461pub unsafe fn mmap_anonymous(
462 addr: Option<NonZeroUsize>,
463 length: NonZeroUsize,
464 prot: ProtFlags,
465 flags: MapFlags,
466) -> Result<NonNull<c_void>> {
467 let ptr = addr.map_or(std::ptr::null_mut(), |a| a.get() as *mut c_void);
468
469 let flags = MapFlags::MAP_ANONYMOUS | flags;
470 let ret = unsafe {
471 libc::mmap(ptr, length.into(), prot.bits(), flags.bits(), -1, 0)
472 };
473
474 if std::ptr::eq(ret, libc::MAP_FAILED) {
475 Err(Errno::last())
476 } else {
477 // SAFETY: `libc::mmap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
478 // will be non-null here.
479 Ok(unsafe { NonNull::new_unchecked(ret) })
480 }
481}
482
483/// Expands (or shrinks) an existing memory mapping, potentially moving it at
484/// the same time.
485///
486/// # Safety
487///
488/// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for
489/// detailed requirements.
490#[cfg(any(target_os = "linux", target_os = "netbsd"))]
491pub unsafe fn mremap(
492 addr: NonNull<c_void>,
493 old_size: size_t,
494 new_size: size_t,
495 flags: MRemapFlags,
496 new_address: Option<NonNull<c_void>>,
497) -> Result<NonNull<c_void>> {
498 #[cfg(target_os = "linux")]
499 let ret = unsafe {
500 libc::mremap(
501 addr.as_ptr(),
502 old_size,
503 new_size,
504 flags.bits(),
505 new_address
506 .map(NonNull::as_ptr)
507 .unwrap_or(std::ptr::null_mut()),
508 )
509 };
510 #[cfg(target_os = "netbsd")]
511 let ret = unsafe {
512 libc::mremap(
513 addr.as_ptr(),
514 old_size,
515 new_address
516 .map(NonNull::as_ptr)
517 .unwrap_or(std::ptr::null_mut()),
518 new_size,
519 flags.bits(),
520 )
521 };
522
523 if std::ptr::eq(ret, libc::MAP_FAILED) {
524 Err(Errno::last())
525 } else {
526 // SAFETY: `libc::mremap` returns a valid non-null pointer or `libc::MAP_FAILED`, thus `ret`
527 // will be non-null here.
528 Ok(unsafe { NonNull::new_unchecked(ret) })
529 }
530}
531
532/// remove a mapping
533///
534/// # Safety
535///
536/// `addr` must meet all the requirements described in the [`munmap(2)`] man
537/// page.
538///
539/// [`munmap(2)`]: https://man7.org/linux/man-pages/man2/munmap.2.html
540pub unsafe fn munmap(addr: NonNull<c_void>, len: size_t) -> Result<()> {
541 unsafe { Errno::result(libc::munmap(addr.as_ptr(), len)).map(drop) }
542}
543
544/// give advice about use of memory
545///
546/// # Safety
547///
548/// See the [`madvise(2)`] man page. Take special care when using
549/// [`MmapAdvise::MADV_FREE`].
550///
551/// [`madvise(2)`]: https://man7.org/linux/man-pages/man2/madvise.2.html
552#[allow(rustdoc::broken_intra_doc_links)] // For Hurd as `MADV_FREE` is not available on it
553pub unsafe fn madvise(
554 addr: NonNull<c_void>,
555 length: size_t,
556 advise: MmapAdvise,
557) -> Result<()> {
558 unsafe {
559 Errno::result(libc::madvise(addr.as_ptr(), length, advise as i32))
560 .map(drop)
561 }
562}
563
564/// Set protection of memory mapping.
565///
566/// See [`mprotect(3)`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
567/// details.
568///
569/// # Safety
570///
571/// Calls to `mprotect` are inherently unsafe, as changes to memory protections can lead to
572/// SIGSEGVs.
573///
574/// ```
575/// # use nix::libc::size_t;
576/// # use nix::sys::mman::{mmap_anonymous, mprotect, MapFlags, ProtFlags};
577/// # use std::ptr;
578/// # use std::os::unix::io::BorrowedFd;
579/// const ONE_K: size_t = 1024;
580/// let one_k_non_zero = std::num::NonZeroUsize::new(ONE_K).unwrap();
581/// let mut slice: &mut [u8] = unsafe {
582/// let mem = mmap_anonymous(None, one_k_non_zero, ProtFlags::PROT_NONE, MapFlags::MAP_PRIVATE)
583/// .unwrap();
584/// mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
585/// std::slice::from_raw_parts_mut(mem.as_ptr().cast(), ONE_K)
586/// };
587/// assert_eq!(slice[0], 0x00);
588/// slice[0] = 0xFF;
589/// assert_eq!(slice[0], 0xFF);
590/// ```
591pub unsafe fn mprotect(
592 addr: NonNull<c_void>,
593 length: size_t,
594 prot: ProtFlags,
595) -> Result<()> {
596 unsafe {
597 Errno::result(libc::mprotect(addr.as_ptr(), length, prot.bits()))
598 .map(drop)
599 }
600}
601
602/// synchronize a mapped region
603///
604/// # Safety
605///
606/// `addr` must meet all the requirements described in the [`msync(2)`] man
607/// page.
608///
609/// [`msync(2)`]: https://man7.org/linux/man-pages/man2/msync.2.html
610pub unsafe fn msync(
611 addr: NonNull<c_void>,
612 length: size_t,
613 flags: MsFlags,
614) -> Result<()> {
615 unsafe {
616 Errno::result(libc::msync(addr.as_ptr(), length, flags.bits()))
617 .map(drop)
618 }
619}
620
621#[cfg(not(target_os = "android"))]
622feature! {
623#![feature = "fs"]
624/// Creates and opens a new, or opens an existing, POSIX shared memory object.
625///
626/// For more information, see [`shm_open(3)`].
627///
628/// [`shm_open(3)`]: https://man7.org/linux/man-pages/man3/shm_open.3.html
629pub fn shm_open<P>(
630 name: &P,
631 flag: OFlag,
632 mode: Mode
633 ) -> Result<std::os::unix::io::OwnedFd>
634 where P: ?Sized + NixPath
635{
636 use std::os::unix::io::{FromRawFd, OwnedFd};
637
638 let ret = name.with_nix_path(|cstr| {
639 #[cfg(apple_targets)]
640 unsafe {
641 libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
642 }
643 #[cfg(not(apple_targets))]
644 unsafe {
645 libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
646 }
647 })?;
648
649 match ret {
650 -1 => Err(Errno::last()),
651 fd => Ok(unsafe{ OwnedFd::from_raw_fd(fd) })
652 }
653}
654}
655
656/// Performs the converse of [`shm_open`], removing an object previously created.
657///
658/// For more information, see [`shm_unlink(3)`].
659///
660/// [`shm_unlink(3)`]: https://man7.org/linux/man-pages/man3/shm_unlink.3.html
661#[cfg(not(target_os = "android"))]
662pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
663 let ret =
664 name.with_nix_path(|cstr| unsafe { libc::shm_unlink(cstr.as_ptr()) })?;
665
666 Errno::result(ret).map(drop)
667}