From 45f420a338ea02225bb8a98c9aca5eed8d6a23ae Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sun, 2 Jun 2024 00:26:57 +0200 Subject: Initial commit --- kernel/kalloc.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 kernel/kalloc.c (limited to 'kernel/kalloc.c') diff --git a/kernel/kalloc.c b/kernel/kalloc.c new file mode 100644 index 0000000..e197c0c --- /dev/null +++ b/kernel/kalloc.c @@ -0,0 +1,87 @@ +#include "kernel/lib.h" +#include "kernel/kalloc.h" +#include "kernel/spinlock.h" + +extern uint32_t _heap_start; +extern uint32_t _heap_end; + +union Page +{ + union Page* next; + char dummy[PAGE_SIZE]; +}; +typedef union Page Page; +static_assert(sizeof(Page) == PAGE_SIZE); + +static inline void* align_page_down(void* p) +{ + return (void*)((uint32_t)p & ~(PAGE_SIZE - 1)); +} + +static inline void* align_page_up(void* p) +{ + return align_page_down((char*)p + PAGE_SIZE - 1); +} + +static inline bool is_page_aligned(void* p) +{ + return ((uint32_t)p & (PAGE_SIZE - 1)) == 0; +} + +static Page* g_page_start; +static Page* g_page_end; +static Page* g_free_list; +static Spinlock g_lock; + +void kalloc_init() +{ + spinlock_init(&g_lock); + + g_free_list = NULL; + g_page_start = (Page*)align_page_up(&_heap_start); + g_page_end = (Page*)align_page_down(&_heap_end); + + for (Page* p = g_page_end - 1; p >= g_page_start; --p) + { + p->next = g_free_list; + g_free_list = p; + } +} + +void* kalloc() +{ + spinlock_acquire(&g_lock); + Page* page = g_free_list; + if (!page) + { + panic("kalloc: Out of memory"); + } + g_free_list = page->next; + spinlock_release(&g_lock); + return page; +} + +void* kzalloc() +{ + void* page = kalloc(); + uint32_t* p = (uint32_t*)page; + for (uint32_t i = 0; i < PAGE_SIZE / 4; ++i) + { + *p++ = 0U; + } + return page; +} + +void kfree(void* ptr) +{ + if (ptr < (void*)g_page_start || ptr >= (void*)g_page_end || !is_page_aligned(ptr)) + { + panic("kfree: Invalid page"); + } + + spinlock_acquire(&g_lock); + Page* page = (Page*)ptr; + page->next = g_free_list; + g_free_list = page; + spinlock_release(&g_lock); +} -- cgit