diff --git a/src/small_allocator.c b/src/small_allocator.c index 519d563..695c813 100644 --- a/src/small_allocator.c +++ b/src/small_allocator.c @@ -11,12 +11,14 @@ typedef struct BlockHeader { size_t size_and_flags; // size | free_bit struct BlockHeader* next; + struct BlockHeader* prev; + // Padding to ensure we always return 16 byte aligned ponters + // remove padding & set ALIGNMENT to 8 to get 8 byte alignmet + // (for 64 bit systems, 32 bit systems might need other adjustments) + uint8_t pad[32 - (sizeof(size_t) + 2*sizeof(void*))]; } BlockHeader; -//Note: -// On 64‑bit systems, allocated pointers are 16‑byte aligned. -// On 32‑bit systems, allocated pointers are 8‑byte aligned. _Static_assert(sizeof(BlockHeader) % ALIGNMENT == 0, "BlockHeader size must be a multiple of ALIGNMENT"); @@ -58,17 +60,17 @@ void small_allocator_init(SmallAllocator* a, void* backing_store, size_t size) { a->size = size; BlockHeader* first = (BlockHeader*)a->base; - size_t usable = size - sizeof(BlockHeader); - usable = ALIGN(usable); + size_t usable = ALIGN(size - sizeof(BlockHeader)); first->size_and_flags = usable | BLOCK_FREE; first->next = NULL; + first->prev = NULL; a->heap_start = first; a->last_alloc = first; } -/* --- Block splitting --- */ +/* Splitting */ static void split_block(BlockHeader* block, size_t size) { size = ALIGN(size); @@ -81,35 +83,40 @@ static void split_block(BlockHeader* block, size_t size) { BlockHeader* new_block = (BlockHeader*)(base + sizeof(BlockHeader) + size); - size_t new_size = bsize - size - sizeof(BlockHeader); - new_size = ALIGN(new_size); + size_t new_size = ALIGN(bsize - size - sizeof(BlockHeader)); block_set_size(block, size); block_set_used(block); new_block->size_and_flags = new_size | BLOCK_FREE; new_block->next = block->next; + new_block->prev = block; + + if (block->next) + block->next->prev = new_block; block->next = new_block; } -/* --- Adjacent-only coalescing --- */ +/* Coalescing */ static void merge_with_next(BlockHeader* block) { BlockHeader* next = block->next; if (!next || !block_is_free(next)) return; - size_t new_size = block_size(block) + - sizeof(BlockHeader) + - block_size(next); + size_t new_size = ALIGN(block_size(block) + + sizeof(BlockHeader) + + block_size(next)); - new_size = ALIGN(new_size); block_set_size(block, new_size); block->next = next->next; + + if (next->next) + next->next->prev = block; } -/* --- Allocation (next-fit) --- */ +/* Allocation (next-fit) */ void* small_alloc(SmallAllocator* a, size_t size) { if (size == 0) @@ -133,7 +140,7 @@ void* small_alloc(SmallAllocator* a, size_t size) { return NULL; } -/* --- Free --- */ +/* Free */ void small_free(SmallAllocator* a, void* ptr) { if (!ptr) @@ -146,16 +153,10 @@ void small_free(SmallAllocator* a, void* ptr) { merge_with_next(block); - BlockHeader* prev = NULL; - BlockHeader* curr = a->heap_start; - - while (curr && curr != block) { - prev = curr; - curr = curr->next; - } - - if (prev && block_is_free(prev)) { + if (block->prev && block_is_free(block->prev)) { + BlockHeader* prev = block->prev; merge_with_next(prev); + if (a->last_alloc == block) a->last_alloc = prev; }