diff options
Diffstat (limited to 'vendor/rustix/src/backend/libc/mm')
| -rw-r--r-- | vendor/rustix/src/backend/libc/mm/mod.rs | 2 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/mm/syscalls.rs | 244 | ||||
| -rw-r--r-- | vendor/rustix/src/backend/libc/mm/types.rs | 477 | 
3 files changed, 723 insertions, 0 deletions
diff --git a/vendor/rustix/src/backend/libc/mm/mod.rs b/vendor/rustix/src/backend/libc/mm/mod.rs new file mode 100644 index 0000000..1e0181a --- /dev/null +++ b/vendor/rustix/src/backend/libc/mm/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod syscalls; +pub(crate) mod types; diff --git a/vendor/rustix/src/backend/libc/mm/syscalls.rs b/vendor/rustix/src/backend/libc/mm/syscalls.rs new file mode 100644 index 0000000..33bc9ca --- /dev/null +++ b/vendor/rustix/src/backend/libc/mm/syscalls.rs @@ -0,0 +1,244 @@ +//! libc syscalls supporting `rustix::mm`. + +#[cfg(not(target_os = "redox"))] +use super::types::Advice; +#[cfg(any(linux_kernel, freebsdlike, netbsdlike))] +use super::types::MlockAllFlags; +#[cfg(any(target_os = "emscripten", target_os = "linux"))] +use super::types::MremapFlags; +use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags}; +#[cfg(linux_kernel)] +use super::types::{MlockFlags, UserfaultfdFlags}; +use crate::backend::c; +#[cfg(linux_kernel)] +use crate::backend::conv::ret_owned_fd; +use crate::backend::conv::{borrowed_fd, no_fd, ret}; +use crate::fd::BorrowedFd; +#[cfg(linux_kernel)] +use crate::fd::OwnedFd; +use crate::io; + +#[cfg(not(target_os = "redox"))] +pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> { +    // On Linux platforms, `MADV_DONTNEED` has the same value as +    // `POSIX_MADV_DONTNEED` but different behavior. We remap it to a different +    // value, and check for it here. +    #[cfg(target_os = "linux")] +    if let Advice::LinuxDontNeed = advice { +        return unsafe { ret(c::madvise(addr, len, c::MADV_DONTNEED)) }; +    } + +    #[cfg(not(target_os = "android"))] +    { +        let err = unsafe { c::posix_madvise(addr, len, advice as c::c_int) }; + +        // `posix_madvise` returns its error status rather than using `errno`. +        if err == 0 { +            Ok(()) +        } else { +            Err(io::Errno(err)) +        } +    } + +    #[cfg(target_os = "android")] +    { +        if let Advice::DontNeed = advice { +            // Do nothing. Linux's `MADV_DONTNEED` isn't the same as +            // `POSIX_MADV_DONTNEED`, so just discard `MADV_DONTNEED`. +            Ok(()) +        } else { +            unsafe { ret(c::madvise(addr, len, advice as c::c_int)) } +        } +    } +} + +pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> { +    let err = c::msync(addr, len, bitflags_bits!(flags)); + +    // `msync` returns its error status rather than using `errno`. +    if err == 0 { +        Ok(()) +    } else { +        Err(io::Errno(err)) +    } +} + +/// # Safety +/// +/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working +/// with memory pointed to by raw pointers is unsafe. +pub(crate) unsafe fn mmap( +    ptr: *mut c::c_void, +    len: usize, +    prot: ProtFlags, +    flags: MapFlags, +    fd: BorrowedFd<'_>, +    offset: u64, +) -> io::Result<*mut c::c_void> { +    let res = c::mmap( +        ptr, +        len, +        bitflags_bits!(prot), +        bitflags_bits!(flags), +        borrowed_fd(fd), +        offset as i64, +    ); +    if res == c::MAP_FAILED { +        Err(io::Errno::last_os_error()) +    } else { +        Ok(res) +    } +} + +/// # Safety +/// +/// `mmap` is primarily unsafe due to the `addr` parameter, as anything working +/// with memory pointed to by raw pointers is unsafe. +pub(crate) unsafe fn mmap_anonymous( +    ptr: *mut c::c_void, +    len: usize, +    prot: ProtFlags, +    flags: MapFlags, +) -> io::Result<*mut c::c_void> { +    let res = c::mmap( +        ptr, +        len, +        bitflags_bits!(prot), +        bitflags_bits!(flags | MapFlags::from_bits_retain(bitcast!(c::MAP_ANONYMOUS))), +        no_fd(), +        0, +    ); +    if res == c::MAP_FAILED { +        Err(io::Errno::last_os_error()) +    } else { +        Ok(res) +    } +} + +pub(crate) unsafe fn mprotect( +    ptr: *mut c::c_void, +    len: usize, +    flags: MprotectFlags, +) -> io::Result<()> { +    ret(c::mprotect(ptr, len, bitflags_bits!(flags))) +} + +pub(crate) unsafe fn munmap(ptr: *mut c::c_void, len: usize) -> io::Result<()> { +    ret(c::munmap(ptr, len)) +} + +/// # Safety +/// +/// `mremap` is primarily unsafe due to the `old_address` parameter, as +/// anything working with memory pointed to by raw pointers is unsafe. +#[cfg(any(target_os = "emscripten", target_os = "linux"))] +pub(crate) unsafe fn mremap( +    old_address: *mut c::c_void, +    old_size: usize, +    new_size: usize, +    flags: MremapFlags, +) -> io::Result<*mut c::c_void> { +    let res = c::mremap(old_address, old_size, new_size, bitflags_bits!(flags)); +    if res == c::MAP_FAILED { +        Err(io::Errno::last_os_error()) +    } else { +        Ok(res) +    } +} + +/// # Safety +/// +/// `mremap_fixed` is primarily unsafe due to the `old_address` and +/// `new_address` parameters, as anything working with memory pointed to by raw +/// pointers is unsafe. +#[cfg(any(target_os = "emscripten", target_os = "linux"))] +pub(crate) unsafe fn mremap_fixed( +    old_address: *mut c::c_void, +    old_size: usize, +    new_size: usize, +    flags: MremapFlags, +    new_address: *mut c::c_void, +) -> io::Result<*mut c::c_void> { +    let res = c::mremap( +        old_address, +        old_size, +        new_size, +        bitflags_bits!(flags | MremapFlags::from_bits_retain(bitcast!(c::MAP_FIXED))), +        new_address, +    ); +    if res == c::MAP_FAILED { +        Err(io::Errno::last_os_error()) +    } else { +        Ok(res) +    } +} + +/// # Safety +/// +/// `mlock` operates on raw pointers and may round out to the nearest page +/// boundaries. +#[inline] +pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> { +    ret(c::mlock(addr, length)) +} + +/// # Safety +/// +/// `mlock_with` operates on raw pointers and may round out to the nearest page +/// boundaries. +#[cfg(linux_kernel)] +#[inline] +pub(crate) unsafe fn mlock_with( +    addr: *mut c::c_void, +    length: usize, +    flags: MlockFlags, +) -> io::Result<()> { +    weak_or_syscall! { +        fn mlock2( +            addr: *const c::c_void, +            len: c::size_t, +            flags: c::c_int +        ) via SYS_mlock2 -> c::c_int +    } + +    ret(mlock2(addr, length, bitflags_bits!(flags))) +} + +/// # Safety +/// +/// `munlock` operates on raw pointers and may round out to the nearest page +/// boundaries. +#[inline] +pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> { +    ret(c::munlock(addr, length)) +} + +#[cfg(linux_kernel)] +pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> { +    syscall! { +        fn userfaultfd( +            flags: c::c_int +        ) via SYS_userfaultfd -> c::c_int +    } +    ret_owned_fd(userfaultfd(bitflags_bits!(flags))) +} + +/// Locks all pages mapped into the address space of the calling process. +/// +/// This includes the pages of the code, data, and stack segment, as well as +/// shared libraries, user space kernel data, shared memory, and memory-mapped +/// files. All mapped pages are guaranteed to be resident in RAM when the call +/// returns successfully; the pages are guaranteed to stay in RAM until later +/// unlocked. +#[inline] +#[cfg(any(linux_kernel, freebsdlike, netbsdlike))] +pub(crate) fn mlockall(flags: MlockAllFlags) -> io::Result<()> { +    unsafe { ret(c::mlockall(bitflags_bits!(flags))) } +} + +/// Unlocks all pages mapped into the address space of the calling process. +#[inline] +#[cfg(any(linux_kernel, freebsdlike, netbsdlike))] +pub(crate) fn munlockall() -> io::Result<()> { +    unsafe { ret(c::munlockall()) } +} diff --git a/vendor/rustix/src/backend/libc/mm/types.rs b/vendor/rustix/src/backend/libc/mm/types.rs new file mode 100644 index 0000000..a4aa3e2 --- /dev/null +++ b/vendor/rustix/src/backend/libc/mm/types.rs @@ -0,0 +1,477 @@ +use crate::backend::c; +use bitflags::bitflags; + +bitflags! { +    /// `PROT_*` flags for use with [`mmap`]. +    /// +    /// For `PROT_NONE`, use `ProtFlags::empty()`. +    /// +    /// [`mmap`]: crate::mm::mmap +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct ProtFlags: u32 { +        /// `PROT_READ` +        const READ = bitcast!(c::PROT_READ); +        /// `PROT_WRITE` +        const WRITE = bitcast!(c::PROT_WRITE); +        /// `PROT_EXEC` +        const EXEC = bitcast!(c::PROT_EXEC); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +bitflags! { +    /// `PROT_*` flags for use with [`mprotect`]. +    /// +    /// For `PROT_NONE`, use `MprotectFlags::empty()`. +    /// +    /// [`mprotect`]: crate::mm::mprotect +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct MprotectFlags: u32 { +        /// `PROT_READ` +        const READ = bitcast!(c::PROT_READ); +        /// `PROT_WRITE` +        const WRITE = bitcast!(c::PROT_WRITE); +        /// `PROT_EXEC` +        const EXEC = bitcast!(c::PROT_EXEC); +        /// `PROT_GROWSUP` +        #[cfg(linux_kernel)] +        const GROWSUP = bitcast!(c::PROT_GROWSUP); +        /// `PROT_GROWSDOWN` +        #[cfg(linux_kernel)] +        const GROWSDOWN = bitcast!(c::PROT_GROWSDOWN); +        /// `PROT_SEM` +        #[cfg(linux_kernel)] +        const SEM = linux_raw_sys::general::PROT_SEM; +        /// `PROT_BTI` +        #[cfg(all(linux_kernel, target_arch = "aarch64"))] +        const BTI = linux_raw_sys::general::PROT_BTI; +        /// `PROT_MTE` +        #[cfg(all(linux_kernel, target_arch = "aarch64"))] +        const MTE = linux_raw_sys::general::PROT_MTE; +        /// `PROT_SAO` +        #[cfg(all(linux_kernel, any(target_arch = "powerpc", target_arch = "powerpc64")))] +        const SAO = linux_raw_sys::general::PROT_SAO; +        /// `PROT_ADI` +        #[cfg(all(linux_kernel, any(target_arch = "sparc", target_arch = "sparc64")))] +        const ADI = linux_raw_sys::general::PROT_ADI; + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +bitflags! { +    /// `MAP_*` flags for use with [`mmap`]. +    /// +    /// For `MAP_ANONYMOUS` (aka `MAP_ANON`), see [`mmap_anonymous`]. +    /// +    /// [`mmap`]: crate::mm::mmap +    /// [`mmap_anonymous`]: crates::mm::mmap_anonymous +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct MapFlags: u32 { +        /// `MAP_SHARED` +        const SHARED = bitcast!(c::MAP_SHARED); +        /// `MAP_SHARED_VALIDATE` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "android", +            target_os = "emscripten", +            target_os = "fuchsia", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const SHARED_VALIDATE = bitcast!(c::MAP_SHARED_VALIDATE); +        /// `MAP_PRIVATE` +        const PRIVATE = bitcast!(c::MAP_PRIVATE); +        /// `MAP_DENYWRITE` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const DENYWRITE = bitcast!(c::MAP_DENYWRITE); +        /// `MAP_FIXED` +        const FIXED = bitcast!(c::MAP_FIXED); +        /// `MAP_FIXED_NOREPLACE` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "android", +            target_os = "emscripten", +            target_os = "fuchsia", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const FIXED_NOREPLACE = bitcast!(c::MAP_FIXED_NOREPLACE); +        /// `MAP_GROWSDOWN` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const GROWSDOWN = bitcast!(c::MAP_GROWSDOWN); +        /// `MAP_HUGETLB` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const HUGETLB = bitcast!(c::MAP_HUGETLB); +        /// `MAP_HUGE_2MB` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "android", +            target_os = "emscripten", +            target_os = "fuchsia", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const HUGE_2MB = bitcast!(c::MAP_HUGE_2MB); +        /// `MAP_HUGE_1GB` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "android", +            target_os = "emscripten", +            target_os = "fuchsia", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const HUGE_1GB = bitcast!(c::MAP_HUGE_1GB); +        /// `MAP_LOCKED` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const LOCKED = bitcast!(c::MAP_LOCKED); +        /// `MAP_NOCORE` +        #[cfg(freebsdlike)] +        const NOCORE = bitcast!(c::MAP_NOCORE); +        /// `MAP_NORESERVE` +        #[cfg(not(any( +            freebsdlike, +            target_os = "aix", +            target_os = "nto", +            target_os = "redox", +        )))] +        const NORESERVE = bitcast!(c::MAP_NORESERVE); +        /// `MAP_NOSYNC` +        #[cfg(freebsdlike)] +        const NOSYNC = bitcast!(c::MAP_NOSYNC); +        /// `MAP_POPULATE` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +        )))] +        const POPULATE = bitcast!(c::MAP_POPULATE); +        /// `MAP_STACK` +        #[cfg(not(any( +            apple, +            solarish, +            target_os = "aix", +            target_os = "dragonfly", +            target_os = "haiku", +            target_os = "netbsd", +            target_os = "redox", +        )))] +        const STACK = bitcast!(c::MAP_STACK); +        /// `MAP_PREFAULT_READ` +        #[cfg(target_os = "freebsd")] +        const PREFAULT_READ = bitcast!(c::MAP_PREFAULT_READ); +        /// `MAP_SYNC` +        #[cfg(not(any( +            bsd, +            solarish, +            target_os = "aix", +            target_os = "android", +            target_os = "emscripten", +            target_os = "fuchsia", +            target_os = "haiku", +            target_os = "nto", +            target_os = "redox", +            all( +                linux_kernel, +                any(target_arch = "mips", target_arch = "mips32r6", target_arch = "mips64", target_arch = "mips64r6"), +            ) +        )))] +        const SYNC = bitcast!(c::MAP_SYNC); +        /// `MAP_UNINITIALIZED` +        #[cfg(any())] +        const UNINITIALIZED = bitcast!(c::MAP_UNINITIALIZED); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +#[cfg(any(target_os = "emscripten", target_os = "linux"))] +bitflags! { +    /// `MREMAP_*` flags for use with [`mremap`]. +    /// +    /// For `MREMAP_FIXED`, see [`mremap_fixed`]. +    /// +    /// [`mremap`]: crate::mm::mremap +    /// [`mremap_fixed`]: crate::mm::mremap_fixed +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct MremapFlags: u32 { +        /// `MREMAP_MAYMOVE` +        const MAYMOVE = bitcast!(c::MREMAP_MAYMOVE); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +bitflags! { +    /// `MS_*` flags for use with [`msync`]. +    /// +    /// [`msync`]: crate::mm::msync +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct MsyncFlags: u32 { +        /// `MS_SYNC`—Requests an update and waits for it to complete. +        const SYNC = bitcast!(c::MS_SYNC); +        /// `MS_ASYNC`—Specifies that an update be scheduled, but the call +        /// returns immediately. +        const ASYNC = bitcast!(c::MS_ASYNC); +        /// `MS_INVALIDATE`—Asks to invalidate other mappings of the same +        /// file (so that they can be updated with the fresh values just +        /// written). +        const INVALIDATE = bitcast!(c::MS_INVALIDATE); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +#[cfg(linux_kernel)] +bitflags! { +    /// `MLOCK_*` flags for use with [`mlock_with`]. +    /// +    /// [`mlock_with`]: crate::mm::mlock_with +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct MlockFlags: u32 { +        /// `MLOCK_ONFAULT` +        const ONFAULT = bitcast!(c::MLOCK_ONFAULT); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +/// `POSIX_MADV_*` constants for use with [`madvise`]. +/// +/// [`madvise`]: crate::mm::madvise +#[cfg(not(target_os = "redox"))] +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[repr(u32)] +#[non_exhaustive] +pub enum Advice { +    /// `POSIX_MADV_NORMAL` +    #[cfg(not(any(target_os = "android", target_os = "haiku")))] +    Normal = bitcast!(c::POSIX_MADV_NORMAL), + +    /// `POSIX_MADV_NORMAL` +    #[cfg(any(target_os = "android", target_os = "haiku"))] +    Normal = bitcast!(c::MADV_NORMAL), + +    /// `POSIX_MADV_SEQUENTIAL` +    #[cfg(not(any(target_os = "android", target_os = "haiku")))] +    Sequential = bitcast!(c::POSIX_MADV_SEQUENTIAL), + +    /// `POSIX_MADV_SEQUENTIAL` +    #[cfg(any(target_os = "android", target_os = "haiku"))] +    Sequential = bitcast!(c::MADV_SEQUENTIAL), + +    /// `POSIX_MADV_RANDOM` +    #[cfg(not(any(target_os = "android", target_os = "haiku")))] +    Random = bitcast!(c::POSIX_MADV_RANDOM), + +    /// `POSIX_MADV_RANDOM` +    #[cfg(any(target_os = "android", target_os = "haiku"))] +    Random = bitcast!(c::MADV_RANDOM), + +    /// `POSIX_MADV_WILLNEED` +    #[cfg(not(any(target_os = "android", target_os = "haiku")))] +    WillNeed = bitcast!(c::POSIX_MADV_WILLNEED), + +    /// `POSIX_MADV_WILLNEED` +    #[cfg(any(target_os = "android", target_os = "haiku"))] +    WillNeed = bitcast!(c::MADV_WILLNEED), + +    /// `POSIX_MADV_DONTNEED` +    #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "haiku")))] +    DontNeed = bitcast!(c::POSIX_MADV_DONTNEED), + +    /// `POSIX_MADV_DONTNEED` +    #[cfg(any(target_os = "android", target_os = "haiku"))] +    DontNeed = bitcast!(i32::MAX - 1), + +    /// `MADV_DONTNEED` +    // `MADV_DONTNEED` has the same value as `POSIX_MADV_DONTNEED`. We don't +    // have a separate `posix_madvise` from `madvise`, so we expose a special +    // value which we special-case. +    #[cfg(target_os = "linux")] +    LinuxDontNeed = bitcast!(i32::MAX), + +    /// `MADV_DONTNEED` +    #[cfg(target_os = "android")] +    LinuxDontNeed = bitcast!(c::MADV_DONTNEED), +    /// `MADV_FREE` +    #[cfg(linux_kernel)] +    LinuxFree = bitcast!(c::MADV_FREE), +    /// `MADV_REMOVE` +    #[cfg(linux_kernel)] +    LinuxRemove = bitcast!(c::MADV_REMOVE), +    /// `MADV_DONTFORK` +    #[cfg(linux_kernel)] +    LinuxDontFork = bitcast!(c::MADV_DONTFORK), +    /// `MADV_DOFORK` +    #[cfg(linux_kernel)] +    LinuxDoFork = bitcast!(c::MADV_DOFORK), +    /// `MADV_HWPOISON` +    #[cfg(linux_kernel)] +    LinuxHwPoison = bitcast!(c::MADV_HWPOISON), +    /// `MADV_SOFT_OFFLINE` +    #[cfg(all( +        linux_kernel, +        not(any( +            target_arch = "mips", +            target_arch = "mips32r6", +            target_arch = "mips64", +            target_arch = "mips64r6" +        )) +    ))] +    LinuxSoftOffline = bitcast!(c::MADV_SOFT_OFFLINE), +    /// `MADV_MERGEABLE` +    #[cfg(linux_kernel)] +    LinuxMergeable = bitcast!(c::MADV_MERGEABLE), +    /// `MADV_UNMERGEABLE` +    #[cfg(linux_kernel)] +    LinuxUnmergeable = bitcast!(c::MADV_UNMERGEABLE), +    /// `MADV_HUGEPAGE` +    #[cfg(linux_kernel)] +    LinuxHugepage = bitcast!(c::MADV_HUGEPAGE), +    /// `MADV_NOHUGEPAGE` +    #[cfg(linux_kernel)] +    LinuxNoHugepage = bitcast!(c::MADV_NOHUGEPAGE), +    /// `MADV_DONTDUMP` (since Linux 3.4) +    #[cfg(linux_kernel)] +    LinuxDontDump = bitcast!(c::MADV_DONTDUMP), +    /// `MADV_DODUMP` (since Linux 3.4) +    #[cfg(linux_kernel)] +    LinuxDoDump = bitcast!(c::MADV_DODUMP), +    /// `MADV_WIPEONFORK` (since Linux 4.14) +    #[cfg(linux_kernel)] +    LinuxWipeOnFork = bitcast!(c::MADV_WIPEONFORK), +    /// `MADV_KEEPONFORK` (since Linux 4.14) +    #[cfg(linux_kernel)] +    LinuxKeepOnFork = bitcast!(c::MADV_KEEPONFORK), +    /// `MADV_COLD` (since Linux 5.4) +    #[cfg(linux_kernel)] +    LinuxCold = bitcast!(c::MADV_COLD), +    /// `MADV_PAGEOUT` (since Linux 5.4) +    #[cfg(linux_kernel)] +    LinuxPageOut = bitcast!(c::MADV_PAGEOUT), +    /// `MADV_POPULATE_READ` (since Linux 5.14) +    #[cfg(linux_kernel)] +    LinuxPopulateRead = bitcast!(c::MADV_POPULATE_READ), +    /// `MADV_POPULATE_WRITE` (since Linux 5.14) +    #[cfg(linux_kernel)] +    LinuxPopulateWrite = bitcast!(c::MADV_POPULATE_WRITE), +    /// `MADV_DONTNEED_LOCKED` (since Linux 5.18) +    #[cfg(linux_kernel)] +    LinuxDontneedLocked = bitcast!(c::MADV_DONTNEED_LOCKED), +} + +#[cfg(target_os = "emscripten")] +#[allow(non_upper_case_globals)] +impl Advice { +    /// `POSIX_MADV_DONTNEED` +    pub const DontNeed: Self = Self::Normal; +} + +#[cfg(linux_kernel)] +bitflags! { +    /// `O_*` flags for use with [`userfaultfd`]. +    /// +    /// [`userfaultfd`]: crate::mm::userfaultfd +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct UserfaultfdFlags: u32 { +        /// `O_CLOEXEC` +        const CLOEXEC = bitcast!(c::O_CLOEXEC); +        /// `O_NONBLOCK` +        const NONBLOCK = bitcast!(c::O_NONBLOCK); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +} + +#[cfg(any(linux_kernel, freebsdlike, netbsdlike))] +bitflags! { +    /// `MCL_*` flags for use with [`mlockall`]. +    /// +    /// [`mlockall`]: crate::mm::mlockall +    #[repr(transparent)] +    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] +    pub struct MlockAllFlags: u32 { +        /// Used together with `MCL_CURRENT`, `MCL_FUTURE`, or both. Mark all +        /// current (with `MCL_CURRENT`) or future (with `MCL_FUTURE`) mappings +        /// to lock pages when they are faulted in. When used with +        /// `MCL_CURRENT`, all present pages are locked, but `mlockall` will +        /// not fault in non-present pages. When used with `MCL_FUTURE`, all +        /// future mappings will be marked to lock pages when they are faulted +        /// in, but they will not be populated by the lock when the mapping is +        /// created. `MCL_ONFAULT` must be used with either `MCL_CURRENT` or +        /// `MCL_FUTURE` or both. +        #[cfg(linux_kernel)] +        const ONFAULT = bitcast!(libc::MCL_ONFAULT); +        /// Lock all pages which will become mapped into the address space of +        /// the process in the future. These could be, for instance, new pages +        /// required by a growing heap and stack as well as new memory-mapped +        /// files or shared memory regions. +        const FUTURE = bitcast!(libc::MCL_FUTURE); +        /// Lock all pages which are currently mapped into the address space of +        /// the process. +        const CURRENT = bitcast!(libc::MCL_CURRENT); + +        /// <https://docs.rs/bitflags/*/bitflags/#externally-defined-flags> +        const _ = !0; +    } +}  | 
