std1.0.0-beta-7 SafeC docs

Source alloc/tlsf.h

View in the repository

// SafeC Standard Library — TLSF (Two-Level Segregated Fit) Allocator
// O(1) real-time allocator with bounded fragmentation.
// Uses a two-level bitmap index for fast size-class lookup.
// Conforms to Allocator and ArenaAllocator (allocator.h): typed allocation
// is alloc_t / alloc_array_t / dealloc_t there.
#pragma once
#include <std/mem.h>
#include <std/alloc/allocator.h>

// First-level index: log2 buckets. Second-level: linear subdivisions.
// SL_COUNT = 16 subdivisions per FL bucket.
// FL_MAX = 32 covers allocations up to 4 GB.

#define TLSF_FL_MAX   32
#define TLSF_SL_COUNT 16

namespace std {

struct TlsfBlock {
    unsigned long size;       // block size (excluding header), low bit = free flag
    ?&TlsfBlock   prev_phys;  // previous physical block (for coalescing)
    ?&TlsfBlock   next_free;  // next free block in this size class
    ?&TlsfBlock   prev_free;  // prev free block in this size class

    // Query free bit (bit 0 of size field).
    int           is_free_() const;

    // Get actual usable size (mask off free bit).
    unsigned long block_size_() const;

    // Set free bit.
    void          set_free_();

    // Clear free bit (mark as used).
    void          set_used_();
};

struct TlsfAllocator {
    &heap unsigned char base;                                       // heap-backed managed memory
    int           owned;   // 1 if TlsfAllocator::new allocated base (destroy() frees it)
    unsigned long cap;
    unsigned int  fl_bitmap;                                  // first-level bitmap
    unsigned int  sl_bitmap[TLSF_FL_MAX];                     // second-level bitmaps
    ?&TlsfBlock   blocks[TLSF_FL_MAX * TLSF_SL_COUNT];       // free-list heads

    // A TLSF allocator over a user-provided heap buffer of `cap` bytes.
    static struct TlsfAllocator over([]unsigned char buffer);

    // A heap-backed TLSF allocator of `cap` bytes.
    static struct TlsfAllocator new(unsigned long cap);

    // Allocate `size` bytes aligned to `align`. O(1). Every block is
    // 8-aligned (given an 8-aligned buffer: always for TlsfAllocator::new), so align
    // is honoured up to 8 (0 is taken as 1). null when no free block fits,
    // or `align` is above 8 or not a power of two.
    ?&heap unsigned char alloc(unsigned long size, unsigned long align);

    // Free a previously allocated pointer (null: no-op). O(1). Aborts with
    // a diagnostic on a double free.
    void          dealloc(?&heap unsigned char ptr);

    // Free every block at once: the whole buffer is one free block again
    // (blocks handed out before become invalid). O(1) in the block count.
    void          reset();

    // Free the backing buffer (only valid for heap-backed allocators).
    void          drop();
    void          destroy() consume;   // = drop()

    // Internal helpers.
    void          insert_(&TlsfBlock blk);
    void          remove_(&TlsfBlock blk);
    ?&TlsfBlock   find_(unsigned long size);
};

// Compute first-level and second-level indices for a given size.
void tlsf_mapping_(unsigned long size, &int fl, &int sl);

} // namespace std