From 4c6c4a015075a695a935ebb20098da3b8acb4323 Mon Sep 17 00:00:00 2001 From: hippoz Date: Mon, 23 Aug 2021 14:05:04 +0300 Subject: [PATCH] add terrible, janky memory manager --- Makefile | 2 +- arch/x86_64/kernel.c | 17 ++++++++- arch/x86_64/mem/mem.c | 88 +++++++++++++++++++++++++++++++++++++++++++ include/mem/mem.h | 18 +++++++++ include/std/util.h | 2 - 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 arch/x86_64/mem/mem.c create mode 100644 include/mem/mem.h diff --git a/Makefile b/Makefile index 27d3961..b3d9d5c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ ISO := hhhos.iso CC = x86_64-elf-gcc NASM = nasm - + # User controllable CFLAGS. CFLAGS = -Wall -Wextra -O2 -pipe NASMFLAGS = -felf64 diff --git a/arch/x86_64/kernel.c b/arch/x86_64/kernel.c index 47a44ca..0aa2391 100644 --- a/arch/x86_64/kernel.c +++ b/arch/x86_64/kernel.c @@ -13,6 +13,7 @@ #include #include #include +#include static u8 stack[16384]; @@ -88,6 +89,11 @@ framebuffer_t *framebuffer; extern usize _kernel_start; extern usize _kernel_end; +struct test_struct { + unsigned int something; + int hello; +}; + void _start(struct stivale2_struct *stivale2_struct) { struct stivale2_struct_tag_framebuffer *tag_fb = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID); struct stivale2_struct_tag_memmap *tag_mmap = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID); @@ -153,7 +159,16 @@ void _start(struct stivale2_struct *stivale2_struct) { printf("no\n"); } - printf("_start memory address: %#lX\n", (usize)_start); + usize start_mem_addr = (usize)_start; + printf("_start memory address: %#lX\n", start_mem_addr); + + mem_populate_blocks(start_mem_addr + 0x42069); + + /* TODO: only enable this in debug (or just handle testing in a better way) */ + if (mem_test_mm()) { + printf("memory manager test passed\n"); + } + printf("----------\n"); printf("hello yes"); diff --git a/arch/x86_64/mem/mem.c b/arch/x86_64/mem/mem.c new file mode 100644 index 0000000..e7989b2 --- /dev/null +++ b/arch/x86_64/mem/mem.c @@ -0,0 +1,88 @@ +#include +#include + +struct mem_block mem_blocks[MEM_BLOCK_LIST_SIZE]; +usize last_free_index = 0; + +void mem_populate_blocks(usize starting_addr) { + usize last_addr = starting_addr; + unsigned int last_size = 1; + + for (int i = 0; i < MEM_BLOCK_LIST_SIZE; i++) { + mem_blocks[i].addr = last_addr; + mem_blocks[i].size = last_size; + last_addr += mem_blocks[i].size; + last_size += MEM_BLOCK_INCREASE_SIZE; + //printf("-- POPULATED BLOCK: addr = %#lX; size = %#lX\n", mem_blocks[i].addr, mem_blocks[i].size); + } +} + +unsigned int find_available_block(usize start_index, usize size) { + struct mem_block block = mem_blocks[start_index]; + if (!block.is_used) { + if ((block.addr - mem_blocks[last_free_index].addr) >= size) + return start_index; /* we found a free block */ + else + return find_available_block(start_index + 1, size); + } else { + return find_available_block(start_index + 1, size); + } +} + +void* malloc(usize size) { + unsigned int block_index = find_available_block(last_free_index, size); + mem_blocks[block_index].is_used = true; + + return mem_blocks[block_index].addr; +} + +void free(void* memory) { + for (int i = 0; i < MEM_BLOCK_LIST_SIZE; i++) { + if (mem_blocks[i].addr == (usize)memory) { + mem_blocks[i].is_used = false; + return; + } + } +} + +struct test_struct { + int hello; +}; + +/* terrible function to test the really bad memory manager i've made - it's not great at all (only checks if the last element has the same address) */ +bool mem_test_mm() { + unsigned int count = 42; + usize last_addr = 1; + + for (int i = 0; i < count; i++) { + struct test_struct* test_allocated = (struct test_struct*) malloc(sizeof(struct test_struct)); + if ((usize)test_allocated == 0) { + printf("test_struct #%d: FAIL: malloc() -> 0", i); + return false; + } + if ((usize)test_allocated == last_addr) { + printf("test_struct #%d: FAIL: new allocated struct address is the same as the last one", i); + return false; + } + last_addr = (usize)test_allocated; + //printf("test_struct #%d memory address: %#lX\n", i, (usize)test_allocated); + test_allocated->hello = i; + if (test_allocated->hello != i) { + printf("test_struct #%d: FAIL: test_allocated->hello(%d) != i(%d)", i, test_allocated->hello, i); + return false; + } + } + + struct test_struct* will_be_freed = (struct test_struct*) malloc(sizeof(struct test_struct)); + will_be_freed->hello = 76; + free(will_be_freed); + + //printf("test_struct will_be_freed memory address: %#lX\n", (usize)will_be_freed); + + if ((usize)malloc(sizeof(struct test_struct)) != (usize)will_be_freed) { + printf("test_struct will_be_freed: FAIL: next allocation address is not equal to the freed struct's address"); + return false; + } + + return true; +} diff --git a/include/mem/mem.h b/include/mem/mem.h new file mode 100644 index 0000000..f92d9b8 --- /dev/null +++ b/include/mem/mem.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +#define MEM_BLOCK_LIST_SIZE 4096 +#define MEM_BLOCK_INCREASE_SIZE 4 + +struct mem_block { + bool is_used; + bool is_end; + usize size; + usize addr; +}; + +void* malloc(usize size); +void mem_populate_blocks(usize starting_addr); +bool mem_test_mm(); diff --git a/include/std/util.h b/include/std/util.h index 6bda8bc..1da57df 100644 --- a/include/std/util.h +++ b/include/std/util.h @@ -5,8 +5,6 @@ #define LOW_16(address) (u16)((address) & 0xFFFF) #define HIGH_16(address) (u16)(((address) >> 16) & 0xFFFF) -void* malloc(usize amount); - int rand(void); void srand(usize seed); char* itoa(int res);