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