#ifndef LALLOC_H_ #define LALLOC_H_ #include #include #ifdef __ccplusplus extern "C" { #endif // Internal header added in front of each allocation typedef struct BlockHeader BlockHeader; struct BlockHeader { uint32_t next; // offset from base uint32_t prev; // offset from base uint32_t size_and_flags; // size | free_bit // Padding to ensure we always return 16 byte aligned pointers. uint8_t pad[4]; }; _Static_assert(sizeof(BlockHeader) == 16, "sizeof(BlockHeader) is not 16"); /** * General purpose allocator. * - Allocated pointers are aligned to 16 bytes. * - Backing buffer must be aligned to 16 bytes start * - 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 * fragmentation to a minimum */ typedef struct LAlloc LAlloc; struct LAlloc { uint8_t *base; // backing store uint32_t size; // total size BlockHeader *heap_start; // first block BlockHeader *next_alloc; // start of free block search }; void lalloc_init(LAlloc *allocator, void *backing_store, uint32_t size); void *lalloc(LAlloc *allocator, uint32_t size); void lfree(LAlloc *allocator, void *ptr); BlockHeader *block_from_offset(const LAlloc *allocator, uint32_t offset); uint32_t block_size(const BlockHeader *block); int block_is_free(const BlockHeader *block); #ifdef __ccplusplus } // extern "C" #endif #endif