Skip to content

Commit

Permalink
Add mlockall and munlockall
Browse files Browse the repository at this point in the history
  • Loading branch information
newpavlov committed Oct 9, 2023
1 parent 1a9d129 commit eefd082
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 2 deletions.
42 changes: 42 additions & 0 deletions src/backend/libc/mm/syscalls.rs
Expand Up @@ -2,6 +2,15 @@

#[cfg(not(target_os = "redox"))]
use super::types::Advice;
#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
use super::types::MlockFlags;
#[cfg(any(target_os = "emscripten", target_os = "linux"))]
use super::types::MremapFlags;
use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags};
Expand Down Expand Up @@ -220,3 +229,36 @@ pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd>
}
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,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
pub(crate) fn mlockall(flags: MlockFlags) -> 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,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
pub(crate) fn munlockall() -> io::Result<()> {
unsafe { ret(c::munlockall()) }
}
27 changes: 27 additions & 0 deletions src/backend/libc/mm/types.rs
Expand Up @@ -442,3 +442,30 @@ bitflags! {
const _ = !0;
}
}

#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
bitflags! {
/// `MCL_*` flags for use with [`mlockall`].
///
/// [`mlockall`]: crate::mm::mlockall
pub struct MlockallFlags: i32 {
// libc doesn't define `MCL_ONFAULT` yet.
// const ONFAULT = 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 = libc::MCL_FUTURE;
/// Lock all pages which are currently mapped into the address
/// space of the process.
const CURRENT = libc::MCL_CURRENT;
}
}
45 changes: 43 additions & 2 deletions src/backend/linux_raw/mm/syscalls.rs
Expand Up @@ -6,9 +6,17 @@
#![allow(unsafe_code)]
#![allow(clippy::undocumented_unsafe_blocks)]

#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
use super::types::MlockFlags;
use super::types::{
Advice, MapFlags, MlockFlags, MprotectFlags, MremapFlags, MsyncFlags, ProtFlags,
UserfaultfdFlags,
Advice, MapFlags, MprotectFlags, MremapFlags, MsyncFlags, ProtFlags, UserfaultfdFlags,
};
use crate::backend::c;
#[cfg(target_pointer_width = "64")]
Expand Down Expand Up @@ -210,3 +218,36 @@ pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<
pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
ret_owned_fd(syscall_readonly!(__NR_userfaultfd, 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,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
pub(crate) fn mlockall(flags: MlockFlags) -> io::Result<()> {
unsafe { ret(syscall_readonly!(__NR_mlockall, flags)) }
}

/// Unlocks all pages mapped into the address space of the calling process.
#[inline]
#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
pub(crate) fn munlockall() -> io::Result<()> {
unsafe { ret(syscall_readonly!(__NR_munlockall)) }
}
36 changes: 36 additions & 0 deletions src/backend/linux_raw/mm/types.rs
Expand Up @@ -262,3 +262,39 @@ bitflags! {
const _ = !0;
}
}

#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
bitflags! {
/// `MCL_*` flags for use with [`mlockall`].
///
/// [`mlockall`]: crate::mm::mlockall
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.
const ONFAULT = linux_raw_sys::general::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 = linux_raw_sys::general::MCL_FUTURE;
/// Lock all pages which are currently mapped into the address
/// space of the process.
const CURRENT = linux_raw_sys::general::MCL_CURRENT;
}
}
70 changes: 70 additions & 0 deletions src/mm/mmap.rs
Expand Up @@ -340,3 +340,73 @@ pub unsafe fn mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io:
pub unsafe fn munlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
backend::mm::syscalls::munlock(ptr, len)
}

/// 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.
///
/// # References
/// - [POSIX]
/// - [Linux]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlockall.html
/// [Linux]: https://man7.org/linux/man-pages/man2/mlockall.2.html
/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mlockall&sektion=2
/// [NetBSD]: https://man.netbsd.org/mlockall.2
/// [OpenBSD]: https://man.openbsd.org/mlockall.2
/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mlockall&section=2
/// [illumos]: https://illumos.org/man/3C/mlockall
/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlockall
#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
pub fn mlockall(flags: MlockFlags) -> io::Result<()> {
backend::mm::syscalls::mlockall(flags)
}

/// Unlocks all pages mapped into the address space of the calling process.
///
/// # References
/// - [POSIX]
/// - [Linux]
/// - [FreeBSD]
/// - [NetBSD]
/// - [OpenBSD]
/// - [DragonFly BSD]
/// - [illumos]
/// - [glibc]
///
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlockall.html
/// [Linux]: https://man7.org/linux/man-pages/man2/munlockall.2.html
/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munlockall&sektion=2
/// [NetBSD]: https://man.netbsd.org/munlockall.2
/// [OpenBSD]: https://man.openbsd.org/munlockall.2
/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munlockall&section=2
/// [illumos]: https://illumos.org/man/3C/munlockall
/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-munlockall
#[inline]
#[cfg(any(
linux_kernel,
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "illumos",
))]
pub fn munlockall() -> io::Result<()> {
backend::mm::syscalls::munlockall()
}

0 comments on commit eefd082

Please sign in to comment.