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