mmtk/util/heap/layout/mmapper/mod.rs
1use crate::util::{
2 memory::{MmapAnnotation, MmapStrategy},
3 Address,
4};
5use std::io::Result;
6
7#[allow(unused)] // Used in doc comment.
8use crate::util::constants::LOG_BYTES_IN_PAGE;
9
10pub mod csm;
11
12/// An `Mmapper` manages the mmap state of memory used by the heap and side metadata of MMTk.
13///
14/// For the efficiency of implementation, an `Mmapper` operates at the granularity of
15/// [`Mmapper::granularity()`]. Methods that take memory ranges as arguments will round the range
16/// to the overlapping chunks.
17///
18/// From the perspective of the `Mmapper`, each memory range can be in one of the three states:
19/// Unmapped, Quarantined, and Mapped. The state transition graph is:
20///
21/// ```text
22/// ┌────────┐ ensure_mapped / mark_as_mapped ┌──────┐
23/// │Unmapped├────────────────────────────────────►Mapped│
24/// └───┬────┘ └───▲──┘
25/// │ ┌───────────┐ │
26/// └───────────────►Quarantined├─────────────────┘
27/// quarantine └───────────┘ ensure_mapped
28/// ```
29///
30/// - **Unmapped** means the memory is not mapped by the `Mmapper`, and may be mapped by other
31/// components of the process.
32/// - **Quarantined** means the `Mmapper` has reserved the memory for MMTk, usually by using
33/// `mmap` with `PROT_NONE`.
34/// - **Mapped** means `Mmapper` has mapped the memory, and the memory can be read and written by
35/// MMTk.
36pub trait Mmapper: Sync {
37 /// The logarithm of granularity of this `Mmapper`, in bytes. Must be at least
38 /// [`LOG_BYTES_IN_PAGE`].
39 ///
40 /// See trait-level doc for [`Mmapper`] for details.
41 fn log_granularity(&self) -> u8;
42
43 /// The logarithm of the address space size this `Mmapper` can handle.
44 ///
45 /// In other words, this `Mmapper` cannot handle addresses greater than or equal to
46 /// `1 << self.log_mappable_bytes()`.
47 fn log_mappable_bytes(&self) -> u8;
48
49 /// The granularity of `Mmapper`. Don't override this method. Override
50 /// [`Mmapper::log_granularity`] instead.
51 ///
52 /// See trait-level doc for [`Mmapper`] for details.
53 fn granularity(&self) -> usize {
54 1 << self.log_granularity()
55 }
56
57 /// Mark a number of pages as mapped, without making any
58 /// request to the operating system. Used to mark pages
59 /// that the VM has already mapped.
60 ///
61 /// Arguments:
62 /// * `start`: Address of the first page to be mapped
63 /// * `bytes`: Number of bytes to ensure mapped
64 fn mark_as_mapped(&self, start: Address, bytes: usize);
65
66 /// Quarantine/reserve address range. We mmap from the OS with no reserve and with PROT_NONE,
67 /// which should be little overhead. This ensures that we can reserve certain address range that
68 /// we can use if needed. Quarantined memory needs to be mapped before it can be used.
69 ///
70 /// Arguments:
71 /// * `start`: Address of the first page to be quarantined
72 /// * `pages`: Number of pages to quarantine from the start
73 /// * `strategy`: The mmap strategy. The `prot` field is ignored because we always use
74 /// `PROT_NONE`.
75 /// * `anno`: Human-readable annotation to apply to newly mapped memory ranges.
76 fn quarantine_address_range(
77 &self,
78 start: Address,
79 pages: usize,
80 strategy: MmapStrategy,
81 anno: &MmapAnnotation,
82 ) -> Result<()>;
83
84 /// Ensure that a range of pages is mmapped (or equivalent). If the
85 /// pages are not yet mapped, demand-zero map them. Note that mapping
86 /// occurs at chunk granularity, not page granularity.
87 ///
88 /// Arguments:
89 /// * `start`: The start of the range to be mapped.
90 /// * `pages`: The size of the range to be mapped, in pages
91 /// * `strategy`: The mmap strategy.
92 /// * `anno`: Human-readable annotation to apply to newly mapped memory ranges.
93 // NOTE: There is a monotonicity assumption so that only updates require lock
94 // acquisition.
95 // TODO: Fix the above to support unmapping.
96 fn ensure_mapped(
97 &self,
98 start: Address,
99 pages: usize,
100 strategy: MmapStrategy,
101 anno: &MmapAnnotation,
102 ) -> Result<()>;
103
104 /// Is the page pointed to by this address mapped? Returns true if
105 /// the page at the given address is mapped.
106 ///
107 /// Arguments:
108 /// * `addr`: Address in question
109 fn is_mapped_address(&self, addr: Address) -> bool;
110}