diff options
author | Danny Holman <dholman@gymli.org> | 2024-03-28 21:55:33 -0500 |
---|---|---|
committer | Danny Holman <dholman@gymli.org> | 2024-03-28 21:55:33 -0500 |
commit | 3b66779d9a8325c77c6cfbf1565885f98da5378f (patch) | |
tree | 38a1359cbaa1357479a8d57b7c206b190012e783 /arch | |
parent | cbe2690cd5d1b290633c466ebb4df7b64b09b037 (diff) |
arch: i386: kernel: implement a kmalloc function
Add a basic kmalloc implementation. This allows the kernel to allocate
blocks smaller than a whole page.
Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/kmalloc.c | 66 | ||||
-rw-r--r-- | arch/i386/make.config | 1 |
2 files changed, 67 insertions, 0 deletions
diff --git a/arch/i386/kernel/kmalloc.c b/arch/i386/kernel/kmalloc.c new file mode 100644 index 0000000..183545a --- /dev/null +++ b/arch/i386/kernel/kmalloc.c @@ -0,0 +1,66 @@ +#include <kernel/kmalloc.h> +#include <kernel/paging.h> +#include <kernel/pmem.h> +#include <kernel/asm.h> +#include <kernel/errno.h> +#include <kernel/panic.h> +#include <stdint.h> + +static uintptr_t heap_start = KEND + 0xC0001000; +static uintptr_t heap_end = 0xFFFFF000; + +static void *kbrk = NULL; +static struct mem_block *first = NULL; + +void _request_page(void) { + uintptr_t paddr = pfa_alloc(); + if (paddr == PFA_ALLOC_ERR) + panic("Out of physical memory"); + + uintptr_t vaddr = PGROUNDDN((uintptr_t)kbrk + PAGE_SIZE); + kbrk += PAGE_SIZE; + map_page(NULL, paddr, vaddr, PD_PRES | PD_RW); +} + +void kmalloc_init(void) { + kbrk = (void*)(heap_start & 0xFFFFF000); + _request_page(); + first = (struct mem_block*)kbrk; + first->start = (uintptr_t)kbrk + sizeof(struct mem_block); + first->size = 0; + first->alloc = 1; + first->next = NULL; +} + +void* kmalloc(size_t sz) { + if (kbrk == NULL) + panic("Attmpted to malloc before initialization"); + if ((uintptr_t)kbrk >= heap_end) + return NULL; + + struct mem_block *temp = first; + while (temp->next != NULL) { + if (temp->size <= sz && temp->alloc == 0) + return (void*)temp->start; + temp = temp->next; + } + + temp->next = (struct mem_block*)((uintptr_t)temp + sizeof(struct mem_block) + temp->size); + temp = temp->next; + temp->start = (uintptr_t)(temp + sizeof(struct mem_block)); + temp->size = sz; + temp->alloc = 1; + temp->next = NULL; + return (void*)temp->start; +} + +void kfree(void *ptr) { + struct mem_block *temp = first; + while (temp->next != NULL) { + if (temp->start == (uintptr_t)ptr) { + temp->alloc = 0; + return; + } + } + panic("Attempted to free memory not alloc'd"); +} diff --git a/arch/i386/make.config b/arch/i386/make.config index 1ffe8be..8499f1a 100644 --- a/arch/i386/make.config +++ b/arch/i386/make.config @@ -16,3 +16,4 @@ KERNEL_ARCH_OBJS=$(ARCHDIR)/boot/boot.o \ $(ARCHDIR)/kernel/syscall.o \ $(ARCHDIR)/kernel/paging.o \ $(ARCHDIR)/kernel/pmem.o \ + $(ARCHDIR)/kernel/kmalloc.o \ |