Bitmap Page Allocator
Relevant source files
This document covers the BitmapPageAllocator implementation, which provides page-granularity memory allocation using a bitmap-based approach. The allocator manages memory in fixed-size pages and uses an external bitmap data structure to track allocation status.
For byte-granularity allocation algorithms, see Buddy System Allocator, Slab Allocator, and TLSF Allocator. For broader architectural concepts and trait definitions, see Architecture and Design.
Overview and Purpose
The BitmapPageAllocator is a page-granularity allocator that internally uses a bitmap where each bit indicates whether a page has been allocated. It wraps the external bitmap_allocator crate and implements the PageAllocator and BaseAllocator traits defined in the core library.
Core Allocator Structure
classDiagram
class BitmapPageAllocator {
+PAGE_SIZE: usize
-base: usize
-total_pages: usize
-used_pages: usize
-inner: BitAllocUsed
+new() BitmapPageAllocator
+alloc_pages(num_pages, align_pow2) AllocResult~usize~
+alloc_pages_at(base, num_pages, align_pow2) AllocResult~usize~
+dealloc_pages(pos, num_pages)
+total_pages() usize
+used_pages() usize
+available_pages() usize
}
class BaseAllocator {
<<interface>>
+init(start, size)
+add_memory(start, size) AllocResult
}
class PageAllocator {
<<interface>>
+PAGE_SIZE: usize
+alloc_pages(num_pages, align_pow2) AllocResult~usize~
+dealloc_pages(pos, num_pages)
+total_pages() usize
+used_pages() usize
+available_pages() usize
}
class BitAllocUsed {
<<external>>
+alloc() Option~usize~
+alloc_contiguous(start, num, align_log2) Option~usize~
+dealloc(idx) bool
+dealloc_contiguous(start, num) bool
+insert(range)
}
PageAllocator --|> BaseAllocator
BitmapPageAllocator --|> PageAllocator
BitmapPageAllocator *-- BitAllocUsed
Sources: src/bitmap.rs(L34 - L50) src/bitmap.rs(L53 - L75) src/bitmap.rs(L77 - L160)
Memory Size Configuration
The allocator uses feature flags to configure the maximum memory size it can manage. Different BitAlloc implementations from the external bitmap_allocator crate are selected based on compilation features.
Feature-Based BitAlloc Selection
flowchart TD
subgraph subGraph2["Memory Capacity"]
CAP_4G["4GB Memory(Testing)"]
CAP_1T["1TB Memory"]
CAP_64G["64GB Memory"]
CAP_256M["256MB Memory(Default)"]
end
subgraph subGraph1["BitAlloc Types"]
BITALLOC_1M["BitAlloc1M1M pages = 4GB max"]
BITALLOC_256M["BitAlloc256M256M pages = 1TB max"]
BITALLOC_16M["BitAlloc16M16M pages = 64GB max"]
BITALLOC_64K["BitAlloc64K64K pages = 256MB max"]
end
subgraph subGraph0["Feature Flags"]
TEST["cfg(test)"]
FEAT_1T["page-alloc-1t"]
FEAT_64G["page-alloc-64g"]
FEAT_4G["page-alloc-4g"]
DEFAULT["default/page-alloc-256m"]
end
BITALLOC_16M --> CAP_64G
BITALLOC_1M --> CAP_4G
BITALLOC_256M --> CAP_1T
BITALLOC_64K --> CAP_256M
DEFAULT --> BITALLOC_64K
FEAT_1T --> BITALLOC_256M
FEAT_4G --> BITALLOC_1M
FEAT_64G --> BITALLOC_16M
TEST --> BITALLOC_1M
Sources: src/bitmap.rs(L9 - L26)
The configuration table shows the relationship between features and memory limits:
| Feature Flag | BitAlloc Type | Max Pages | Max Memory (4KB pages) |
|---|---|---|---|
| test | BitAlloc1M | 1,048,576 | 4GB |
| page-alloc-1t | BitAlloc256M | 268,435,456 | 1TB |
| page-alloc-64g | BitAlloc16M | 16,777,216 | 64GB |
| page-alloc-4g | BitAlloc1M | 1,048,576 | 4GB |
| page-alloc-256m(default) | BitAlloc64K | 65,536 | 256MB |
Core Implementation Details
Memory Layout and Base Address Calculation
The allocator manages memory regions by calculating a base address aligned to 1GB boundaries and tracking page indices relative to this base.
flowchart TD
subgraph subGraph2["Bitmap Initialization"]
INSERT_RANGE["inner.insert(start_idx..start_idx + total_pages)"]
end
subgraph subGraph1["Base Address Calculation"]
CALC_BASE["base = align_down(start, MAX_ALIGN_1GB)"]
REL_START["relative_start = start - base"]
START_IDX["start_idx = relative_start / PAGE_SIZE"]
end
subgraph subGraph0["Memory Region Setup"]
INPUT_START["Input: start, size"]
ALIGN_START["align_up(start, PAGE_SIZE)"]
ALIGN_END["align_down(start + size, PAGE_SIZE)"]
CALC_TOTAL["total_pages = (end - start) / PAGE_SIZE"]
end
ALIGN_END --> CALC_TOTAL
ALIGN_START --> CALC_BASE
ALIGN_START --> CALC_TOTAL
CALC_BASE --> REL_START
CALC_TOTAL --> INSERT_RANGE
INPUT_START --> ALIGN_END
INPUT_START --> ALIGN_START
REL_START --> START_IDX
START_IDX --> INSERT_RANGE
Sources: src/bitmap.rs(L54 - L70) src/bitmap.rs(L7)
Page Allocation Process
The allocator provides two allocation methods: general allocation with alignment requirements and allocation at specific addresses.
sequenceDiagram
participant Client as Client
participant BitmapPageAllocator as BitmapPageAllocator
participant BitAllocUsed as BitAllocUsed
Note over Client,BitAllocUsed: General Page Allocation
Client ->> BitmapPageAllocator: alloc_pages(num_pages, align_pow2)
BitmapPageAllocator ->> BitmapPageAllocator: Validate alignment parameters
BitmapPageAllocator ->> BitmapPageAllocator: Convert align_pow2 to page units
alt num_pages == 1
BitmapPageAllocator ->> BitAllocUsed: alloc()
else num_pages > 1
BitmapPageAllocator ->> BitAllocUsed: alloc_contiguous(None, num_pages, align_log2)
end
BitAllocUsed -->> BitmapPageAllocator: Option<page_idx>
BitmapPageAllocator ->> BitmapPageAllocator: Convert to address: idx * PAGE_SIZE + base
BitmapPageAllocator ->> BitmapPageAllocator: Update used_pages count
BitmapPageAllocator -->> Client: AllocResult<usize>
Note over Client,BitAllocUsed: Specific Address Allocation
Client ->> BitmapPageAllocator: alloc_pages_at(base, num_pages, align_pow2)
BitmapPageAllocator ->> BitmapPageAllocator: Validate alignment and base address
BitmapPageAllocator ->> BitmapPageAllocator: Calculate target page index
BitmapPageAllocator ->> BitAllocUsed: alloc_contiguous(Some(idx), num_pages, align_log2)
BitAllocUsed -->> BitmapPageAllocator: Option<page_idx>
BitmapPageAllocator -->> Client: AllocResult<usize>
Sources: src/bitmap.rs(L80 - L100) src/bitmap.rs(L103 - L131)
Allocation Constraints and Validation
The allocator enforces several constraints to ensure correct operation:
Alignment Validation Process
flowchart TD
subgraph Results["Results"]
VALID["Valid Parameters"]
INVALID["AllocError::InvalidParam"]
end
subgraph subGraph2["Parameter Validation"]
CHECK_NUM_PAGES["num_pages > 0"]
CHECK_PAGE_SIZE["PAGE_SIZE.is_power_of_two()"]
end
subgraph subGraph1["Address Validation (alloc_pages_at)"]
CHECK_BASE_ALIGN["is_aligned(base, align_pow2)"]
end
subgraph subGraph0["Alignment Checks"]
CHECK_MAX["align_pow2 <= MAX_ALIGN_1GB"]
CHECK_PAGE_ALIGN["is_aligned(align_pow2, PAGE_SIZE)"]
CHECK_POW2["(align_pow2 / PAGE_SIZE).is_power_of_two()"]
end
CHECK_BASE_ALIGN --> INVALID
CHECK_BASE_ALIGN --> VALID
CHECK_MAX --> INVALID
CHECK_MAX --> VALID
CHECK_NUM_PAGES --> INVALID
CHECK_NUM_PAGES --> VALID
CHECK_PAGE_ALIGN --> INVALID
CHECK_PAGE_ALIGN --> VALID
CHECK_PAGE_SIZE --> VALID
CHECK_POW2 --> INVALID
CHECK_POW2 --> VALID
Sources: src/bitmap.rs(L82 - L88) src/bitmap.rs(L111 - L121) src/bitmap.rs(L55)
Key constraints include:
PAGE_SIZEmust be a power of two- Maximum alignment is 1GB (
MAX_ALIGN_1GB = 0x4000_0000) - Alignment must be a multiple of
PAGE_SIZE - Alignment (in page units) must be a power of two
- For
alloc_pages_at, the base address must be aligned to the requested alignment
Memory Management Operations
Deallocation Process
flowchart TD
subgraph subGraph1["Deallocation Flow"]
INPUT["dealloc_pages(pos, num_pages)"]
ASSERT_ALIGN["assert: pos aligned to PAGE_SIZE"]
CALC_IDX["idx = (pos - base) / PAGE_SIZE"]
UPDATE_COUNT["used_pages -= num_pages"]
subgraph subGraph0["Bitmap Update"]
SINGLE["num_pages == 1:inner.dealloc(idx)"]
MULTI["num_pages > 1:inner.dealloc_contiguous(idx, num_pages)"]
end
end
ASSERT_ALIGN --> CALC_IDX
CALC_IDX --> MULTI
CALC_IDX --> SINGLE
INPUT --> ASSERT_ALIGN
MULTI --> UPDATE_COUNT
SINGLE --> UPDATE_COUNT
Sources: src/bitmap.rs(L133 - L147)
Statistics Tracking
The allocator maintains three key statistics accessible through the PageAllocator interface:
| Method | Description | Implementation |
|---|---|---|
| total_pages() | Total pages managed | Returnsself.total_pages |
| used_pages() | Currently allocated pages | Returnsself.used_pages |
| available_pages() | Free pages remaining | Returnstotal_pages - used_pages |
Sources: src/bitmap.rs(L149 - L159)
Usage Patterns and Testing
The test suite demonstrates typical usage patterns and validates the allocator's behavior across different scenarios.
Single Page Allocation Example
sequenceDiagram
participant TestCode as Test Code
participant BitmapPageAllocator as BitmapPageAllocator
TestCode ->> BitmapPageAllocator: new()
TestCode ->> BitmapPageAllocator: init(PAGE_SIZE, PAGE_SIZE)
Note over BitmapPageAllocator: total_pages=1, used_pages=0
TestCode ->> BitmapPageAllocator: alloc_pages(1, PAGE_SIZE)
BitmapPageAllocator -->> TestCode: addr = 0x1000
Note over BitmapPageAllocator: used_pages=1, available_pages=0
TestCode ->> BitmapPageAllocator: dealloc_pages(0x1000, 1)
Note over BitmapPageAllocator: used_pages=0, available_pages=1
TestCode ->> BitmapPageAllocator: alloc_pages(1, PAGE_SIZE)
BitmapPageAllocator -->> TestCode: addr = 0x1000 (reused)
Sources: src/bitmap.rs(L168 - L190)
Large Memory Region Testing
The test suite validates operation with large memory regions (2GB) and various allocation patterns:
- Sequential allocation/deallocation of 1, 10, 100, 1000 pages
- Alignment testing with powers of 2 from
PAGE_SIZEtoMAX_ALIGN_1GB - Multiple concurrent allocations with different alignments
- Specific address allocation using
alloc_pages_at
Sources: src/bitmap.rs(L193 - L327)
The allocator demonstrates robust behavior across different memory sizes and allocation patterns while maintaining efficient bitmap-based tracking of page allocation status.