diff options
Diffstat (limited to 'src/memory.c')
-rw-r--r-- | src/memory.c | 60 |
1 files changed, 55 insertions, 5 deletions
diff --git a/src/memory.c b/src/memory.c index bc65311..e5e215c 100644 --- a/src/memory.c +++ b/src/memory.c @@ -4,19 +4,29 @@ #include <stddef.h> #include "memory.h" #include "multiboot.h" +#include "bees.h" +#include "misc.h" #include "printf.h" struct memory_area { uint32_t len; struct memory_area *next; + struct memory_area *prev; }; -struct memory_area *first = NULL; - uint32_t memory_available = 0; +uint32_t total_memory = 0; +struct memory_area *first_area = NULL; + +struct cell *first_free = NULL; + +extern mem_t __kernel_start; +extern mem_t __kernel_end; void init_memory(multiboot_info_t *mb) { struct memory_area *prev = NULL; + struct cell *prev_cell = NULL; + for ( multiboot_memory_map_t *e = (multiboot_memory_map_t *) mb->mmap_addr; (unsigned int) e < mb->mmap_addr + mb->mmap_length; @@ -24,7 +34,7 @@ void init_memory(multiboot_info_t *mb) { ) { if (e->type != MULTIBOOT_MEMORY_AVAILABLE) continue; // memory below 1MB is not safe to use. - if (e->addr < 1000000) continue; + if (e->addr < __kernel_start) continue; // memory above UINT_MAX is unusable. if (e->addr > UINT_MAX) continue; @@ -34,14 +44,54 @@ void init_memory(multiboot_info_t *mb) { length = UINT_MAX - e->addr; else length = e->len; - memory_available += length; + // free memory comes after the kernel + uint32_t addr = e->addr; + if (addr < (uint32_t) __kernel_end) { + addr = (uint32_t) __kernel_end; + length -= addr - e->addr; + } + + memory_available += length - sizeof(struct memory_area); - struct memory_area *cur = (struct memory_area *) e->addr; + // join memory area to linked list + struct memory_area *cur = (struct memory_area *) addr; cur->len = length; + cur->next = NULL; + cur->prev = prev; if (prev != NULL) prev->next = (struct memory_area *) e->addr; prev = cur; + + if (first_area == NULL) first_area = cur; + + unsigned char *after = (unsigned char*) (cur + 1); + + // link memory into free list + for ( + // cells start after memory area struct; they must be aligned. + struct cell *c = (struct cell *) + (after + ((uint32_t) after % sizeof(struct cell))); + // no part of the cell can be outside of the memory area + (uint32_t) (c + 1) < (uint32_t) cur + cur->len; + c++ + ) { + if (first_free == NULL) first_free = c; + c->type = FREE_CELL; + set_cdr(c, 0); + if (prev_cell != NULL) set_cdr(prev_cell, (uint32_t) c); + prev_cell = c; + } } + total_memory = memory_available; +} + +struct cell *alloc_cell(enum cell_type t) { + if (first_free == NULL) return NULL; // GC should be invoked here somehow + if (first_free->type != FREE_CELL) bees("heap corruption has occurred"); + first_free = cdr_cell(first_free); + first_free->type = t; + memory_available -= sizeof(struct cell); + return first_free; } |