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}