diff options
Diffstat (limited to 'src/init')
-rw-r--r-- | src/init/malloc.c | 69 | ||||
-rw-r--r-- | src/init/malloc.h | 5 | ||||
-rw-r--r-- | src/init/stdlib.h | 1 | ||||
-rw-r--r-- | src/init/tests/main.c | 23 |
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); } |