Initial commit
This commit is contained in:
87
kernel/kalloc.c
Normal file
87
kernel/kalloc.c
Normal file
@ -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);
|
||||
}
|
Reference in New Issue
Block a user