summaryrefslogtreecommitdiff
path: root/kernel/mem.c
diff options
context:
space:
mode:
authorNathan Lee <me@nwlee.tech>2026-06-24 23:06:44 -0500
committerNathan Lee <me@nwlee.tech>2026-06-24 23:06:44 -0500
commit746212c43067836488b77b146c01852eafe07b14 (patch)
tree85e0799238fad745049292601e2a261ce38265b4 /kernel/mem.c
parent95e5618b0e4cf354c80d75b00b60539b5ed47150 (diff)
update kmalloc
Diffstat (limited to 'kernel/mem.c')
-rw-r--r--kernel/mem.c65
1 files changed, 58 insertions, 7 deletions
diff --git a/kernel/mem.c b/kernel/mem.c
index 840a3b7..444436a 100644
--- a/kernel/mem.c
+++ b/kernel/mem.c
@@ -5,27 +5,76 @@
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;
- while (page != NULL && page->size < size && page->status != MEMPAGE_FREE) {
+ struct page *last = NULL;
+ while (page && page->size < size) {
+ last = page;
page = page->next;
}
if (page == NULL)
return NULL;
size_t combined_size = size + sizeof(struct page);
- struct page *next = (struct page *)((void *)page + combined_size);
- next->next = page->next;
- next->size = page->size - combined_size;
- next->status = MEMPAGE_FREE;
+
+ if (page->size == combined_size) {
+ if (last)
+ last = page->next;
+ else
+ free_list = page->next;
+ } else if (page->size - combined_size < sizeof(struct page)) {
+ if (page->next) {
+ struct page *curr = (void *)page + combined_size;
+
+ size_t curr_size = page->size + page->next->size - combined_size;
+ struct page *next_page = page->next->next;
+
+ curr->next = next_page;
+ curr->size = curr_size;
+ curr->status = MEMPAGE_FREE;
+ }
+ // If page->next is undefined then there's nothing we can do except leak the last few bytes of memory.
+ }
page->status = MEMPAGE_USED;
- next->size = combined_size;
- next->next = NULL;
+ page->size = combined_size;
+ page->next = NULL;
return (void *)page + sizeof(struct page);
}
+void kfree(void *ptr) {
+ struct page *page_info = (struct page *)(ptr - sizeof(struct page));
+ struct page *iter = free_list;
+
+ if (!iter) {
+ free_list = page_info;
+ return;
+ }
+
+ while (iter->next && iter->next < page_info) {
+ iter = iter->next;
+ }
+
+ page_info->next = iter->next;
+ iter->next = page_info;
+
+ merge_freelist();
+}
+
void* memcpy(void *to, const void *from, size_t size) {
@@ -47,3 +96,5 @@ void km_init(struct mem_info *info) {
free_list = base;
}
+
+