blob: 0556dfb778fb5f7ed8edeb1d2669aa9b2b5439be (
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#include <types.h>
#include <mem.h>
#include <dtb.h>
#include <common.h>
static struct page *free_list;
static void merge_freelist() {
struct page *list = free_list;
while (list && list->next) {
if ((void*)list + list->size == list->next) {
list->size += list->next->size;
list->next = list->next->next;
continue;
}
list = list->next;
}
}
void* kmalloc(size_t size) {
struct page *page = free_list;
struct page *last = NULL;
size_t combined_size = size + sizeof(struct page);
while (page && page->size < combined_size) {
last = page;
page = page->next;
}
if (page == NULL)
return NULL;
if (page->size - combined_size < sizeof(struct page)) {
// Return the entire page
if (last)
last->next = page->next;
else
free_list = page->next;
} else {
// break page and create a new one
struct page *broken = (void *)page + combined_size;
broken->size = page->size - combined_size;
broken->next = page->next;
broken->status = MEMPAGE_FREE;
page->size = combined_size;
page->next = broken;
if (last)
last->next = broken;
else
free_list = broken;
}
page->status = MEMPAGE_USED;
return (void *)page + sizeof(struct page);
}
void* kzalloc(size_t size) {
char *ptr = kmalloc(size);
if (!ptr)
return NULL;
for (size_t i = 0; i < size; i++) {
*(ptr + i) = 0;
}
return ptr;
}
void kfree(void *ptr) {
if (!ptr)
return;
struct page *page_info = (struct page *)(ptr - sizeof(struct page));
struct page *iter = free_list;
page_info->status = MEMPAGE_FREE;
if (!iter) {
free_list = page_info;
page_info->next = NULL;
goto merge;
}
if (page_info < free_list) {
page_info->next = iter;
free_list = page_info;
goto merge;
}
while (iter->next && iter->next < page_info) {
iter = iter->next;
}
page_info->next = iter->next;
iter->next = page_info;
merge:
merge_freelist();
}
void* memcpy(void *to, const void *from, size_t size) {
char *dest = (char *)to;
const char *src = (const char *)from;
while (size--) {
*dest++ = *src++;
}
return dest;
}
void km_init(struct mem_info *info) {
struct page *base = (struct page *)info->start;
base->next = NULL;
base->size = info->size - sizeof(struct page);
base->status = MEMPAGE_FREE;
free_list = base;
}
|