blob: e197c0cab1b022e61fbb55e24b5a409a7c99054b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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);
}
|