buddy-slab-allocator
A no_std two-level allocator for kernel and embedded environments, combining a buddy page allocator with per-CPU slab allocators.
Overview
The current implementation is built from three layers:
BuddyAllocatorManages one or more virtual memory sections in page units, with power-of-two splitting and merging.SlabAllocatorManages small objects up to 2048 bytes with fixed size classes.GlobalAllocatorCombines the two, routing small allocations to per-CPU slab caches and large allocations to buddy pages.
The design details are documented in docs/design.md.
Architecture
flowchart TD
GA[GlobalAllocator] --> B[SpinMutex<BuddyAllocator>]
GA --> OS[OsImpl]
GA --> PCS[per_cpu_slabs: *mut SpinMutex<SlabAllocator>[]]
B --> PM[PageMeta[]]
B --> FL[free_lists by order]
PCS --> SA[SlabAllocator]
SA --> SC[SlabCache x 9]
SC --> P[partial]
SC --> F[full]
SC --> E[empty]
SC --> H[SlabPageHeader]
Allocation routing
flowchart TD
A[GlobalAllocator::alloc(layout)] --> B{size <= 2048 and align <= 2048?}
B -- Yes --> C[Use current CPU slab allocator]
C --> D{Allocated from slab?}
D -- Yes --> E[Return object pointer]
D -- No --> F[Allocate pages from buddy as a new slab]
F --> G[add_slab and retry]
G --> E
B -- No --> H[Allocate pages directly from buddy]
H --> I[Return page-backed pointer]
Cross-CPU free path
sequenceDiagram
participant CPU1 as current CPU
participant H as SlabPageHeader
participant CPU0 as owner CPU
participant S as owner SlabAllocator
CPU1->>H: remote_free(obj_addr)
Note right of H: lock-free CAS push to remote_free_head
CPU1-->>CPU1: return immediately
CPU0->>S: next local alloc/dealloc under slab lock
S->>H: drain_remote_frees()
H-->>S: slots moved back into local bitmap
Features
- Buddy page allocation with splitting and merging
- Dynamic hot-add of managed regions via
add_region - Slab allocation for 9 size classes:
8..=2048 - Per-CPU slab caches
- Lock-free cross-CPU remote frees
- DMA32 / lowmem page allocation via
alloc_pages_lowmem no_stdfriendly- Built-in
logintegration - Standalone
BuddyAllocatorandSlabAllocatorusage
Add dependency
[]
= "0.2.0"
Using GlobalAllocator
use ;
use Layout;
const PAGE_SIZE: usize = 0x1000;
;
static OS: DemoOs = DemoOs;
let allocator = new;
let region_start = 0x8000_0000 as *mut u8;
let region_size = 16 * 1024 * 1024;
let region = unsafe ;
unsafe
let layout = from_size_align.unwrap;
let ptr = allocator.alloc.unwrap;
unsafe
// More memory can be added later.
let extra_region_start = 0x9000_0000 as *mut u8;
let extra_region_size = 8 * 1024 * 1024;
let extra_region = unsafe ;
unsafe
Using Buddy and Slab separately
For lower-level control, the two building blocks can be used directly.
use ;
use Layout;
const PAGE_SIZE: usize = 0x1000;
let region_start = 0x8000_0000 as *mut u8;
let region_size = 16 * 1024 * 1024;
let region = unsafe ;
let mut buddy = new;
unsafe
let mut slab = new;
let layout = from_size_align.unwrap;
let ptr = loop ;
match slab.dealloc
let extra_region_start = 0x9000_0000 as *mut u8;
let extra_region_size = 8 * 1024 * 1024;
let extra_region = unsafe ;
unsafe
Public API summary
GlobalAllocator<PAGE_SIZE>High-level allocator facade that can also implementGlobalAlloc, and supportsadd_region,managed_section_count,managed_section,managed_bytes, andallocated_bytes.BuddyAllocator<PAGE_SIZE>Standalone multi-section page allocator, supportinginit,add_region, section queries,managed_bytes, andallocated_bytes.ManagedSectionRead-only summary for one managed section.SlabAllocator<PAGE_SIZE>Standalone slab allocator.SizeClassFixed object size classes used by slab.SlabAllocResultAllocated(ptr)orNeedsSlab { size_class, pages }.SlabDeallocResultDoneorFreeSlab { base, pages }.OsImplProvidescurrent_cpu_idx()andvirt_to_phys()for per-CPU routing and lowmem selection.
managed_bytes counts only allocatable heap bytes and excludes region-prefix metadata.
allocated_bytes is backend page occupancy, not the exact sum of requested layout.size().
Testing
# Run normal tests
# Run tests serially
# Run ignored stress tests
# Check benchmarks compile
# Run benchmarks
More test notes are in tests/README.md.
License
Licensed under Apache-2.0.