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
use crate::util::freelist::FreeList;
use crate::util::heap::space_descriptor::SpaceDescriptor;
use crate::util::Address;

/// The result of creating free list.
///
/// `VMMap` will select an implementation of `FreeList`.  If it is `RawMemoryFreeList`, it will
/// occupy a portion of address range at the beginning of the space.  That will require the
/// starting address of the space to be displaced.  This information is conveyed via the
/// `space_displacement` field.
pub struct CreateFreeListResult {
    // The created free list.
    pub free_list: Box<dyn FreeList>,
    // The number of bytes to be added to the starting address of the space.  Zero if not needed.
    // Always aligned to chunks.
    pub space_displacement: usize,
}

pub trait VMMap: Sync {
    fn insert(&self, start: Address, extent: usize, descriptor: SpaceDescriptor);

    /// Create a free-list for a discontiguous space. Must only be called at boot time.
    fn create_freelist(&self, start: Address) -> CreateFreeListResult;

    /// Create a free-list for a contiguous space. Must only be called at boot time.
    fn create_parent_freelist(
        &self,
        start: Address,
        units: usize,
        grain: i32,
    ) -> CreateFreeListResult;

    /// # Safety
    ///
    /// Caller must ensure that only one thread is calling this method.
    unsafe fn allocate_contiguous_chunks(
        &self,
        descriptor: SpaceDescriptor,
        chunks: usize,
        head: Address,
        maybe_freelist: Option<&mut dyn FreeList>,
    ) -> Address;

    fn get_next_contiguous_region(&self, start: Address) -> Address;

    fn get_contiguous_region_chunks(&self, start: Address) -> usize;

    fn get_contiguous_region_size(&self, start: Address) -> usize;

    /// Return the total number of chunks available (unassigned) within the range of virtual memory
    /// apportioned to discontiguous spaces.
    fn get_available_discontiguous_chunks(&self) -> usize;

    /// Return the total number of clients contending for chunks. This is useful when establishing
    /// conservative bounds on the number of remaining chunks.
    fn get_chunk_consumer_count(&self) -> usize;

    fn free_all_chunks(&self, any_chunk: Address);

    /// # Safety
    ///
    /// Caller must ensure that only one thread is calling this method.
    unsafe fn free_contiguous_chunks(&self, start: Address) -> usize;

    /// Finalize the globlal maps in the implementations of `VMMap`.  This should be called after
    /// all spaces are created.
    ///
    /// Arguments:
    /// -   `from`: the starting address of the heap
    /// -   `to`: the address of the last byte within the heap
    /// -   `on_discontig_start_determined`: Called when the address range of the discontiguous
    ///     memory range is determined.  Will not be called if the `VMMap` implementation does not
    ///     have a discontigous memory range.  The `Address` argument of the callback is the
    ///     starting address of the discontiguous memory range.
    fn finalize_static_space_map(
        &self,
        from: Address,
        to: Address,
        on_discontig_start_determined: &mut dyn FnMut(Address),
    );

    fn is_finalized(&self) -> bool;

    fn get_descriptor_for_address(&self, address: Address) -> SpaceDescriptor;

    fn add_to_cumulative_committed_pages(&self, pages: usize);
}