#include "mem.h" #include #include "paging.h" #include #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; 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(" "); */ } } 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(" "); page_unmapFree(pagedir_getPage(kernel_pagedir, i, 0)); } } } return (void*)tmp; } void kbrk(void* ptr) { if ((size_t)ptr > (size_t)&end) { ksbrk((size_t)ptr - (size_t)mem_placementAddr); } else { PANIC("INVALID KBRK."); } }