Free list allocator (rough)
This commit is contained in:
parent
33d55b2cd2
commit
14d1667424
1 changed files with 107 additions and 0 deletions
107
free_list.c
Normal file
107
free_list.c
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue