Skip to main content

Crate attachable_slab_allocator

Crate attachable_slab_allocator 

Source
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:

  • T Size: Must be at least 4 bytes (u32) to store internal freelist indices.
  • T Alignment: Must be at least u32 aligned.
  • 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 the Slab header 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 SlabBox for 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 NonNull pointer.

Structs§

SlabBox
A smart pointer to an object of type T allocated in a slab.
SlabCache
A thread-safe, reference-counted handle to a Master-Slave slab hierarchy.

Enums§

SlabError
Represents the types of errors that can occur during memory allocation operations.

Type Aliases§

Result
A specialized Result type for memory allocation operations.