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.
normal() -> Self10     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.)
random() -> Self18     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.)
sequential() -> Self27     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.)
will_need() -> Self35     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.
dont_need() -> Self74     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"))]
free() -> Self111     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")]
remove() -> Self140     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")]
dont_fork() -> Self153     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")]
do_fork() -> Self162     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")]
mergeable() -> Self187     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")]
unmergeable() -> Self198     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")]
huge_page() -> Self239     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")]
no_huge_page() -> Self248     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")]
dont_dump() -> Self262     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")]
do_dump() -> Self270     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")]
hw_poison() -> Self287     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")]
populate_read() -> Self324     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")]
populate_write() -> Self358     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"))]
zero_wired_pages() -> Self369     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"))]
free_reusable() -> Self383     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"))]
free_reuse() -> Self399     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