Expand description
§Attachable Slab Allocator: The Manual 🦀
A high-performance, $O(1)$, Master-Slave slab allocator designed for no_std environments,
kernels, and embedded systems.
§1. The Core Philosophy: “The Bridge”
This library provides the logic for dividing memory into fixed-size “slots”, but it does
not know how to acquire raw memory from the system. You must provide two “bridges”
(hooks) using the define_allocation_hooks! macro.
Note: If these hooks are not defined, your code will fail to link.
§Example: Setting up Hooks
use std::alloc::{alloc, dealloc, Layout};
use core::ptr::NonNull;
use attachable_slab_allocator::{define_allocation_hooks, Result};
unsafe fn my_alloc(layout: Layout) -> Option<NonNull<u8>> {
NonNull::new(alloc(layout))
}
unsafe fn my_free(ptr: NonNull<u8>, layout: Layout) -> Result<()> {
dealloc(ptr.as_ptr(), layout);
Ok(())
}
define_allocation_hooks!(my_alloc, my_free);§2. Using SlabCache
SlabCache is the primary interface. It is reference-counted and handles the
creation of Slaves when memory runs out.
§Constraints on T and SLAB_SIZE:
TSize: Must be at least 4 bytes (u32) to store internal freelist indices.TAlignment: Must be at leastu32aligned.SLAB_SIZE: Must be a Power of Two.- Slab Alignment: The allocator enforces that
Slab Alignment == SLAB_SIZE. This is checked at compile time.
§Example: Allocation
use attachable_slab_allocator::{SlabCache, locks::SpinLock};
// Create a cache for u64, using a 4096-byte slab size.
let mut cache = SlabCache::<u64, SpinLock, 4096>::new().unwrap();
// Allocate a smart pointer (SlabBox)
let mut boxed_val = cache.alloc().unwrap();
*boxed_val = 12345;
// boxed_val is dropped here, returning memory to the slab automatically.§3. Synchronization and Locks
The allocator uses a Master-Slave architecture. The Master Slab holds the lock that protects the entire hierarchy (itself and all its Slaves).
§Custom Locks:
You can implement the LockTrait for your own synchronization primitive.
Requirement: The lock structure must be smaller than or equal to 16 bytes
to ensure the slab header remains efficient.
§4. SlabBox: Independence & RAII
SlabBox<T> is a smart pointer that automatically returns its memory to the slab
when dropped. It is independent of the SlabCache. You can clone the cache,
drop the cache, or move the SlabBox to another thread—it will always find its
home slab using the “Alignment == Size” bitmask trick.
§5. Internal Mechanisms
- Link Lists: The allocator uses internal intrusive doubly linked lists to manage slabs. Metadata is stored inside the slab headers.
- Freelist: Within each slab, free slots are tracked using an intrusive stack (the slot memory itself stores the index of the next free slot).
§6. Error Handling and Safety
§Result and SlabError:
Operations return a Result<T, SlabError>. Common errors include:
OutOfMemory: System hooks failed or capacity reached.InvalidPointer: Magic header check failed (indicates corruption or use-after-free).
§⚠️ Critical Safety:
- Internal Panic/Corruption: If you write outside the bounds of your type
T, you might overwrite theSlabheader or the internal freelist. This can lead to internal panics or silent data corruption. - Double Free: Manually freeing the same pointer twice will corrupt the
internal list. Always prefer
SlabBoxfor automatic management.
Modules§
- locks
- Locks Module
Macros§
- define_
allocation_ hooks - The primary macro used to satisfy the allocator’s linker requirements.
- get_
field_ ptr - Safely calculates the address of a field from a
NonNullpointer.
Structs§
- SlabBox
- A smart pointer to an object of type
Tallocated in a slab. - Slab
Cache - A thread-safe, reference-counted handle to a Master-Slave slab hierarchy.
Enums§
- Slab
Error - Represents the types of errors that can occur during memory allocation operations.
Type Aliases§
- Result
- A specialized
Resulttype for memory allocation operations.