diff options
Diffstat (limited to 'src/kernel/mem/mem.cpp')
-rw-r--r-- | src/kernel/mem/mem.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/kernel/mem/mem.cpp b/src/kernel/mem/mem.cpp new file mode 100644 index 0000000..5e04de3 --- /dev/null +++ b/src/kernel/mem/mem.cpp @@ -0,0 +1,137 @@ +#include "mem.h" +#include <core/sys.h> +#include <core/monitor.h> +#include "paging.h" + +#include <config.h> + +#include "_dlmalloc.h" + +#include "mem.h" + +#define FREEPAGESTOKEEP 5 + +#define KHEAP_IDXSIZE 0x4000 // only used with heap.std.h +#define KHEAP_INITSIZE 0x00080000 +#define KHEAP_MAXSIZE 0x08000000 + +size_t mem_placementAddr; +bool _no_more_ksbrk = false; + + +// ****************************** +// PAGE ALLOCATION +// **************************** +static struct freepage { + size_t virt, phys; +} freepages[FREEPAGESTOKEEP]; +uint32_t freepagecount = 0; + +/* For internal use only. Populates the cache of pages that can be given to requesters. */ +static void get_free_pages() { + static uint32_t locked = 0; + uint32_t i; + if (locked) return; + locked = 1; + while (freepagecount < FREEPAGESTOKEEP) { + if (_no_more_ksbrk) { + for (i = 0xFFFFF000; i >= 0xF0000000; i -= 0x1000) { + if (pagedir_getPage(kernel_pagedir, i, 1)->frame == 0) break; + } + freepages[freepagecount].virt = i; + uint32_t frame = frame_alloc(); + freepages[freepagecount].phys = frame * 0x1000; + page_map(pagedir_getPage(kernel_pagedir, i, 0), freepages[freepagecount].phys / 0x1000, 0, 0); + freepagecount++; + } else { + if (mem_placementAddr & 0xFFFFF000) { + mem_placementAddr &= 0xFFFFF000; + mem_placementAddr += 0x1000; + } + freepages[freepagecount].virt = (size_t)ksbrk(0x1000); + freepages[freepagecount].phys = freepages[freepagecount].virt - K_HIGHHALF_ADDR; + freepagecount++; + } + } + locked = 0; +} + +/* Gives one page from the cache to someone requesting it. */ +void* kmalloc_page(size_t *phys) { + cli(); + get_free_pages(); + freepagecount--; + *phys = freepages[freepagecount].phys; + size_t tmp = freepages[freepagecount].virt; + sti(); + return (void*)tmp; +} + +void kfree_page(void* ptr) { + size_t addr = (size_t)ptr; + if (_no_more_ksbrk) { + page_unmapFree(pagedir_getPage(kernel_pagedir, addr, 0)); + } +} + +//*********************************** +// MEMORY ALLOCATION FOR DLMALLOC +// ************************* + +void* ksbrk(size_t size) { + if (!_no_more_ksbrk) { // ksbrk is NOT being called by dlmalloc + if (size & 0x0FFF) { + size = (size & 0xFFFFF000) + 0x1000; + } + } + + size_t tmp = mem_placementAddr; + size_t er_begin, er_end, i; + + /* (DBG) monitor_write("<ksbrk "); + monitor_writeHex(size); + monitor_write(":"); + monitor_writeHex(tmp); + monitor_write("> "); */ + + mem_placementAddr += size; + + if (_no_more_ksbrk) { // paging enabled, we must allocate these pages + if (tmp < mem_placementAddr) { + er_begin = tmp; + if (er_begin & 0x0FFF) er_begin = (er_begin & 0xFFFFF000) + 0x1000; + er_end = mem_placementAddr; + if (er_end & 0x0FFF) er_end = (er_end & 0xFFFFF000) + 0x1000; + for (i = er_begin; i < er_end; i += 0x1000) { + page *p = pagedir_getPage(kernel_pagedir, i, 1); + size_t f = frame_alloc(); + page_map(p, f, 0, 0); + /* (DBG) monitor_write("<map "); monitor_writeHex(i); monitor_write(" "); + monitor_writeHex(f); monitor_write("> "); */ + } + } else if (tmp > mem_placementAddr) { + er_begin = (size_t)mem_placementAddr; + if (er_begin & 0x0FFF) er_begin = (er_begin & 0xFFFFF000) + 0x1000; + er_end = tmp; + if (er_end & 0x0FFF) er_end = (er_end & 0xFFFFF000) + 0x1000; + for (i = er_end - 0x1000; i >= er_begin; i -= 0x1000) { + // (DBG) monitor_write("<unmap:"); monitor_writeHex(i); monitor_write("> "); + page_unmapFree(pagedir_getPage(kernel_pagedir, i, 0)); + } + } + } + + return (void*)tmp; +} + +void kbrk(void* ptr) { + monitor_write("<kbrk "); + monitor_writeHex((uint32_t)ptr); + monitor_write(">\n"); + + if ((size_t)ptr > (size_t)&end) { + ksbrk((size_t)ptr - (size_t)mem_placementAddr); + } else { + PANIC("INVALID KBRK."); + } +} |