attachable-slab-allocator 0.1.0

A high-performance, $O(1)$, Master-Slave slab allocator designed for `no_std` environments, kernels, and embedded systems. This library provides fixed-size memory management with RAII safety while remaining completely agnostic of the underlying memory provider.
Documentation
//! # The Allocation Bridge: System Integration Hooks
//!
//! This module defines the "Pluggable" foundation of the entire slab allocator.
//!
//! ## The Problem: Where does the memory come from?
//! The `Slab` and `SlabCache` modules know how to *divide* memory into slots, but they
//! do not know how to *acquire* the raw blocks (slabs) from the operating system or hardware.
//!
//! ## The Solution: The Linker Contract
//! This file uses `extern "Rust"` blocks to declare two specific functions:
//! 1. `__attachable_slab_allocator_slab_allocation_func`
//! 2. `__attachable_slab_allocator_slab_free_func`
//!
//! These are **Required Symbols**. If you try to use this crate without defining these
//! functions, the compiler's **linker will fail** with an "undefined reference" error.
//! This ensures that you, the user, explicitly choose how raw memory is sourced.
//!
//! ## Using the Hooks
//! To "plug in" your allocator (e.g., `dlmalloc`, `buddy_allocator`, or even `std::alloc`),
//! you must use the [`define_allocation_hooks!`] macro exactly once in your project.
//!
//! ### Example: Connecting to the Rust Standard Heap
//! ```ignore
//! use std::alloc::{alloc, dealloc, Layout};
//! use core::ptr::NonNull;
//! use my_slab_crate::{define_allocation_hooks, Result};
//!
//! // 1. Define your raw allocation functions
//! unsafe fn my_alloc(layout: Layout) -> Option<NonNull<u8>> {
//!     let ptr = unsafe { alloc(layout) };
//!     NonNull::new(ptr)
//! }
//!
//! unsafe fn my_free(ptr: NonNull<u8>, layout: Layout) -> Result<()> {
//!     unsafe { dealloc(ptr.as_ptr(), layout) };
//!     Ok(())
//! }
//!
//! // 2. Register them globally using the macro
//! define_allocation_hooks!(my_alloc, my_free);
//! ```

use crate::defs::Result;
use core::{alloc::Layout, ptr::NonNull};

// External symbols that MUST be provided by the user at link-time.
//
// These are declared as `unsafe extern "Rust"` to allow for seamless integration
// with other Rust modules without C-style ABI overhead.
unsafe extern "Rust" {
    /// The global hook for acquiring a new Slab's raw memory.
    unsafe fn __attachable_slab_allocator_slab_allocation_func(
        layout: Layout,
    ) -> Option<NonNull<u8>>;

    /// The global hook for releasing a Slab's raw memory back to the system.
    unsafe fn __attachable_slab_allocator_slab_free_func(
        ptr: NonNull<u8>,
        layout: Layout,
    ) -> Result<()>;
}

/// Internal wrapper to call the system allocation hook.
///
/// This is used by `Slab::alloc_slab_ptr` when the cache needs to grow.
pub fn alloc_slab(layout: Layout) -> Option<NonNull<u8>> {
    unsafe { __attachable_slab_allocator_slab_allocation_func(layout) }
}

/// Internal wrapper to call the system deallocation hook.
///
/// This is used when a Master or Slave slab is fully empty and being retired.
pub fn free_slab(ptr: NonNull<u8>, layout: Layout) -> Result<()> {
    unsafe { __attachable_slab_allocator_slab_free_func(ptr, layout) }
}

/// The primary macro used to satisfy the allocator's linker requirements.
///
/// This macro defines the specific symbols the crate expects.
///
/// # Arguments
/// * `$alloc`: A function or path with signature `unsafe fn(Layout) -> Option<NonNull<u8>>`
/// * `$free`: A function or path with signature `unsafe fn(NonNull<u8>, Layout) -> Result<()>`
///
/// # Safety
/// The functions provided to this macro must correctly handle the `Layout` alignment
/// requirements. Slabs are typically page-aligned; your provided allocator must respect
/// the `layout.align()` property.
#[macro_export]
macro_rules! define_allocation_hooks {
    ($alloc:ident, $free:ident) => {
        /// Symbol exported for the linker to satisfy the allocation requirement.
        #[unsafe(no_mangle)]
        pub unsafe extern "Rust" fn __attachable_slab_allocator_slab_allocation_func(
            layout: Layout,
        ) -> Option<NonNull<u8>> {
            $alloc(layout)
        }

        /// Symbol exported for the linker to satisfy the deallocation requirement.
        #[unsafe(no_mangle)]
        pub unsafe extern "Rust" fn __attachable_slab_allocator_slab_free_func(
            ptr: NonNull<u8>,
            layout: Layout,
        ) -> Result<()> {
            $free(ptr, layout)
        }
    };
}