summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/imp/libc/mm/syscalls.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/rustix/src/imp/libc/mm/syscalls.rs')
-rw-r--r--vendor/rustix/src/imp/libc/mm/syscalls.rs218
1 files changed, 218 insertions, 0 deletions
diff --git a/vendor/rustix/src/imp/libc/mm/syscalls.rs b/vendor/rustix/src/imp/libc/mm/syscalls.rs
new file mode 100644
index 000000000..ee670b5bf
--- /dev/null
+++ b/vendor/rustix/src/imp/libc/mm/syscalls.rs
@@ -0,0 +1,218 @@
+//! libc syscalls supporting `rustix::mm`.
+
+use super::super::c;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::super::conv::syscall_ret_owned_fd;
+use super::super::conv::{borrowed_fd, no_fd, ret};
+use super::super::offset::libc_mmap;
+#[cfg(not(target_os = "redox"))]
+use super::types::Advice;
+#[cfg(target_os = "linux")]
+use super::types::MremapFlags;
+use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags};
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use super::types::{MlockFlags, UserfaultfdFlags};
+use crate::fd::BorrowedFd;
+use crate::io;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use crate::io::OwnedFd;
+
+#[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, flags.bits());
+
+ // `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 = libc_mmap(
+ ptr,
+ len,
+ prot.bits(),
+ flags.bits(),
+ 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 = libc_mmap(
+ ptr,
+ len,
+ prot.bits(),
+ flags.bits() | 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, flags.bits()))
+}
+
+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(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, flags.bits());
+ 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(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,
+ flags.bits() | 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(any(target_os = "android", target_os = "linux"))]
+#[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, flags.bits()))
+}
+
+/// # 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(any(target_os = "android", target_os = "linux"))]
+pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
+ syscall_ret_owned_fd(c::syscall(c::SYS_userfaultfd, flags.bits()))
+}