• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Memory management declarations.
2 
3 use crate::errno::Errno;
4 #[cfg(not(any(target_os = "android", target_env = "ohos")))]
5 use crate::NixPath;
6 use crate::Result;
7 #[cfg(not(any(target_os = "android", target_env = "ohos")))]
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::{os::unix::io::RawFd, num::NonZeroUsize};
12 
13 libc_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 
35 libc_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", any(target_env = "musl", target_env = "ohos"), 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"))]
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         #[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 
213 libc_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 
334 libc_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"))]
355 libc_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
mlock(addr: *const c_void, length: size_t) -> Result<()>375 pub 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
munlock(addr: *const c_void, length: size_t) -> Result<()>388 pub 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"))]
mlockall(flags: MlockAllFlags) -> Result<()>398 pub 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"))]
munlockall() -> Result<()>408 pub 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
mmap( addr: Option<NonZeroUsize>, length: NonZeroUsize, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t, ) -> Result<*mut c_void>419 pub 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"))]
mremap( addr: *mut c_void, old_size: size_t, new_size: size_t, flags: MRemapFlags, new_address: Option<*mut c_void>, ) -> Result<*mut c_void>449 pub 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
munmap(addr: *mut c_void, len: size_t) -> Result<()>488 pub 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
madvise( addr: *mut c_void, length: size_t, advise: MmapAdvise, ) -> Result<()>500 pub 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 /// ```
mprotect( addr: *mut c_void, length: size_t, prot: ProtFlags, ) -> Result<()>534 pub 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
msync( addr: *mut c_void, length: size_t, flags: MsFlags, ) -> Result<()>550 pub 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(any(target_os = "android", target_env = "ohos")))]
559 feature! {
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
566 pub 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(any(target_os = "android", target_env = "ohos")))]
shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()>594 pub 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 }
600