1//! The `mmap` API.
2//!
3//! # Safety
4//!
5//! `mmap` and related functions manipulate raw pointers and have special
6//! semantics and are wildly unsafe.
7#![allow(unsafe_code)]
8
9use crate::{backend, io};
10use backend::fd::AsFd;
11use core::ffi::c_void;
12
13#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
14pub use backend::mm::types::MlockAllFlags;
15#[cfg(linux_kernel)]
16pub use backend::mm::types::MlockFlags;
17#[cfg(any(target_os = "emscripten", target_os = "linux"))]
18pub use backend::mm::types::MremapFlags;
19pub use backend::mm::types::{MapFlags, MprotectFlags, ProtFlags};
20
21impl MapFlags {
22 /// Create `MAP_HUGETLB` with provided size of huge page.
23 ///
24 /// Under the hood it computes
25 /// `MAP_HUGETLB | (huge_page_size_log2 << MAP_HUGE_SHIFT)`.
26 /// `huge_page_size_log2` denotes logarithm of huge page size to use and
27 /// should be between 16 and 63 (inclusive).
28 ///
29 /// ```
30 /// use rustix::mm::MapFlags;
31 ///
32 /// let f = MapFlags::hugetlb_with_size_log2(30).unwrap();
33 /// assert_eq!(f, MapFlags::HUGETLB | MapFlags::HUGE_1GB);
34 /// ```
35 #[cfg(linux_kernel)]
36 pub const fn hugetlb_with_size_log2(huge_page_size_log2: u32) -> Option<Self> {
37 use linux_raw_sys::general::{MAP_HUGETLB, MAP_HUGE_SHIFT};
38 if 16 <= huge_page_size_log2 && huge_page_size_log2 <= 63 {
39 let bits = MAP_HUGETLB | (huge_page_size_log2 << MAP_HUGE_SHIFT);
40 Self::from_bits(bits)
41 } else {
42 None
43 }
44 }
45}
46
47/// `mmap(ptr, len, prot, flags, fd, offset)`—Create a file-backed memory
48/// mapping.
49///
50/// For anonymous mappings (`MAP_ANON`/`MAP_ANONYMOUS`), see
51/// [`mmap_anonymous`].
52///
53/// # Safety
54///
55/// Raw pointers and lots of special semantics.
56///
57/// # References
58/// - [POSIX]
59/// - [Linux]
60/// - [Apple]
61/// - [FreeBSD]
62/// - [NetBSD]
63/// - [OpenBSD]
64/// - [DragonFly BSD]
65/// - [illumos]
66/// - [glibc]
67///
68/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
69/// [Linux]: https://man7.org/linux/man-pages/man2/mmap.2.html
70/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mmap.2.html
71/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mmap&sektion=2
72/// [NetBSD]: https://man.netbsd.org/mmap.2
73/// [OpenBSD]: https://man.openbsd.org/mmap.2
74/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mmap&section=2
75/// [illumos]: https://illumos.org/man/2/mmap
76/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html#index-mmap
77#[inline]
78pub unsafe fn mmap<Fd: AsFd>(
79 ptr: *mut c_void,
80 len: usize,
81 prot: ProtFlags,
82 flags: MapFlags,
83 fd: Fd,
84 offset: u64,
85) -> io::Result<*mut c_void> {
86 backend::mm::syscalls::mmap(addr:ptr, length:len, prot, flags, fd.as_fd(), offset)
87}
88
89/// `mmap(ptr, len, prot, MAP_ANONYMOUS | flags, -1, 0)`—Create an anonymous
90/// memory mapping.
91///
92/// For file-backed mappings, see [`mmap`].
93///
94/// # Safety
95///
96/// Raw pointers and lots of special semantics.
97///
98/// # References
99/// - [POSIX]
100/// - [Linux]
101/// - [Apple]
102/// - [FreeBSD]
103/// - [NetBSD]
104/// - [OpenBSD]
105/// - [DragonFly BSD]
106/// - [illumos]
107/// - [glibc]
108///
109/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html
110/// [Linux]: https://man7.org/linux/man-pages/man2/mmap.2.html
111/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mmap.2.html
112/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mmap&sektion=2
113/// [NetBSD]: https://man.netbsd.org/mmap.2
114/// [OpenBSD]: https://man.openbsd.org/mmap.2
115/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mmap&section=2
116/// [illumos]: https://illumos.org/man/2/mmap
117/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html#index-mmap
118#[inline]
119#[doc(alias = "mmap")]
120pub unsafe fn mmap_anonymous(
121 ptr: *mut c_void,
122 len: usize,
123 prot: ProtFlags,
124 flags: MapFlags,
125) -> io::Result<*mut c_void> {
126 backend::mm::syscalls::mmap_anonymous(addr:ptr, length:len, prot, flags)
127}
128
129/// `munmap(ptr, len)`—Remove a memory mapping.
130///
131/// # Safety
132///
133/// Raw pointers and lots of special semantics.
134///
135/// # References
136/// - [POSIX]
137/// - [Linux]
138/// - [Apple]
139/// - [FreeBSD]
140/// - [NetBSD]
141/// - [OpenBSD]
142/// - [DragonFly BSD]
143/// - [illumos]
144/// - [glibc]
145///
146/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html
147/// [Linux]: https://man7.org/linux/man-pages/man2/munmap.2.html
148/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/munmap.2.html
149/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munmap&sektion=2
150/// [NetBSD]: https://man.netbsd.org/munmap.2
151/// [OpenBSD]: https://man.openbsd.org/munmap.2
152/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munmap&section=2
153/// [illumos]: https://illumos.org/man/2/munmap
154/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Memory_002dmapped-I_002fO.html#index-munmap
155#[inline]
156pub unsafe fn munmap(ptr: *mut c_void, len: usize) -> io::Result<()> {
157 backend::mm::syscalls::munmap(addr:ptr, length:len)
158}
159
160/// `mremap(old_address, old_size, new_size, flags)`—Resize, modify, and/or
161/// move a memory mapping.
162///
163/// For moving a mapping to a fixed address (`MREMAP_FIXED`), see
164/// [`mremap_fixed`].
165///
166/// # Safety
167///
168/// Raw pointers and lots of special semantics.
169///
170/// # References
171/// - [Linux]
172///
173/// [Linux]: https://man7.org/linux/man-pages/man2/mremap.2.html
174#[cfg(any(target_os = "emscripten", target_os = "linux"))]
175#[inline]
176pub unsafe fn mremap(
177 old_address: *mut c_void,
178 old_size: usize,
179 new_size: usize,
180 flags: MremapFlags,
181) -> io::Result<*mut c_void> {
182 backend::mm::syscalls::mremap(old_address, old_size, new_size, flags)
183}
184
185/// `mremap(old_address, old_size, new_size, MREMAP_FIXED | flags)`—Resize,
186/// modify, and/or move a memory mapping to a specific address.
187///
188/// For `mremap` without moving to a specific address, see [`mremap`].
189/// [`mremap_fixed`].
190///
191/// # Safety
192///
193/// Raw pointers and lots of special semantics.
194///
195/// # References
196/// - [Linux]
197///
198/// [Linux]: https://man7.org/linux/man-pages/man2/mremap.2.html
199#[cfg(any(target_os = "emscripten", target_os = "linux"))]
200#[inline]
201#[doc(alias = "mremap")]
202pub unsafe fn mremap_fixed(
203 old_address: *mut c_void,
204 old_size: usize,
205 new_size: usize,
206 flags: MremapFlags,
207 new_address: *mut c_void,
208) -> io::Result<*mut c_void> {
209 backend::mm::syscalls::mremap_fixed(old_address, old_size, new_size, flags, new_address)
210}
211
212/// `mprotect(ptr, len, flags)`—Change the protection flags of a region of
213/// memory.
214///
215/// # Safety
216///
217/// Raw pointers and lots of special semantics.
218///
219/// # References
220/// - [POSIX]
221/// - [Linux]
222/// - [Apple]
223/// - [FreeBSD]
224/// - [NetBSD]
225/// - [OpenBSD]
226/// - [DragonFly BSD]
227/// - [illumos]
228///
229/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html
230/// [Linux]: https://man7.org/linux/man-pages/man2/mprotect.2.html
231/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mprotect.2.html
232/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mprotect&sektion=2
233/// [NetBSD]: https://man.netbsd.org/mprotect.2
234/// [OpenBSD]: https://man.openbsd.org/mprotect.2
235/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mprotect&section=2
236/// [illumos]: https://illumos.org/man/2/mprotect
237#[inline]
238pub unsafe fn mprotect(ptr: *mut c_void, len: usize, flags: MprotectFlags) -> io::Result<()> {
239 backend::mm::syscalls::mprotect(ptr, len, flags)
240}
241
242/// `mlock(ptr, len)`—Lock memory into RAM.
243///
244/// # Safety
245///
246/// This function operates on raw pointers, but it should only be used on
247/// memory which the caller owns. Technically, locking memory shouldn't violate
248/// any invariants, but since unlocking it can violate invariants, this
249/// function is also unsafe for symmetry.
250///
251/// Some implementations implicitly round the memory region out to the nearest
252/// page boundaries, so this function may lock more memory than explicitly
253/// requested if the memory isn't page-aligned. Other implementations fail if
254/// the memory isn't page-aligned.
255///
256/// # References
257/// - [POSIX]
258/// - [Linux]
259/// - [Apple]
260/// - [FreeBSD]
261/// - [NetBSD]
262/// - [OpenBSD]
263/// - [DragonFly BSD]
264/// - [illumos]
265/// - [glibc]
266///
267/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlock.html
268/// [Linux]: https://man7.org/linux/man-pages/man2/mlock.2.html
269/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mlock.2.html
270/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mlock&sektion=2
271/// [NetBSD]: https://man.netbsd.org/mlock.2
272/// [OpenBSD]: https://man.openbsd.org/mlock.2
273/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mlock&section=2
274/// [illumos]: https://illumos.org/man/3C/mlock
275/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlock
276#[inline]
277pub unsafe fn mlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
278 backend::mm::syscalls::mlock(addr:ptr, length:len)
279}
280
281/// `mlock2(ptr, len, flags)`—Lock memory into RAM, with flags.
282///
283/// `mlock_with` is the same as [`mlock`] but adds an additional flags operand.
284///
285/// # Safety
286///
287/// This function operates on raw pointers, but it should only be used on
288/// memory which the caller owns. Technically, locking memory shouldn't violate
289/// any invariants, but since unlocking it can violate invariants, this
290/// function is also unsafe for symmetry.
291///
292/// Some implementations implicitly round the memory region out to the nearest
293/// page boundaries, so this function may lock more memory than explicitly
294/// requested if the memory isn't page-aligned.
295///
296/// # References
297/// - [Linux]
298/// - [glibc]
299///
300/// [Linux]: https://man7.org/linux/man-pages/man2/mlock2.2.html
301/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlock2
302#[cfg(linux_kernel)]
303#[inline]
304#[doc(alias = "mlock2")]
305pub unsafe fn mlock_with(ptr: *mut c_void, len: usize, flags: MlockFlags) -> io::Result<()> {
306 backend::mm::syscalls::mlock_with(addr:ptr, length:len, flags)
307}
308
309/// `munlock(ptr, len)`—Unlock memory.
310///
311/// # Safety
312///
313/// This function operates on raw pointers, but it should only be used on
314/// memory which the caller owns, to avoid compromising the `mlock` invariants
315/// of other unrelated code in the process.
316///
317/// Some implementations implicitly round the memory region out to the nearest
318/// page boundaries, so this function may unlock more memory than explicitly
319/// requested if the memory isn't page-aligned.
320///
321/// # References
322/// - [POSIX]
323/// - [Linux]
324/// - [Apple]
325/// - [FreeBSD]
326/// - [NetBSD]
327/// - [OpenBSD]
328/// - [DragonFly BSD]
329/// - [illumos]
330/// - [glibc]
331///
332/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlock.html
333/// [Linux]: https://man7.org/linux/man-pages/man2/munlock.2.html
334/// [Apple]: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/munlock.2.html
335/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munlock&sektion=2
336/// [NetBSD]: https://man.netbsd.org/munlock.2
337/// [OpenBSD]: https://man.openbsd.org/munlock.2
338/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munlock&section=2
339/// [illumos]: https://illumos.org/man/3C/munlock
340/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-munlock
341#[inline]
342pub unsafe fn munlock(ptr: *mut c_void, len: usize) -> io::Result<()> {
343 backend::mm::syscalls::munlock(addr:ptr, length:len)
344}
345
346/// Locks all pages mapped into the address space of the calling process.
347///
348/// This includes the pages of the code, data, and stack segment, as well as
349/// shared libraries, user space kernel data, shared memory, and memory-mapped
350/// files. All mapped pages are guaranteed to be resident in RAM when the call
351/// returns successfully; the pages are guaranteed to stay in RAM until later
352/// unlocked.
353///
354/// # References
355/// - [POSIX]
356/// - [Linux]
357/// - [FreeBSD]
358/// - [NetBSD]
359/// - [OpenBSD]
360/// - [DragonFly BSD]
361/// - [illumos]
362/// - [glibc]
363///
364/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/mlockall.html
365/// [Linux]: https://man7.org/linux/man-pages/man2/mlockall.2.html
366/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=mlockall&sektion=2
367/// [NetBSD]: https://man.netbsd.org/mlockall.2
368/// [OpenBSD]: https://man.openbsd.org/mlockall.2
369/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=mlockall&section=2
370/// [illumos]: https://illumos.org/man/3C/mlockall
371/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-mlockall
372#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
373#[inline]
374pub fn mlockall(flags: MlockAllFlags) -> io::Result<()> {
375 backend::mm::syscalls::mlockall(flags)
376}
377
378/// Unlocks all pages mapped into the address space of the calling process.
379///
380/// # Warnings
381///
382/// This function is aware of all the memory pages in the process, as if it
383/// were a debugger. It unlocks all the pages, which could potentially
384/// compromise security assumptions made by code about memory it has
385/// encapsulated.
386///
387/// # References
388/// - [POSIX]
389/// - [Linux]
390/// - [FreeBSD]
391/// - [NetBSD]
392/// - [OpenBSD]
393/// - [DragonFly BSD]
394/// - [illumos]
395/// - [glibc]
396///
397/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/munlockall.html
398/// [Linux]: https://man7.org/linux/man-pages/man2/munlockall.2.html
399/// [FreeBSD]: https://man.freebsd.org/cgi/man.cgi?query=munlockall&sektion=2
400/// [NetBSD]: https://man.netbsd.org/munlockall.2
401/// [OpenBSD]: https://man.openbsd.org/munlockall.2
402/// [DragonFly BSD]: https://man.dragonflybsd.org/?command=munlockall&section=2
403/// [illumos]: https://illumos.org/man/3C/munlockall
404/// [glibc]: https://www.gnu.org/software/libc/manual/html_node/Page-Lock-Functions.html#index-munlockall
405#[cfg(any(linux_kernel, freebsdlike, netbsdlike))]
406#[inline]
407pub fn munlockall() -> io::Result<()> {
408 backend::mm::syscalls::munlockall()
409}
410