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