2025-05-28 14:41:02 -05:00
|
|
|
#include <mm/pmm.h>
|
|
|
|
|
#include <mm/paging.h>
|
2025-10-20 21:57:30 -05:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <mm_macros.h>
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
#include <mm/heap.h>
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
#define ALIGN4(x) (((x) + 3) & ~3)
|
|
|
|
|
#define MIN_BLOCK_SIZE 16
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
typedef struct block {
|
2025-05-28 14:41:02 -05:00
|
|
|
size_t size;
|
2025-10-20 21:57:30 -05:00
|
|
|
struct block* next;
|
2025-05-28 14:41:02 -05:00
|
|
|
int free;
|
2025-10-20 21:57:30 -05:00
|
|
|
} block_t;
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
#define BLOCK_SIZE sizeof(block_t)
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
static uint8_t* heap_base;
|
|
|
|
|
static uint8_t* heap_end;
|
|
|
|
|
static size_t heap_size;
|
|
|
|
|
static block_t* free_list;
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
void heap_init(uint32_t start, uint32_t size)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
#ifdef _DEBUG
|
|
|
|
|
printf("[ HEAP ] Initializing heap allocator...\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
heap_base = (uint8_t*) ALIGN4((uintptr_t) start);
|
|
|
|
|
heap_end = heap_base;
|
|
|
|
|
heap_size = size;
|
|
|
|
|
free_list = NULL;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < size; i += 0x1000)
|
|
|
|
|
{
|
|
|
|
|
map_page(pmm_alloc_page(), (void*)(start + i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set up initial free block */
|
|
|
|
|
free_list = (block_t*)heap_base;
|
|
|
|
|
free_list->size = heap_size - BLOCK_SIZE;
|
2025-05-28 14:41:02 -05:00
|
|
|
free_list->free = 1;
|
2025-10-20 21:57:30 -05:00
|
|
|
free_list->next = NULL;
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
heap_end = heap_base + size;
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
printf("[ HEAP ] Heap allocator initialized\n");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
static block_t* find_free_block(size_t size)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
block_t* curr = free_list;
|
2025-05-28 14:41:02 -05:00
|
|
|
while (curr)
|
|
|
|
|
{
|
|
|
|
|
if (curr->free && curr->size >= size)
|
|
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
return curr;
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
2025-10-20 21:57:30 -05:00
|
|
|
|
2025-05-28 14:41:02 -05:00
|
|
|
curr = curr->next;
|
|
|
|
|
}
|
2025-10-20 21:57:30 -05:00
|
|
|
|
|
|
|
|
printf("find_free_block(): No free block found!\n");
|
2025-05-28 14:41:02 -05:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
static void split_block(block_t* blk, size_t size)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
if (blk->size >= size + BLOCK_SIZE + MIN_BLOCK_SIZE)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
block_t* new_blk = (block_t*)((uint8_t*)blk + BLOCK_SIZE + size);
|
|
|
|
|
new_blk->size = blk->size - size - BLOCK_SIZE;
|
|
|
|
|
new_blk->free = 1;
|
|
|
|
|
new_blk->next = blk->next;
|
|
|
|
|
blk->next = new_blk;
|
|
|
|
|
blk->size = size;
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
void* malloc(size_t size)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
size = ALIGN4(size);
|
|
|
|
|
block_t* blk = find_free_block(size);
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
if (!blk)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
printf("malloc(): No free block found!\n");
|
2025-05-28 14:41:02 -05:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
split_block(blk, size);
|
|
|
|
|
blk->free = 0;
|
|
|
|
|
return (void*)((uint8_t*)blk + BLOCK_SIZE);
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void free(void* ptr)
|
|
|
|
|
{
|
|
|
|
|
if (!ptr)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
block_t* blk = (block_t*)((uint8_t*)ptr - BLOCK_SIZE);
|
|
|
|
|
blk->free = 1;
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
/* coalesce */
|
|
|
|
|
block_t* curr = free_list;
|
|
|
|
|
while (curr && curr->next)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
if (curr->free && curr->next->free)
|
|
|
|
|
{
|
|
|
|
|
curr->size += BLOCK_SIZE + curr->next->size;
|
|
|
|
|
curr->next = curr->next->next;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
curr = curr->next;
|
|
|
|
|
}
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
2025-10-20 21:57:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void* calloc(size_t nmemb, size_t size)
|
|
|
|
|
{
|
|
|
|
|
size_t total = nmemb * size;
|
|
|
|
|
void* ptr = malloc(total);
|
|
|
|
|
|
|
|
|
|
if (ptr)
|
|
|
|
|
{
|
|
|
|
|
MEMSET(ptr, 0, total);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
void* realloc(void* ptr, size_t size)
|
|
|
|
|
{
|
|
|
|
|
if (!ptr)
|
|
|
|
|
{
|
|
|
|
|
return malloc(size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!size)
|
|
|
|
|
{
|
|
|
|
|
free(ptr);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2025-05-28 14:41:02 -05:00
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
block_t* blk = (block_t*)((uint8_t*)ptr - BLOCK_SIZE);
|
|
|
|
|
if (blk->size >= size)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
return ptr;
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
void* new_ptr = malloc(size);
|
|
|
|
|
|
|
|
|
|
if (new_ptr)
|
2025-05-28 14:41:02 -05:00
|
|
|
{
|
2025-10-20 21:57:30 -05:00
|
|
|
memcpy(new_ptr, ptr, blk->size);
|
|
|
|
|
free(ptr);
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
2025-10-20 21:57:30 -05:00
|
|
|
return new_ptr;
|
2025-05-28 14:41:02 -05:00
|
|
|
}
|
2025-07-04 14:23:29 -05:00
|
|
|
|