1 | /// Values supported by [`Mmap::advise`][crate::Mmap::advise] and [`MmapMut::advise`][crate::MmapMut::advise] functions. |
2 | /// See [madvise()](https://man7.org/linux/man-pages/man2/madvise.2.html) map page. |
3 | #[derive (Debug, Eq, PartialEq, Hash)] |
4 | pub struct Advice(pub(crate) libc::c_int); |
5 | |
6 | impl Advice { |
7 | /// **MADV_NORMAL** |
8 | /// |
9 | /// No special treatment. This is the default. |
10 | pub fn normal() -> Self { |
11 | Self(libc::MADV_NORMAL) |
12 | } |
13 | |
14 | /// **MADV_RANDOM** |
15 | /// |
16 | /// Expect page references in random order. (Hence, read |
17 | /// ahead may be less useful than normally.) |
18 | pub fn random() -> Self { |
19 | Self(libc::MADV_RANDOM) |
20 | } |
21 | |
22 | /// **MADV_SEQUENTIAL** |
23 | /// |
24 | /// Expect page references in sequential order. (Hence, pages |
25 | /// in the given range can be aggressively read ahead, and may |
26 | /// be freed soon after they are accessed.) |
27 | pub fn sequential() -> Self { |
28 | Self(libc::MADV_SEQUENTIAL) |
29 | } |
30 | |
31 | /// **MADV_WILLNEED** |
32 | /// |
33 | /// Expect access in the near future. (Hence, it might be a |
34 | /// good idea to read some pages ahead.) |
35 | pub fn will_need() -> Self { |
36 | Self(libc::MADV_WILLNEED) |
37 | } |
38 | |
39 | /// **MADV_DONTNEED** |
40 | /// |
41 | /// Do not expect access in the near future. (For the time |
42 | /// being, the application is finished with the given range, |
43 | /// so the kernel can free resources associated with it.) |
44 | /// |
45 | /// After a successful MADV_DONTNEED operation, the semantics |
46 | /// of memory access in the specified region are changed: |
47 | /// subsequent accesses of pages in the range will succeed, |
48 | /// but will result in either repopulating the memory contents |
49 | /// from the up-to-date contents of the underlying mapped file |
50 | /// (for shared file mappings, shared anonymous mappings, and |
51 | /// shmem-based techniques such as System V shared memory |
52 | /// segments) or zero-fill-on-demand pages for anonymous |
53 | /// private mappings. |
54 | /// |
55 | /// Note that, when applied to shared mappings, MADV_DONTNEED |
56 | /// might not lead to immediate freeing of the pages in the |
57 | /// range. The kernel is free to delay freeing the pages |
58 | /// until an appropriate moment. The resident set size (RSS) |
59 | /// of the calling process will be immediately reduced |
60 | /// however. |
61 | /// |
62 | /// **MADV_DONTNEED** cannot be applied to locked pages, Huge TLB |
63 | /// pages, or VM_PFNMAP pages. (Pages marked with the kernel- |
64 | /// internal VM_PFNMAP flag are special memory areas that are |
65 | /// not managed by the virtual memory subsystem. Such pages |
66 | /// are typically created by device drivers that map the pages |
67 | /// into user space.) |
68 | /// |
69 | /// # Safety |
70 | /// |
71 | /// Using the returned value with conceptually write to the |
72 | /// mapped pages, i.e. borrowing the mapping when the pages |
73 | /// are freed results in undefined behaviour. |
74 | pub unsafe fn dont_need() -> Self { |
75 | Self(libc::MADV_DONTNEED) |
76 | } |
77 | |
78 | // |
79 | // The rest are Linux-specific |
80 | // |
81 | /// **MADV_FREE** - Linux (since Linux 4.5) and Darwin |
82 | /// |
83 | /// The application no longer requires the pages in the range |
84 | /// specified by addr and len. The kernel can thus free these |
85 | /// pages, but the freeing could be delayed until memory |
86 | /// pressure occurs. For each of the pages that has been |
87 | /// marked to be freed but has not yet been freed, the free |
88 | /// operation will be canceled if the caller writes into the |
89 | /// page. After a successful MADV_FREE operation, any stale |
90 | /// data (i.e., dirty, unwritten pages) will be lost when the |
91 | /// kernel frees the pages. However, subsequent writes to |
92 | /// pages in the range will succeed and then kernel cannot |
93 | /// free those dirtied pages, so that the caller can always |
94 | /// see just written data. If there is no subsequent write, |
95 | /// the kernel can free the pages at any time. Once pages in |
96 | /// the range have been freed, the caller will see zero-fill- |
97 | /// on-demand pages upon subsequent page references. |
98 | /// |
99 | /// The MADV_FREE operation can be applied only to private |
100 | /// anonymous pages (see mmap(2)). In Linux before version |
101 | /// 4.12, when freeing pages on a swapless system, the pages |
102 | /// in the given range are freed instantly, regardless of |
103 | /// memory pressure. |
104 | /// |
105 | /// # Safety |
106 | /// |
107 | /// Using the returned value with conceptually write to the |
108 | /// mapped pages, i.e. borrowing the mapping while the pages |
109 | /// are still being freed results in undefined behaviour. |
110 | #[cfg (any(target_os = "linux" , target_os = "macos" , target_os = "ios" ))] |
111 | pub unsafe fn free() -> Self { |
112 | Self(libc::MADV_FREE) |
113 | } |
114 | |
115 | /// **MADV_REMOVE** - Linux only (since Linux 2.6.16) |
116 | /// |
117 | /// Free up a given range of pages and its associated backing |
118 | /// store. This is equivalent to punching a hole in the |
119 | /// corresponding byte range of the backing store (see |
120 | /// fallocate(2)). Subsequent accesses in the specified |
121 | /// address range will see bytes containing zero. |
122 | /// |
123 | /// The specified address range must be mapped shared and |
124 | /// writable. This flag cannot be applied to locked pages, |
125 | /// Huge TLB pages, or VM_PFNMAP pages. |
126 | /// |
127 | /// In the initial implementation, only tmpfs(5) was supported |
128 | /// **MADV_REMOVE**; but since Linux 3.5, any filesystem which |
129 | /// supports the fallocate(2) FALLOC_FL_PUNCH_HOLE mode also |
130 | /// supports MADV_REMOVE. Hugetlbfs fails with the error |
131 | /// EINVAL and other filesystems fail with the error |
132 | /// EOPNOTSUPP. |
133 | /// |
134 | /// # Safety |
135 | /// |
136 | /// Using the returned value with conceptually write to the |
137 | /// mapped pages, i.e. borrowing the mapping when the pages |
138 | /// are freed results in undefined behaviour. |
139 | #[cfg (target_os = "linux" )] |
140 | pub unsafe fn remove() -> Self { |
141 | Self(libc::MADV_REMOVE) |
142 | } |
143 | |
144 | /// **MADV_DONTFORK** - Linux only (since Linux 2.6.16) |
145 | /// |
146 | /// Do not make the pages in this range available to the child |
147 | /// after a fork(2). This is useful to prevent copy-on-write |
148 | /// semantics from changing the physical location of a page if |
149 | /// the parent writes to it after a fork(2). (Such page |
150 | /// relocations cause problems for hardware that DMAs into the |
151 | /// page.) |
152 | #[cfg (target_os = "linux" )] |
153 | pub fn dont_fork() -> Self { |
154 | Self(libc::MADV_DONTFORK) |
155 | } |
156 | |
157 | /// **MADV_DOFORK** - Linux only (since Linux 2.6.16) |
158 | /// |
159 | /// Undo the effect of MADV_DONTFORK, restoring the default |
160 | /// behavior, whereby a mapping is inherited across fork(2). |
161 | #[cfg (target_os = "linux" )] |
162 | pub fn do_fork() -> Self { |
163 | Self(libc::MADV_DOFORK) |
164 | } |
165 | |
166 | /// **MADV_MERGEABLE** - Linux only (since Linux 2.6.32) |
167 | /// |
168 | /// Enable Kernel Samepage Merging (KSM) for the pages in the |
169 | /// range specified by addr and length. The kernel regularly |
170 | /// scans those areas of user memory that have been marked as |
171 | /// mergeable, looking for pages with identical content. |
172 | /// These are replaced by a single write-protected page (which |
173 | /// is automatically copied if a process later wants to update |
174 | /// the content of the page). KSM merges only private |
175 | /// anonymous pages (see mmap(2)). |
176 | /// |
177 | /// The KSM feature is intended for applications that generate |
178 | /// many instances of the same data (e.g., virtualization |
179 | /// systems such as KVM). It can consume a lot of processing |
180 | /// power; use with care. See the Linux kernel source file |
181 | /// Documentation/admin-guide/mm/ksm.rst for more details. |
182 | /// |
183 | /// The MADV_MERGEABLE and MADV_UNMERGEABLE operations are |
184 | /// available only if the kernel was configured with |
185 | /// CONFIG_KSM. |
186 | #[cfg (target_os = "linux" )] |
187 | pub fn mergeable() -> Self { |
188 | Self(libc::MADV_MERGEABLE) |
189 | } |
190 | |
191 | /// **MADV_UNMERGEABLE** - Linux only (since Linux 2.6.32) |
192 | /// |
193 | /// Undo the effect of an earlier MADV_MERGEABLE operation on |
194 | /// the specified address range; KSM unmerges whatever pages |
195 | /// it had merged in the address range specified by addr and |
196 | /// length. |
197 | #[cfg (target_os = "linux" )] |
198 | pub fn unmergeable() -> Self { |
199 | Self(libc::MADV_UNMERGEABLE) |
200 | } |
201 | |
202 | /// **MADV_HUGEPAGE** - Linux only (since Linux 2.6.38) |
203 | /// |
204 | /// Enable Transparent Huge Pages (THP) for pages in the range |
205 | /// specified by addr and length. Currently, Transparent Huge |
206 | /// Pages work only with private anonymous pages (see |
207 | /// mmap(2)). The kernel will regularly scan the areas marked |
208 | /// as huge page candidates to replace them with huge pages. |
209 | /// The kernel will also allocate huge pages directly when the |
210 | /// region is naturally aligned to the huge page size (see |
211 | /// posix_memalign(2)). |
212 | /// |
213 | /// This feature is primarily aimed at applications that use |
214 | /// large mappings of data and access large regions of that |
215 | /// memory at a time (e.g., virtualization systems such as |
216 | /// QEMU). It can very easily waste memory (e.g., a 2 MB |
217 | /// mapping that only ever accesses 1 byte will result in 2 MB |
218 | /// of wired memory instead of one 4 KB page). See the Linux |
219 | /// kernel source file |
220 | /// Documentation/admin-guide/mm/transhuge.rst for more |
221 | /// details. |
222 | /// |
223 | /// Most common kernels configurations provide MADV_HUGEPAGE- |
224 | /// style behavior by default, and thus MADV_HUGEPAGE is |
225 | /// normally not necessary. It is mostly intended for |
226 | /// embedded systems, where MADV_HUGEPAGE-style behavior may |
227 | /// not be enabled by default in the kernel. On such systems, |
228 | /// this flag can be used in order to selectively enable THP. |
229 | /// Whenever MADV_HUGEPAGE is used, it should always be in |
230 | /// regions of memory with an access pattern that the |
231 | /// developer knows in advance won't risk to increase the |
232 | /// memory footprint of the application when transparent |
233 | /// hugepages are enabled. |
234 | /// |
235 | /// The MADV_HUGEPAGE and MADV_NOHUGEPAGE operations are |
236 | /// available only if the kernel was configured with |
237 | /// CONFIG_TRANSPARENT_HUGEPAGE. |
238 | #[cfg (target_os = "linux" )] |
239 | pub fn huge_page() -> Self { |
240 | Self(libc::MADV_HUGEPAGE) |
241 | } |
242 | |
243 | /// **MADV_NOHUGEPAGE** - Linux only (since Linux 2.6.38) |
244 | /// |
245 | /// Ensures that memory in the address range specified by addr |
246 | /// and length will not be backed by transparent hugepages. |
247 | #[cfg (target_os = "linux" )] |
248 | pub fn no_huge_page() -> Self { |
249 | Self(libc::MADV_NOHUGEPAGE) |
250 | } |
251 | |
252 | /// **MADV_DONTDUMP** - Linux only (since Linux 3.4) |
253 | /// |
254 | /// Exclude from a core dump those pages in the range |
255 | /// specified by addr and length. This is useful in |
256 | /// applications that have large areas of memory that are |
257 | /// known not to be useful in a core dump. The effect of |
258 | /// **MADV_DONTDUMP** takes precedence over the bit mask that is |
259 | /// set via the `/proc/[pid]/coredump_filter` file (see |
260 | /// core(5)). |
261 | #[cfg (target_os = "linux" )] |
262 | pub fn dont_dump() -> Self { |
263 | Self(libc::MADV_DONTDUMP) |
264 | } |
265 | |
266 | /// **MADV_DODUMP** - Linux only (since Linux 3.4) |
267 | /// |
268 | /// Undo the effect of an earlier MADV_DONTDUMP. |
269 | #[cfg (target_os = "linux" )] |
270 | pub fn do_dump() -> Self { |
271 | Self(libc::MADV_DODUMP) |
272 | } |
273 | |
274 | /// **MADV_HWPOISON** - Linux only (since Linux 2.6.32) |
275 | /// |
276 | /// Poison the pages in the range specified by addr and length |
277 | /// and handle subsequent references to those pages like a |
278 | /// hardware memory corruption. This operation is available |
279 | /// only for privileged (CAP_SYS_ADMIN) processes. This |
280 | /// operation may result in the calling process receiving a |
281 | /// SIGBUS and the page being unmapped. |
282 | /// |
283 | /// This feature is intended for testing of memory error- |
284 | /// handling code; it is available only if the kernel was |
285 | /// configured with CONFIG_MEMORY_FAILURE. |
286 | #[cfg (target_os = "linux" )] |
287 | pub fn hw_poison() -> Self { |
288 | Self(libc::MADV_HWPOISON) |
289 | } |
290 | |
291 | /// **MADV_POPULATE_READ** - Linux only (since Linux 5.14) |
292 | /// |
293 | /// Populate (prefault) page tables readable, faulting in all |
294 | /// pages in the range just as if manually reading from each |
295 | /// page; however, avoid the actual memory access that would have |
296 | /// been performed after handling the fault. |
297 | /// |
298 | /// In contrast to MAP_POPULATE, MADV_POPULATE_READ does not hide |
299 | /// errors, can be applied to (parts of) existing mappings and |
300 | /// will always populate (prefault) page tables readable. One |
301 | /// example use case is prefaulting a file mapping, reading all |
302 | /// file content from disk; however, pages won't be dirtied and |
303 | /// consequently won't have to be written back to disk when |
304 | /// evicting the pages from memory. |
305 | /// |
306 | /// Depending on the underlying mapping, map the shared zeropage, |
307 | /// preallocate memory or read the underlying file; files with |
308 | /// holes might or might not preallocate blocks. If populating |
309 | /// fails, a SIGBUS signal is not generated; instead, an error is |
310 | /// returned. |
311 | /// |
312 | /// If MADV_POPULATE_READ succeeds, all page tables have been |
313 | /// populated (prefaulted) readable once. If MADV_POPULATE_READ |
314 | /// fails, some page tables might have been populated. |
315 | /// |
316 | /// MADV_POPULATE_READ cannot be applied to mappings without read |
317 | /// permissions and special mappings, for example, mappings |
318 | /// marked with kernel-internal flags such as VM_PFNMAP or VM_IO, |
319 | /// or secret memory regions created using memfd_secret(2). |
320 | /// |
321 | /// Note that with MADV_POPULATE_READ, the process can be killed |
322 | /// at any moment when the system runs out of memory. |
323 | #[cfg (target_os = "linux" )] |
324 | pub fn populate_read() -> Self { |
325 | Self(libc::MADV_POPULATE_READ) |
326 | } |
327 | |
328 | /// **MADV_POPULATE_WRITE** - Linux only (since Linux 5.14) |
329 | /// |
330 | /// Populate (prefault) page tables writable, faulting in all |
331 | /// pages in the range just as if manually writing to each each |
332 | /// page; however, avoid the actual memory access that would have |
333 | /// been performed after handling the fault. |
334 | /// |
335 | /// In contrast to MAP_POPULATE, MADV_POPULATE_WRITE does not |
336 | /// hide errors, can be applied to (parts of) existing mappings |
337 | /// and will always populate (prefault) page tables writable. |
338 | /// One example use case is preallocating memory, breaking any |
339 | /// CoW (Copy on Write). |
340 | /// |
341 | /// Depending on the underlying mapping, preallocate memory or |
342 | /// read the underlying file; files with holes will preallocate |
343 | /// blocks. If populating fails, a SIGBUS signal is not gener‐ |
344 | /// ated; instead, an error is returned. |
345 | /// |
346 | /// If MADV_POPULATE_WRITE succeeds, all page tables have been |
347 | /// populated (prefaulted) writable once. If MADV_POPULATE_WRITE |
348 | /// fails, some page tables might have been populated. |
349 | /// |
350 | /// MADV_POPULATE_WRITE cannot be applied to mappings without |
351 | /// write permissions and special mappings, for example, mappings |
352 | /// marked with kernel-internal flags such as VM_PFNMAP or VM_IO, |
353 | /// or secret memory regions created using memfd_secret(2). |
354 | /// |
355 | /// Note that with MADV_POPULATE_WRITE, the process can be killed |
356 | /// at any moment when the system runs out of memory. |
357 | #[cfg (target_os = "linux" )] |
358 | pub fn populate_write() -> Self { |
359 | Self(libc::MADV_POPULATE_WRITE) |
360 | } |
361 | |
362 | /// **MADV_ZERO_WIRED_PAGES** - Darwin only |
363 | /// |
364 | /// Indicates that the application would like the wired pages in this address range to be |
365 | /// zeroed out if the address range is deallocated without first unwiring the pages (i.e. |
366 | /// a munmap(2) without a preceding munlock(2) or the application quits). This is used |
367 | /// with madvise() system call. |
368 | #[cfg (any(target_os = "macos" , target_os = "ios" ))] |
369 | pub fn zero_wired_pages() -> Self { |
370 | Self(libc::MADV_ZERO_WIRED_PAGES) |
371 | } |
372 | |
373 | /// **MADV_FREE_REUSABLE** - Darwin only |
374 | /// |
375 | /// Behaves like **MADV_FREE**, but the freed pages are accounted for in the RSS of the process. |
376 | /// |
377 | /// # Safety |
378 | /// |
379 | /// Using the returned value with conceptually write to the |
380 | /// mapped pages, i.e. borrowing the mapping while the pages |
381 | /// are still being freed results in undefined behaviour. |
382 | #[cfg (any(target_os = "macos" , target_os = "ios" ))] |
383 | pub unsafe fn free_reusable() -> Self { |
384 | Self(libc::MADV_FREE_REUSABLE) |
385 | } |
386 | |
387 | /// **MADV_FREE_REUSE** - Darwin only |
388 | /// |
389 | /// Marks a memory region previously freed by **MADV_FREE_REUSABLE** as non-reusable, accounts |
390 | /// for the pages in the RSS of the process. Pages that have been freed will be replaced by |
391 | /// zero-filled pages on demand, other pages will be left as is. |
392 | /// |
393 | /// # Safety |
394 | /// |
395 | /// Using the returned value with conceptually write to the |
396 | /// mapped pages, i.e. borrowing the mapping while the pages |
397 | /// are still being freed results in undefined behaviour. |
398 | #[cfg (any(target_os = "macos" , target_os = "ios" ))] |
399 | pub unsafe fn free_reuse() -> Self { |
400 | Self(libc::MADV_FREE_REUSE) |
401 | } |
402 | } |
403 | |
404 | // Future expansion: |
405 | // MADV_SOFT_OFFLINE (since Linux 2.6.33) |
406 | // MADV_WIPEONFORK (since Linux 4.14) |
407 | // MADV_KEEPONFORK (since Linux 4.14) |
408 | // MADV_COLD (since Linux 5.4) |
409 | // MADV_PAGEOUT (since Linux 5.4) |
410 | |