#pragma once #include "core.h" // Internal header added in front of each allocation typedef struct LBlockHeader LBlockHeader; struct LBlockHeader { U32 next; // offset from base U32 prev; // offset from base U32 size_and_flags; // size | free_bit // Padding to ensure we always return 16 byte aligned pointers. uint8_t pad[4]; }; _Static_assert(sizeof(LBlockHeader) == 16, "sizeof(BlockHeader) is not 16"); /** * General purpose allocator from a pre-defined backing store * - Allocated pointers are aligned to 16 bytes. * - Backing buffer must be aligned to 16 bytes * - 4Gb - 16 is max for the allocator backing buffer. * - Allocation of > 0 bytes returns a size aligned up to 16 bytes * - Allocation of 0 bytes returns a valid pointer with 0 usable space * The allocator maintains a doubly linked list of blocks, * when blocks are free'd, adjacent blocks are merged to keep. * This is also known as a buddy allocator * fragmentation to a minimum */ typedef struct LAlloc LAlloc; struct LAlloc { uint8_t *base; // backing store U32 size; // total size LBlockHeader *next_alloc; // start of free block search }; void lalloc_init(LAlloc *allocator, void *backing_store, U32 size); void *lalloc(LAlloc *allocator, U32 size); void lfree(LAlloc *allocator, void *ptr); LBlockHeader *lblock_from_offset(const LAlloc *allocator, U32 offset); U32 lblock_size(const LBlockHeader *block); int lblock_is_free(const LBlockHeader *block);