Prefix functions with l in lalloc

This commit is contained in:
Nils O. Selåsdal
2026-05-11 22:45:13 +02:00
parent c9a51a85ea
commit ce0e998d2a
3 changed files with 61 additions and 61 deletions
+10 -10
View File
@@ -9,15 +9,15 @@ extern "C" {
#endif #endif
// Internal header added in front of each allocation // Internal header added in front of each allocation
typedef struct BlockHeader BlockHeader; typedef struct LBlockHeader LBlockHeader;
struct BlockHeader { struct LBlockHeader {
uint32_t next; // offset from base uint32_t next; // offset from base
uint32_t prev; // offset from base uint32_t prev; // offset from base
uint32_t size_and_flags; // size | free_bit uint32_t size_and_flags; // size | free_bit
// Padding to ensure we always return 16 byte aligned pointers. // Padding to ensure we always return 16 byte aligned pointers.
uint8_t pad[4]; uint8_t pad[4];
}; };
_Static_assert(sizeof(BlockHeader) == 16, "sizeof(BlockHeader) is not 16"); _Static_assert(sizeof(LBlockHeader) == 16, "sizeof(BlockHeader) is not 16");
/** /**
* General purpose allocator. * General purpose allocator.
@@ -32,10 +32,10 @@ _Static_assert(sizeof(BlockHeader) == 16, "sizeof(BlockHeader) is not 16");
*/ */
typedef struct LAlloc LAlloc; typedef struct LAlloc LAlloc;
struct LAlloc { struct LAlloc {
uint8_t *base; // backing store uint8_t *base; // backing store
uint32_t size; // total size uint32_t size; // total size
BlockHeader *heap_start; // first block LBlockHeader *heap_start; // first block
BlockHeader *next_alloc; // start of free block search LBlockHeader *next_alloc; // start of free block search
}; };
void lalloc_init(LAlloc *allocator, void *backing_store, uint32_t size); void lalloc_init(LAlloc *allocator, void *backing_store, uint32_t size);
@@ -43,9 +43,9 @@ void lalloc_init(LAlloc *allocator, void *backing_store, uint32_t size);
void *lalloc(LAlloc *allocator, uint32_t size); void *lalloc(LAlloc *allocator, uint32_t size);
void lfree(LAlloc *allocator, void *ptr); void lfree(LAlloc *allocator, void *ptr);
BlockHeader *block_from_offset(const LAlloc *allocator, uint32_t offset); LBlockHeader *lblock_from_offset(const LAlloc *allocator, uint32_t offset);
uint32_t block_size(const BlockHeader *block); uint32_t lblock_size(const LBlockHeader *block);
int block_is_free(const BlockHeader *block); int lblock_is_free(const LBlockHeader *block);
#ifdef __ccplusplus #ifdef __ccplusplus
} // extern "C" } // extern "C"
+48 -48
View File
@@ -3,49 +3,49 @@
#include <assert.h> #include <assert.h>
#include "lalloc.h" #include "lalloc.h"
#define ALIGNMENT sizeof(BlockHeader) #define ALIGNMENT sizeof(LBlockHeader)
#define ALIGN_UP(n) (((n) + (__typeof__(n))(ALIGNMENT) - 1) & ~((__typeof__(n))(ALIGNMENT) - 1)) #define ALIGN_UP(n) (((n) + (__typeof__(n))(ALIGNMENT) - 1) & ~((__typeof__(n))(ALIGNMENT) - 1))
#define ALIGN_DOWN(n) ((n) & ~((__typeof__(n))(ALIGNMENT) - 1)) #define ALIGN_DOWN(n) ((n) & ~((__typeof__(n))(ALIGNMENT) - 1))
#define NULL_BLOCK (0xffffffff) #define NULL_BLOCK (0xffffffff)
#define BLOCK_FREE ((uint32_t)1) #define BLOCK_FREE ((uint32_t)1)
static inline void block_set_free(BlockHeader *block) static inline void lblock_set_free(LBlockHeader *block)
{ {
block->size_and_flags |= BLOCK_FREE; block->size_and_flags |= BLOCK_FREE;
} }
static inline void block_set_used(BlockHeader *block) static inline void lblock_set_used(LBlockHeader *block)
{ {
block->size_and_flags &= ~BLOCK_FREE; block->size_and_flags &= ~BLOCK_FREE;
} }
static inline void block_set_size(BlockHeader *block, uint32_t size) static inline void lblock_set_size(LBlockHeader *block, uint32_t size)
{ {
uint32_t flags = block->size_and_flags & BLOCK_FREE; uint32_t flags = block->size_and_flags & BLOCK_FREE;
block->size_and_flags = size | flags; block->size_and_flags = size | flags;
} }
uint32_t block_size(const BlockHeader *block) uint32_t lblock_size(const LBlockHeader *block)
{ {
return block->size_and_flags & ~BLOCK_FREE; return block->size_and_flags & ~BLOCK_FREE;
} }
int block_is_free(const BlockHeader *block) int lblock_is_free(const LBlockHeader *block)
{ {
return (block->size_and_flags & BLOCK_FREE) != 0; return (block->size_and_flags & BLOCK_FREE) != 0;
} }
inline BlockHeader *block_from_offset(const LAlloc *allocator, uint32_t offset) LBlockHeader *lblock_from_offset(const LAlloc *allocator, uint32_t offset)
{ {
if (offset == NULL_BLOCK) { if (offset == NULL_BLOCK) {
return NULL; return NULL;
} }
return (BlockHeader *)((uintptr_t)allocator->base + offset); return (LBlockHeader *)((uintptr_t)allocator->base + offset);
} }
static inline uint32_t bh_offset(LAlloc *allocator, BlockHeader *block) static inline uint32_t lbh_offset(LAlloc *allocator, LBlockHeader *block)
{ {
if (block == NULL) { if (block == NULL) {
return NULL_BLOCK; return NULL_BLOCK;
@@ -54,46 +54,46 @@ static inline uint32_t bh_offset(LAlloc *allocator, BlockHeader *block)
return (uint32_t)((uintptr_t)block - (uintptr_t)allocator->base); return (uint32_t)((uintptr_t)block - (uintptr_t)allocator->base);
} }
static void maybe_split_block(LAlloc *allocator, BlockHeader *block, uint32_t size) static void lmaybe_split_block(LAlloc *allocator, LBlockHeader *block, uint32_t size)
{ {
// assumes size is already aligned // assumes size is already aligned
uint32_t bsize = block_size(block); uint32_t bsize = lblock_size(block);
if (bsize < size + sizeof(BlockHeader) + ALIGNMENT) { if (bsize < size + sizeof(LBlockHeader) + ALIGNMENT) {
return; return;
} }
uint8_t *base = (uint8_t *)block; uint8_t *base = (uint8_t *)block;
BlockHeader *new_block = (BlockHeader *)(base + sizeof(BlockHeader) + size); LBlockHeader *new_block = (LBlockHeader *)(base + sizeof(LBlockHeader) + size);
uint32_t new_size = bsize - size - sizeof(BlockHeader); uint32_t new_size = bsize - size - sizeof(LBlockHeader);
block_set_size(block, size); lblock_set_size(block, size);
block_set_used(block); lblock_set_used(block);
new_block->size_and_flags = new_size | BLOCK_FREE; new_block->size_and_flags = new_size | BLOCK_FREE;
new_block->next = block->next; new_block->next = block->next;
new_block->prev = bh_offset(allocator, block); new_block->prev = lbh_offset(allocator, block);
BlockHeader *next = block_from_offset(allocator, new_block->next); LBlockHeader *next = lblock_from_offset(allocator, new_block->next);
if (next) { if (next) {
next->prev = bh_offset(allocator, new_block); next->prev = lbh_offset(allocator, new_block);
} }
block->next = bh_offset(allocator, new_block); block->next = lbh_offset(allocator, new_block);
} }
static void merge_with_next(LAlloc *allocator, BlockHeader *block) static void lmerge_with_next(LAlloc *allocator, LBlockHeader *block)
{ {
BlockHeader *next = block_from_offset(allocator, block->next); LBlockHeader *next = lblock_from_offset(allocator, block->next);
if (next == NULL || !block_is_free(next)) return; if (next == NULL || !lblock_is_free(next)) return;
uint32_t new_size = block_size(block) + sizeof(BlockHeader) + block_size(next); uint32_t new_size = lblock_size(block) + sizeof(LBlockHeader) + lblock_size(next);
block_set_size(block, new_size); lblock_set_size(block, new_size);
block->next = next->next; block->next = next->next;
BlockHeader *nextnext = block_from_offset(allocator, next->next); LBlockHeader *nextnext = lblock_from_offset(allocator, next->next);
if (nextnext) nextnext->prev = bh_offset(allocator, block); if (nextnext) nextnext->prev = lbh_offset(allocator, block);
// note - caller have to adjust next_alloc on return // note - caller have to adjust next_alloc on return
} }
@@ -101,18 +101,18 @@ void lalloc_init(LAlloc *allocator, void *backing_store, uint32_t size)
{ {
// backing store must be aligned, otherwise all alignment guarantees are lies // backing store must be aligned, otherwise all alignment guarantees are lies
assert(((uintptr_t)backing_store & (ALIGNMENT - 1)) == 0); assert(((uintptr_t)backing_store & (ALIGNMENT - 1)) == 0);
assert(size >= sizeof(BlockHeader)); assert(size >= sizeof(LBlockHeader));
assert(size < 0xfffffff0); assert(size < 0xfffffff0);
allocator->base = backing_store; allocator->base = backing_store;
allocator->size = size; allocator->size = size;
BlockHeader *first = backing_store; LBlockHeader *first = backing_store;
// allocator logic requires the first block to be properly aligned // allocator logic requires the first block to be properly aligned
// as well as size being eligned. // as well as size being eligned.
uint32_t usable = ALIGN_DOWN(size) - sizeof(BlockHeader); uint32_t usable = ALIGN_DOWN(size) - sizeof(LBlockHeader);
block_set_free(first); lblock_set_free(first);
block_set_size(first, usable); lblock_set_size(first, usable);
first->next = NULL_BLOCK; first->next = NULL_BLOCK;
first->prev = NULL_BLOCK; first->prev = NULL_BLOCK;
@@ -127,18 +127,18 @@ void *lalloc(LAlloc *allocator, uint32_t size)
} }
size = ALIGN_UP(size); size = ALIGN_UP(size);
BlockHeader *start = allocator->next_alloc ? allocator->next_alloc : allocator->heap_start; LBlockHeader *start = allocator->next_alloc ? allocator->next_alloc : allocator->heap_start;
BlockHeader *curr = start; LBlockHeader *curr = start;
do { do {
if (block_is_free(curr) && block_size(curr) >= size) { if (lblock_is_free(curr) && lblock_size(curr) >= size) {
maybe_split_block(allocator, curr, size); lmaybe_split_block(allocator, curr, size);
block_set_used(curr); lblock_set_used(curr);
BlockHeader *next = block_from_offset(allocator, curr->next); LBlockHeader *next = lblock_from_offset(allocator, curr->next);
allocator->next_alloc = next ? next : allocator->heap_start; allocator->next_alloc = next ? next : allocator->heap_start;
return (uint8_t *)curr + sizeof(BlockHeader); return (uint8_t *)curr + sizeof(LBlockHeader);
} }
BlockHeader *next = block_from_offset(allocator, curr->next); LBlockHeader *next = lblock_from_offset(allocator, curr->next);
curr = next ? next : allocator->heap_start; curr = next ? next : allocator->heap_start;
} while (curr != start); } while (curr != start);
@@ -151,18 +151,18 @@ void lfree(LAlloc *allocator, void *ptr)
return; return;
} }
BlockHeader *block = (BlockHeader *)((uint8_t *)ptr - sizeof(BlockHeader)); LBlockHeader *block = (LBlockHeader *)((uint8_t *)ptr - sizeof(LBlockHeader));
assert((uint8_t *)ptr - sizeof(BlockHeader) >= allocator->base && (uint8_t *)ptr < allocator->base + allocator->size); assert((uint8_t *)ptr - sizeof(LBlockHeader) >= allocator->base && (uint8_t *)ptr < allocator->base + allocator->size);
// double free detection // double free detection
assert(!block_is_free(block)); assert(!lblock_is_free(block));
block_set_free(block); lblock_set_free(block);
merge_with_next(allocator, block); lmerge_with_next(allocator, block);
BlockHeader *prev = block_from_offset(allocator, block->prev); LBlockHeader *prev = lblock_from_offset(allocator, block->prev);
if (prev != NULL && block_is_free(prev)) { if (prev != NULL && lblock_is_free(prev)) {
merge_with_next(allocator, prev); lmerge_with_next(allocator, prev);
allocator->next_alloc = prev; allocator->next_alloc = prev;
} else { } else {
allocator->next_alloc = block; allocator->next_alloc = block;
+3 -3
View File
@@ -7,8 +7,8 @@
void debug_alloc(const LAlloc *allocator) void debug_alloc(const LAlloc *allocator)
{ {
puts("--debug start--"); puts("--debug start--");
for (BlockHeader *b = allocator->heap_start; b; b = block_from_offset(allocator, b->next)) { for (LBlockHeader *b = allocator->heap_start; b; b = lblock_from_offset(allocator, b->next)) {
printf("Block size %u free %d prev %u next %u \n", block_size(b), block_is_free(b), b->prev, b->next); printf("Block size %u free %d prev %u next %u \n", lblock_size(b), lblock_is_free(b), b->prev, b->next);
} }
puts("--debug end--"); puts("--debug end--");
} }
@@ -16,7 +16,7 @@ void debug_alloc(const LAlloc *allocator)
[[gnu::aligned(16)]] char buff[1023]; [[gnu::aligned(16)]] char buff[1023];
int main(void) int main(void)
{ {
printf("bh size %zu\n", sizeof(BlockHeader)); printf("bh size %zu\n", sizeof(LBlockHeader));
#define SZ 64 #define SZ 64
LAlloc a; LAlloc a;
char *ptrs[SZ]; char *ptrs[SZ];