game/axl_memory.c

129 lines
2.5 KiB
C

#include "axl_memory.h"
static u8 memory[AXL_HEAP_SIZE];
struct mb_header
{
u32 size;
b8 is_free;
struct mb_header* next;
};
typedef struct mb_header mb_header;
#define MB_HEADER_SIZE sizeof(mb_header)
static mb_header* root = 0;
void* axl_memset(void* ptr, i8 c, u32 n)
{
if(ptr)
{
for(u32 i = 0; i < n; i++)
{
((i8*)ptr)[i] = c;
}
}
return ptr;
}
void axl_init(void)
{
static b8 axl_initialized = false;
if(!axl_initialized)
{
axl_memset(memory, 0, AXL_HEAP_SIZE);
root = (mb_header*)memory;
root->is_free = true;
root->next = NULL;
root->size = AXL_HEAP_SIZE - MB_HEADER_SIZE;
axl_initialized = true;
}
}
mb_header* axl_find_mb(u32 req_size)
{
mb_header* block = root;
while(block != NULL)
{
if(block->is_free && block->size >= req_size)
{
return block;
}
block = block->next;
}
return NULL;
}
void axl_split_mb(mb_header* block, u32 size)
{
if(block->size > size + MB_HEADER_SIZE)
{
mb_header* new_block = (mb_header*)((u8*)block + MB_HEADER_SIZE + size);
new_block->size = block->size - size - MB_HEADER_SIZE;
new_block->is_free = true;
new_block->next = block->next;
block->size = size;
block->next = new_block;
}
}
void* axl_malloc(u32 size)
{
if(size > AXL_HEAP_SIZE - MB_HEADER_SIZE)
{
return NULL;
}
mb_header* free_block = axl_find_mb(size);
if(!free_block)
{
return NULL;
}
axl_split_mb(free_block, size);
free_block->is_free = false;
return (void*)((u8*)free_block + MB_HEADER_SIZE);
}
void axl_free(void* ptr)
{
if(!ptr)
{
return;
}
mb_header* block = (mb_header*)((u8*)ptr - MB_HEADER_SIZE);
mb_header* next_block = block->next;
block->is_free = true;
if(next_block != NULL && next_block->is_free)
{
block->size += next_block->size + MB_HEADER_SIZE;
block->next = next_block->next;
}
if(block != root)
{
for(mb_header* mb = root; mb != NULL; mb = mb->next)
{
if(mb->next == block)
{
if(mb->is_free)
{
mb_header* prev_free_mb = mb;
prev_free_mb->size += block->size + MB_HEADER_SIZE;
prev_free_mb->next = block->next;
}
break;
}
}
}
}