summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init/malloc.c69
-rw-r--r--src/init/malloc.h5
-rw-r--r--src/init/stdlib.h1
-rw-r--r--src/init/tests/main.c23
4 files changed, 97 insertions, 1 deletions
diff --git a/src/init/malloc.c b/src/init/malloc.c
new file mode 100644
index 0000000..35b1741
--- /dev/null
+++ b/src/init/malloc.c
@@ -0,0 +1,69 @@
+#include <init/malloc.h>
+#include <shared/flags.h>
+#include <shared/syscalls.h>
+#include <stdbool.h>
+
+#include <init/stdlib.h>
+
+#define MBLOCK_MAGIC 0x1337BABE
+
+struct mblock {
+ uint32_t magic;
+ size_t length; // including this struct
+ bool used;
+ struct mblock *next;
+};
+
+static struct mblock *first = NULL, *last = NULL;
+static struct mblock *expand(size_t size);
+
+void *malloc(size_t size) {
+ struct mblock *iter = first;
+ size += sizeof(struct mblock);
+ while (iter) {
+ if (!iter->used && iter->length >= size)
+ break;
+ iter = iter->next;
+ }
+
+ if (!iter) iter = expand(size);
+ if (!iter) return NULL;
+
+ iter->used = true;
+ // TODO truncate and split
+
+ return &iter[1];
+}
+
+void free(void *ptr) {
+ struct mblock *block = ptr - sizeof(struct mblock);
+ if (block->magic != MBLOCK_MAGIC) {
+ // TODO debug log switch
+ printf("didn't find MBLOCK_MAGIC @ 0x%x\n", block);
+ return;
+ }
+
+ block->used = false;
+}
+
+static struct mblock *expand(size_t size) {
+ size = (size + 4095) & ~4095; // round up to nearest page
+
+ static void *start = (void*)0x80000000; // TODO workaround for unimplemented feature
+ _syscall_memflag(start, size, MEMFLAG_PRESENT);
+ struct mblock *block = start;
+ start += size;
+
+ block->magic = MBLOCK_MAGIC;
+ block->length = size;
+ block->used = false;
+ block->next = NULL;
+
+ if (!first) first = block;
+ if (last) last->next = block;
+ last = block;
+
+ // TODO collapse
+
+ return block;
+}
diff --git a/src/init/malloc.h b/src/init/malloc.h
new file mode 100644
index 0000000..5916ebc
--- /dev/null
+++ b/src/init/malloc.h
@@ -0,0 +1,5 @@
+#pragma once
+#include <stddef.h>
+
+void *malloc(size_t size);
+void free(void *ptr);
diff --git a/src/init/stdlib.h b/src/init/stdlib.h
index f8ab6c0..b1709e0 100644
--- a/src/init/stdlib.h
+++ b/src/init/stdlib.h
@@ -1,4 +1,5 @@
#pragma once
+#include <init/malloc.h>
#include <shared/mem.h>
#include <stdbool.h>
#include <stddef.h>
diff --git a/src/init/tests/main.c b/src/init/tests/main.c
index 20923b0..29f6c61 100644
--- a/src/init/tests/main.c
+++ b/src/init/tests/main.c
@@ -109,6 +109,26 @@ static void test_memflag(void) {
// TODO the kernel shouldn't even be mapped in userland
}
+static void test_malloc(void) {
+ // not really a test
+ void *p1, *p2, *p3;
+
+ p1 = malloc(420);
+ printf("p1 = 0x%x\n", p1);
+
+ p2 = malloc(1024);
+ printf("p2 = 0x%x\n", p2);
+ free(p2);
+ p2 = malloc(256);
+ printf("p2 = 0x%x\n", p2);
+ free(p2);
+ p2 = malloc(4096);
+ printf("p2 = 0x%x\n", p2);
+ free(p2);
+
+ free(p1);
+}
+
static void stress_fork(void) {
/* run a lot of processes */
for (size_t i = 0; i < 2048; i++) {
@@ -124,5 +144,6 @@ void test_all(void) {
run_forked(test_interrupted_fs);
run_forked(test_orphaned_fs);
run_forked(test_memflag);
- run_forked(stress_fork);
+ run_forked(test_malloc);
+// run_forked(stress_fork);
}