diff options
Diffstat (limited to 'src/memory')
-rw-r--r-- | src/memory/memory.c | 34 | ||||
-rw-r--r-- | src/memory/physalloc.c | 25 | ||||
-rw-r--r-- | src/memory/virtalloc.c | 81 |
3 files changed, 86 insertions, 54 deletions
diff --git a/src/memory/memory.c b/src/memory/memory.c index 1c69bae..af63865 100644 --- a/src/memory/memory.c +++ b/src/memory/memory.c @@ -1,10 +1,8 @@ +#include "serial.h" #include <memory.h> #include <stdint.h> #include <lib.h> - -#ifdef MEMORY_PANIC #include <panic.h> -#endif #define MAGIC 0xBEEFCAFE @@ -18,8 +16,8 @@ struct page_header { }; static const size_t header_len = sizeof(struct page_header); -struct page_header *start_header = NULL; -struct page_header *end_header = NULL; +static struct page_header *start_header = NULL; +static struct page_header *end_header = NULL; struct page_header* get_header(void *ptr) { struct page_header *header = @@ -36,6 +34,7 @@ struct page_header* get_header(void *ptr) { void *kalloc_new(size_t size) { size_t pages = ((size + header_len) / PAGE_SIZE) + 1; + void *addr = alloc_pages(pages); void *mem = (char *)addr + header_len; @@ -54,20 +53,20 @@ void *kalloc_new(size_t size) { } struct page_header *header = addr; - header->magic = MAGIC; + header->magic = 0xBEEFCAFE; header->used = size; header->free = free; header->prev = end_header; header->next = NULL; header->node_number = node; - if (end_header == NULL) { + if (start_header == NULL) { start_header = header; - } else { - end_header->next = header; } - end_header = header; + if (end_header != NULL) { + end_header->next = header; + } return mem; } @@ -97,6 +96,9 @@ void *kalloc(size_t size) { for (; header != NULL; header = header->next) { size_t free = header->free; + if (free < header_len) { + continue; + } if (size <= (free - header_len)) { // we must be able to fit data + header break; } @@ -129,21 +131,13 @@ void *krealloc(void *src, size_t dst_len) { header = get_header(src); if (header == NULL) { -#ifdef MEMORY_PANIC panic("attempted to realloc on a invalid ptr"); -#else - return NULL; // invalid pointer passed -#endif } src_len = header->used; if (src_len == 0) { -#ifdef MEMORY_PANIC panic("attempted to realloc on an empty ptr"); -#else - return NULL; // likely double free :( -#endif } dst = kalloc(dst_len); @@ -166,11 +160,7 @@ void kfree(void *ptr) { header = get_header(ptr); if (header == NULL || header->used == 0) { -#ifdef MEMORY_PANIC panic("attempted to kfree invalid pointer"); -#else - return; -#endif } header->free += header->used; diff --git a/src/memory/physalloc.c b/src/memory/physalloc.c index 1140258..bcbc66d 100644 --- a/src/memory/physalloc.c +++ b/src/memory/physalloc.c @@ -1,3 +1,4 @@ +#include "serial.h" #include <memory.h> #include <stdint.h> #include <lib.h> @@ -63,6 +64,10 @@ static inline bool bitmap_get(int i) { } static inline void bitmap_set(int i, bool v) { + if (v) + free_memory -= PAGE_SIZE; + else + free_memory += PAGE_SIZE; int idx = i / 64; bitmap[idx] &= ~(1 << i % 64); bitmap[idx] |= (v << i % 64); @@ -115,11 +120,11 @@ void free_phys_pages(void *ptr, int pages) { } static bool segment_invalid(const struct memory_segment *segment) { - if (segment->type != 1) return false; - if (segment->addr < kaddr(kernel_start)) return false; - if (segment->addr + segment->len < memory_start) return false; - if (segment->addr + segment->len < kaddr(kernel_start)) return false; - return true; + if (segment->type != 1) return true; + if (segment->addr < kaddr(kernel_start)) return true; + if (segment->addr + segment->len < memory_start) return true; + if (segment->addr + segment->len < kaddr(kernel_start)) return true; + return false; } static struct memory_area segment_to_area(const struct memory_segment *segment) { @@ -195,18 +200,28 @@ void memory_init(struct memory_map *map) { struct memory_area *area = page_start; + kprintf("MEMORY MAP\n"); for(uint32_t i = 0; i < map->entry_count; i++) { struct memory_segment *segment = &map->entries[i]; if (segment_invalid(segment)) continue; + kprintf("addr: 0x%16p\tlen: %ld\n", (void *)segment->addr, segment->len); + struct memory_area temp = segment_to_area(segment); *area = temp; area++; } + total_memory = page_count * PAGE_SIZE; page_count -= bitmap_pages; + free_memory = page_count * PAGE_SIZE; + + kprintf("\nMEMORY USAGE\n"); + kprintf("mem total: %ld\n", memory_total()); + kprintf("mem free: %ld\n", memory_free()); + kprintf("mem used: %ld\n\n", memory_used()); memory_unlock(); diff --git a/src/memory/virtalloc.c b/src/memory/virtalloc.c index 781fc9b..2ab9fc2 100644 --- a/src/memory/virtalloc.c +++ b/src/memory/virtalloc.c @@ -1,6 +1,9 @@ +#include "lib.h" +#include "panic.h" #include <stdint.h> #include <stddef.h> #include <memory.h> +#include <string.h> #define MEMORY_INTERNAL #include <memory/virtalloc.h> @@ -10,34 +13,60 @@ struct addr_node { uintptr_t end; struct addr_node *next; struct addr_node *prev; - uint8_t is_alloc; - uint8_t is_bss; + uint8_t is_alloc; // if node is storing allocated data + uint8_t is_used; // if node is in use by virtalloc }; -#define BOOTSTRAP_BSS_NODES 16 -static uint8_t bss_nodes = 0; -static struct addr_node nodes[BOOTSTRAP_BSS_NODES]; +#define BSS_NODES 64 +static struct addr_node bootstrap_nodes[BSS_NODES]; +static struct addr_node *alloc_nodes = NULL; +static size_t free_node_start = 0; +static size_t alloc_node_count = 0; +static size_t used_node_count = 0; +static bool is_allocating = false; -static struct addr_node *start_node; +static struct addr_node *start_node = NULL; -static struct addr_node *alloc_node(void) { - struct addr_node *node = NULL; - if (bss_nodes >= BOOTSTRAP_BSS_NODES) { - node = kalloc(sizeof(struct addr_node)); - if (node == NULL) - return NULL; - node->is_bss = false; +static struct addr_node *get_node_idx(int idx) { + if (idx < BSS_NODES) { + return &bootstrap_nodes[idx]; } else { - node = &nodes[bss_nodes]; - bss_nodes += 1; - node->is_bss = true; + return &alloc_nodes[idx - BSS_NODES]; } - return node; +} + +static struct addr_node *get_node(void) { + size_t count = BSS_NODES + alloc_node_count; + + if (!is_allocating && used_node_count + 16 >= count) { + is_allocating = true; + int new_alloc = alloc_node_count * 2; + if (new_alloc < 8) + new_alloc = 8; + int allocated = new_alloc - alloc_node_count; + int old = new_alloc - allocated; + alloc_nodes = krealloc(alloc_nodes, sizeof(struct addr_node) * new_alloc); + memset(alloc_nodes + old, 0, sizeof(struct addr_node) + allocated);; + alloc_node_count = new_alloc; + is_allocating = false; + count = BSS_NODES + alloc_node_count; + } + + size_t idx = free_node_start; + for (; idx < count; idx++) { + struct addr_node *node = get_node_idx(idx); + if (!node->is_used) { + used_node_count++; + return node; + } + } + + panic("could not get virtaddr node"); } static void free_node(struct addr_node *node) { - if (!node->is_bss) - kfree(node); + node->is_used = false; + used_node_count--; } void virtaddr_init(void) { @@ -47,11 +76,11 @@ void virtaddr_init(void) { .next = NULL, .prev = NULL, .is_alloc = false, - .is_bss = true, + .is_used = true, }; - nodes[0] = init; - start_node = &nodes[0]; - bss_nodes++; + memset(bootstrap_nodes, 0, sizeof(bootstrap_nodes)); + bootstrap_nodes[0] = init; + start_node = &bootstrap_nodes[0]; } void *virtaddr_alloc(int n_pages) { @@ -69,10 +98,7 @@ void *virtaddr_alloc(int n_pages) { long length = node->end - node->start; if (length >= n_length) { - struct addr_node *new = alloc_node(); - if (node == NULL) { - return NULL; - } + struct addr_node *new = get_node(); if (node->prev != NULL) { node->prev->next = new; } @@ -82,6 +108,7 @@ void *virtaddr_alloc(int n_pages) { new->end = new->start + n_length; node->start = new->end; new->is_alloc = true; + new->is_used = true; new->next = node; return (void *) new->start; } |