Luna/kernel/src/memory/KernelHeap.cpp

136 lines
3.6 KiB
C++

#define MODULE "kheap"
#include "memory/KernelHeap.h"
#include "assert.h"
#include "log/Log.h"
#include "std/string.h"
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
static uint8_t page_bitmap[2048];
static int64_t kheap_free = sizeof(page_bitmap) * 8 * PAGE_SIZE;
static int64_t kheap_used = 0;
#define ALLOC_BASE 0xfffffffff8000000
#define ALLOC_END 0xfffffffffc000000
// static uint64_t start_index = 0;
static bool bitmap_read(uint64_t index)
{
return (page_bitmap[index / 8] & (0b10000000 >> (index % 8))) > 0;
}
static void bitmap_set(uint64_t index, bool value)
{
uint64_t byteIndex = index / 8;
uint8_t bitIndexer = 0b10000000 >> (index % 8);
page_bitmap[byteIndex] &= ~bitIndexer;
if (value) { page_bitmap[byteIndex] |= bitIndexer; }
}
void KernelHeap::clear()
{
memset(page_bitmap, 0, sizeof(page_bitmap));
kinfoln("page bitmap located at %p", (void*)page_bitmap);
}
uint64_t KernelHeap::request_virtual_page()
{
for (uint64_t index = 0; index < sizeof(page_bitmap) * 8; index++)
{
if (bitmap_read(index)) continue;
bitmap_set(index, true);
// start_index = index + 1;
#ifdef KHEAP_DEBUG
kinfoln("allocating one page for caller %p, returning %lx", __builtin_return_address(0),
ALLOC_BASE + (index * PAGE_SIZE));
#endif
kheap_free -= PAGE_SIZE;
kheap_used += PAGE_SIZE;
#ifdef KHEAP_DEBUG
dump_usage();
#endif
return ALLOC_BASE + (index * PAGE_SIZE);
}
return 0;
}
uint64_t KernelHeap::request_virtual_pages(uint64_t count)
{
uint64_t contiguous = 0;
uint64_t contiguous_start = 0;
for (uint64_t index = 0; index < sizeof(page_bitmap) * 8; index++)
{
if (bitmap_read(index))
{
contiguous = 0;
continue;
}
if (contiguous == 0)
{
contiguous_start = index;
contiguous++;
}
else
contiguous++;
if (contiguous == count)
{
for (uint64_t i = 0; i < count; i++) bitmap_set(contiguous_start + i, true);
#ifdef KHEAP_DEBUG
kinfoln("allocating %lu pages for caller %p, returning %lx", count, __builtin_return_address(0),
ALLOC_BASE + (contiguous_start * PAGE_SIZE));
#endif
kheap_free -= (count * PAGE_SIZE);
kheap_used += (count * PAGE_SIZE);
#ifdef KHEAP_DEBUG
dump_usage();
#endif
return ALLOC_BASE + (contiguous_start * PAGE_SIZE);
}
}
return 0;
}
void KernelHeap::free_virtual_page(uint64_t address)
{
if (address < ALLOC_BASE || address >= ALLOC_END) return;
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
bitmap_set(index, false);
#ifdef KHEAP_DEBUG
kinfoln("releasing one page for caller %p, %lx", __builtin_return_address(0), address);
#endif
kheap_free += PAGE_SIZE;
kheap_used -= PAGE_SIZE;
#ifdef KHEAP_DEBUG
dump_usage();
#endif
// if (start_index > index) start_index = index;
}
void KernelHeap::free_virtual_pages(uint64_t address, uint64_t count)
{
if (address < ALLOC_BASE || address >= ALLOC_END) return;
uint64_t index = (address - ALLOC_BASE) / PAGE_SIZE;
for (uint64_t i = 0; i < count; i++) { bitmap_set(index + i, false); }
#ifdef KHEAP_DEBUG
kinfoln("releasing %lu pages for caller %p, %lx", count, __builtin_return_address(0), address);
#endif
kheap_free += (count * PAGE_SIZE);
kheap_used -= (count * PAGE_SIZE);
#ifdef KHEAP_DEBUG
dump_usage();
#endif
// if (start_index > index) start_index = index;
}
void KernelHeap::dump_usage()
{
kinfoln("Used: %ld KB", kheap_used / 1024);
kinfoln("Free: %ld KB", kheap_free / 1024);
}