aboutsummaryrefslogtreecommitdiff
path: root/vendor/rustix/src/backend/libc/mm/syscalls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/backend/libc/mm/syscalls.rs')
-rw-r--r--vendor/rustix/src/backend/libc/mm/syscalls.rs244
1 files changed, 244 insertions, 0 deletions
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()) }
+}