Buddy System Allocator
Relevant source files
This document covers the BuddyByteAllocator
implementation, which provides byte-granularity memory allocation using the buddy system algorithm. This allocator is one of several byte-level allocators available in the crate and is enabled through the buddy
feature flag.
For information about the overall trait architecture and how allocators integrate with the system, see Architecture and Design. For other byte-level allocator implementations, see Slab Allocator and TLSF Allocator.
Implementation Overview
The BuddyByteAllocator
serves as a wrapper around the external buddy_system_allocator::Heap
crate, adapting it to the crate's trait-based interface. The implementation focuses on providing a consistent API while leveraging the performance characteristics of the buddy system algorithm.
Core Structure
flowchart TD subgraph subGraph3["Key Methods"] INIT["init(start, size)"] ADD["add_memory(start, size)"] ALLOC["alloc(layout)"] DEALLOC["dealloc(pos, layout)"] STATS["total_bytes(), used_bytes(), available_bytes()"] end subgraph subGraph2["External Dependency"] EXT["buddy_system_allocator::Heap<32>"] end subgraph subGraph1["Trait Implementations"] BASE["BaseAllocator"] BYTE["ByteAllocator"] end subgraph subGraph0["BuddyByteAllocator Structure"] BUDDY["BuddyByteAllocator"] INNER["inner: Heap<32>"] end BASE --> ADD BASE --> INIT BUDDY --> BASE BUDDY --> BYTE BUDDY --> INNER BYTE --> ALLOC BYTE --> DEALLOC BYTE --> STATS INNER --> EXT
Sources: src/buddy.rs(L14 - L25)
The allocator uses a fixed const generic parameter of 32, which determines the maximum order of buddy blocks that can be allocated from the underlying Heap<32>
implementation.
Component | Type | Purpose |
---|---|---|
BuddyByteAllocator | Struct | Main allocator wrapper |
inner | Heap<32> | Underlying buddy system implementation |
Generic Parameter | 32 | Maximum buddy block order |
Trait Implementation Details
BaseAllocator Implementation
The BaseAllocator
trait provides fundamental memory management operations for initializing and expanding the allocator's memory pool.
flowchart TD subgraph subGraph2["Safety Considerations"] UNSAFE_INIT["unsafe { inner.init() }"] UNSAFE_ADD["unsafe { inner.add_to_heap() }"] end subgraph subGraph1["Internal Operations"] HEAP_INIT["inner.init(start, size)"] HEAP_ADD["inner.add_to_heap(start, start + size)"] end subgraph subGraph0["BaseAllocator Methods"] INIT_CALL["init(start: usize, size: usize)"] ADD_CALL["add_memory(start: usize, size: usize)"] end ADD_CALL --> HEAP_ADD HEAP_ADD --> UNSAFE_ADD HEAP_INIT --> UNSAFE_INIT INIT_CALL --> HEAP_INIT
Sources: src/buddy.rs(L27 - L36)
The init
method performs initial setup of the memory region, while add_memory
allows dynamic expansion of the allocator's available memory pool. Both operations delegate to the underlying Heap
implementation using unsafe blocks.
ByteAllocator Implementation
The ByteAllocator
trait provides the core allocation and deallocation interface along with memory usage statistics.
flowchart TD subgraph Statistics["Statistics"] TOTAL["total_bytes()"] STATS_TOTAL["inner.stats_total_bytes()"] USED["used_bytes()"] STATS_ACTUAL["inner.stats_alloc_actual()"] AVAILABLE["available_bytes()"] CALC_AVAIL["total - actual"] DEALLOC_REQ["dealloc(pos: NonNull, layout: Layout)"] HEAP_DEALLOC["inner.dealloc(pos, layout)"] ALLOC_REQ["alloc(layout: Layout)"] HEAP_ALLOC["inner.alloc(layout)"] end subgraph subGraph0["Allocation Flow"] ERROR_MAP["map_err(|_| AllocError::NoMemory)"] RESULT["AllocResult>"] subgraph subGraph1["Deallocation Flow"] TOTAL["total_bytes()"] STATS_TOTAL["inner.stats_total_bytes()"] DEALLOC_REQ["dealloc(pos: NonNull, layout: Layout)"] HEAP_DEALLOC["inner.dealloc(pos, layout)"] ALLOC_REQ["alloc(layout: Layout)"] HEAP_ALLOC["inner.alloc(layout)"] end end ALLOC_REQ --> HEAP_ALLOC AVAILABLE --> CALC_AVAIL DEALLOC_REQ --> HEAP_DEALLOC ERROR_MAP --> RESULT HEAP_ALLOC --> ERROR_MAP TOTAL --> STATS_TOTAL USED --> STATS_ACTUAL
Sources: src/buddy.rs(L38 - L58)
Method | Return Type | Description |
---|---|---|
alloc | AllocResult<NonNull | Allocates memory according to layout requirements |
dealloc | () | Deallocates previously allocated memory |
total_bytes | usize | Total memory managed by allocator |
used_bytes | usize | Currently allocated memory |
available_bytes | usize | Calculated as total minus used bytes |
Memory Management Characteristics
Buddy System Algorithm
The buddy system algorithm manages memory by maintaining blocks in powers of two sizes. When a block is split, it creates two "buddy" blocks that can be efficiently merged when both become free.
Error Handling
The allocator implements a simple error mapping strategy where allocation failures from the underlying Heap
are converted to AllocError::NoMemory
. This provides a consistent error interface across all allocator implementations in the crate.
Memory Statistics
The implementation provides three key statistics through delegation to the underlying heap:
- Total bytes: Complete memory pool size managed by the allocator
- Used bytes: Currently allocated memory tracked by the heap
- Available bytes: Computed difference representing allocatable memory
Sources: src/buddy.rs(L47 - L57)
Integration with Feature System
The BuddyByteAllocator
is conditionally compiled based on the buddy
feature flag defined in the crate's feature system. When enabled, it provides byte-granularity allocation as an alternative to page-based or other allocation strategies.
The allocator integrates with the crate's unified interface through the trait implementations, allowing it to be used interchangeably with other ByteAllocator
implementations depending on the application's requirements.
Sources: src/buddy.rs(L1 - L59)