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