]> git.proxmox.com Git - rustc.git/blob - vendor/rustix-0.36.5/src/backend/libc/mm/syscalls.rs
New upstream version 1.70.0+dfsg1
[rustc.git] / vendor / rustix-0.36.5 / src / backend / libc / mm / syscalls.rs
1 //! libc syscalls supporting `rustix::mm`.
2
3 use super::super::c;
4 #[cfg(any(target_os = "android", target_os = "linux"))]
5 use super::super::conv::syscall_ret_owned_fd;
6 use super::super::conv::{borrowed_fd, no_fd, ret};
7 use super::super::offset::libc_mmap;
8 #[cfg(not(target_os = "redox"))]
9 use super::types::Advice;
10 #[cfg(target_os = "linux")]
11 use super::types::MremapFlags;
12 use super::types::{MapFlags, MprotectFlags, MsyncFlags, ProtFlags};
13 #[cfg(any(target_os = "android", target_os = "linux"))]
14 use super::types::{MlockFlags, UserfaultfdFlags};
15 use crate::fd::BorrowedFd;
16 #[cfg(any(target_os = "android", target_os = "linux"))]
17 use crate::fd::OwnedFd;
18 use crate::io;
19
20 #[cfg(not(target_os = "redox"))]
21 pub(crate) fn madvise(addr: *mut c::c_void, len: usize, advice: Advice) -> io::Result<()> {
22 // On Linux platforms, `MADV_DONTNEED` has the same value as
23 // `POSIX_MADV_DONTNEED` but different behavior. We remap it to a different
24 // value, and check for it here.
25 #[cfg(target_os = "linux")]
26 if let Advice::LinuxDontNeed = advice {
27 return unsafe { ret(c::madvise(addr, len, c::MADV_DONTNEED)) };
28 }
29
30 #[cfg(not(target_os = "android"))]
31 {
32 let err = unsafe { c::posix_madvise(addr, len, advice as c::c_int) };
33
34 // `posix_madvise` returns its error status rather than using `errno`.
35 if err == 0 {
36 Ok(())
37 } else {
38 Err(io::Errno(err))
39 }
40 }
41
42 #[cfg(target_os = "android")]
43 {
44 if let Advice::DontNeed = advice {
45 // Do nothing. Linux's `MADV_DONTNEED` isn't the same as
46 // `POSIX_MADV_DONTNEED`, so just discard `MADV_DONTNEED`.
47 Ok(())
48 } else {
49 unsafe { ret(c::madvise(addr, len, advice as c::c_int)) }
50 }
51 }
52 }
53
54 pub(crate) unsafe fn msync(addr: *mut c::c_void, len: usize, flags: MsyncFlags) -> io::Result<()> {
55 let err = c::msync(addr, len, flags.bits());
56
57 // `msync` returns its error status rather than using `errno`.
58 if err == 0 {
59 Ok(())
60 } else {
61 Err(io::Errno(err))
62 }
63 }
64
65 /// # Safety
66 ///
67 /// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
68 /// with memory pointed to by raw pointers is unsafe.
69 pub(crate) unsafe fn mmap(
70 ptr: *mut c::c_void,
71 len: usize,
72 prot: ProtFlags,
73 flags: MapFlags,
74 fd: BorrowedFd<'_>,
75 offset: u64,
76 ) -> io::Result<*mut c::c_void> {
77 let res = libc_mmap(
78 ptr,
79 len,
80 prot.bits(),
81 flags.bits(),
82 borrowed_fd(fd),
83 offset as i64,
84 );
85 if res == c::MAP_FAILED {
86 Err(io::Errno::last_os_error())
87 } else {
88 Ok(res)
89 }
90 }
91
92 /// # Safety
93 ///
94 /// `mmap` is primarily unsafe due to the `addr` parameter, as anything working
95 /// with memory pointed to by raw pointers is unsafe.
96 pub(crate) unsafe fn mmap_anonymous(
97 ptr: *mut c::c_void,
98 len: usize,
99 prot: ProtFlags,
100 flags: MapFlags,
101 ) -> io::Result<*mut c::c_void> {
102 let res = libc_mmap(
103 ptr,
104 len,
105 prot.bits(),
106 flags.bits() | c::MAP_ANONYMOUS,
107 no_fd(),
108 0,
109 );
110 if res == c::MAP_FAILED {
111 Err(io::Errno::last_os_error())
112 } else {
113 Ok(res)
114 }
115 }
116
117 pub(crate) unsafe fn mprotect(
118 ptr: *mut c::c_void,
119 len: usize,
120 flags: MprotectFlags,
121 ) -> io::Result<()> {
122 ret(c::mprotect(ptr, len, flags.bits()))
123 }
124
125 pub(crate) unsafe fn munmap(ptr: *mut c::c_void, len: usize) -> io::Result<()> {
126 ret(c::munmap(ptr, len))
127 }
128
129 /// # Safety
130 ///
131 /// `mremap` is primarily unsafe due to the `old_address` parameter, as
132 /// anything working with memory pointed to by raw pointers is unsafe.
133 #[cfg(target_os = "linux")]
134 pub(crate) unsafe fn mremap(
135 old_address: *mut c::c_void,
136 old_size: usize,
137 new_size: usize,
138 flags: MremapFlags,
139 ) -> io::Result<*mut c::c_void> {
140 let res = c::mremap(old_address, old_size, new_size, flags.bits());
141 if res == c::MAP_FAILED {
142 Err(io::Errno::last_os_error())
143 } else {
144 Ok(res)
145 }
146 }
147
148 /// # Safety
149 ///
150 /// `mremap_fixed` is primarily unsafe due to the `old_address` and
151 /// `new_address` parameters, as anything working with memory pointed to by raw
152 /// pointers is unsafe.
153 #[cfg(target_os = "linux")]
154 pub(crate) unsafe fn mremap_fixed(
155 old_address: *mut c::c_void,
156 old_size: usize,
157 new_size: usize,
158 flags: MremapFlags,
159 new_address: *mut c::c_void,
160 ) -> io::Result<*mut c::c_void> {
161 let res = c::mremap(
162 old_address,
163 old_size,
164 new_size,
165 flags.bits() | c::MAP_FIXED,
166 new_address,
167 );
168 if res == c::MAP_FAILED {
169 Err(io::Errno::last_os_error())
170 } else {
171 Ok(res)
172 }
173 }
174
175 /// # Safety
176 ///
177 /// `mlock` operates on raw pointers and may round out to the nearest page
178 /// boundaries.
179 #[inline]
180 pub(crate) unsafe fn mlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
181 ret(c::mlock(addr, length))
182 }
183
184 /// # Safety
185 ///
186 /// `mlock_with` operates on raw pointers and may round out to the nearest page
187 /// boundaries.
188 #[cfg(any(target_os = "android", target_os = "linux"))]
189 #[inline]
190 pub(crate) unsafe fn mlock_with(
191 addr: *mut c::c_void,
192 length: usize,
193 flags: MlockFlags,
194 ) -> io::Result<()> {
195 weak_or_syscall! {
196 fn mlock2(
197 addr: *const c::c_void,
198 len: c::size_t,
199 flags: c::c_int
200 ) via SYS_mlock2 -> c::c_int
201 }
202
203 ret(mlock2(addr, length, flags.bits()))
204 }
205
206 /// # Safety
207 ///
208 /// `munlock` operates on raw pointers and may round out to the nearest page
209 /// boundaries.
210 #[inline]
211 pub(crate) unsafe fn munlock(addr: *mut c::c_void, length: usize) -> io::Result<()> {
212 ret(c::munlock(addr, length))
213 }
214
215 #[cfg(any(target_os = "android", target_os = "linux"))]
216 pub(crate) unsafe fn userfaultfd(flags: UserfaultfdFlags) -> io::Result<OwnedFd> {
217 syscall_ret_owned_fd(c::syscall(c::SYS_userfaultfd, flags.bits()))
218 }