Free list allocator (rough)

This commit is contained in:
Imbus 2025-09-03 00:14:08 +02:00
parent 33d55b2cd2
commit 14d1667424

107
free_list.c Normal file
View file

@ -0,0 +1,107 @@
#include "stddef.h"
#include "stdint.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
/* Free list allocator, unfinished code that i found laying around */
// extern uint8_t _heap_start;
// extern uint8_t _heap_end;
#define HEAP_SIZE 1024
static uint8_t heap_area[HEAP_SIZE];
typedef struct Block {
size_t size;
struct Block *next;
struct Block *prev;
uint8_t is_free;
uint8_t padding[3]; // To align to 8 bytes
} Block;
#define ALIGNMENT 8
#define ALIGN(size) (((size) + (ALIGNMENT - 1)) & ~(ALIGNMENT - 1))
static Block *free_list = NULL;
static inline void fl_heap_init(void *heap_start, void *heap_end) {
free_list = (Block *)heap_start;
free_list->size = (size_t)((uint8_t *)heap_end - (uint8_t *)heap_start) - sizeof(Block);
free_list->next = NULL;
free_list->prev = NULL;
free_list->is_free = 1;
}
static inline void *fl_malloc(size_t size) {
size = ALIGN(size);
Block *current = free_list;
while (current) {
if (current->is_free && current->size >= size) {
if (current->size >= size + sizeof(Block) + ALIGNMENT) {
// Split
Block *new_block = (Block *)((uint8_t *)current + sizeof(Block) + size);
new_block->size = current->size - size - sizeof(Block);
new_block->next = current->next;
new_block->prev = current;
new_block->is_free = 1;
if (new_block->next)
new_block->next->prev = new_block;
current->next = new_block;
current->size = size;
}
current->is_free = 0;
return (void *)((uint8_t *)current + sizeof(Block));
}
current = current->next;
}
return NULL; // No suitable block
}
void fl_free(void *ptr) {
if (!ptr)
return;
/* The actual block struct resides _before_ the payload part */
Block *block = (Block *)((uint8_t *)ptr - sizeof(Block));
/* Zero out the block payload to catch dangling pointers and such */
memset(ptr, 0, block->size);
block->is_free = 1;
/* Coalesce with next */
if (block->next && block->next->is_free) {
block->size += sizeof(Block) + block->next->size;
block->next = block->next->next;
if (block->next)
block->next->prev = block;
}
/* Coalesce with prev */
if (block->prev && block->prev->is_free) {
block->prev->size += sizeof(Block) + block->size;
block->prev->next = block->next;
if (block->next)
block->next->prev = block->prev;
}
ptr = NULL;
}
int main(void) {
fl_heap_init(heap_area, heap_area + HEAP_SIZE);
int *a = fl_malloc(sizeof(int));
assert(a != NULL);
*a = 10;
printf("a = %d\n", *a);
fl_free(a);
printf("a = %d\n", *a);
printf("All good!\n");
return 0;
}