107 lines
2.9 KiB
C
107 lines
2.9 KiB
C
#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;
|
|
}
|