1//! Memory management declarations. 2 3use crate::errno::Errno; 4#[cfg(not(any(target_os = "android", target_env = "ohos")))] 5use crate::NixPath; 6use crate::Result; 7#[cfg(not(any(target_os = "android", target_env = "ohos")))] 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", 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"))] 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(any(target_os = "android", target_env = "ohos")))] 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(any(target_os = "android", target_env = "ohos")))] 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} 600