Allocator improvements, kernel C++ platform, streaming

This commit is contained in:
Daniel Hammer
2025-03-01 03:31:14 +04:00
parent 6f1c6f1316
commit 17d0bbf1bb
16 changed files with 367 additions and 166 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
#include "Memmap.hpp"
#include <KernelTerminal/terminal.hpp>
#include <Terminal/terminal.hpp>
#include <Common/Panic.hpp>
#include "PageAllocator.hpp"
#include "MemoryAllocator.hpp"
using namespace Kt;
+174
View File
@@ -0,0 +1,174 @@
/*
* MemoryAllocator.cpp
* Heap memory allocator
* Copyright (c) 2025 Daniel Hammer
*/
#include "MemoryAllocator.hpp"
#include "Memmap.hpp"
#include "HHDM.hpp"
#include <Libraries/Memory.hpp>
#include <Terminal/terminal.hpp>
namespace Memory
{
#if defined(__x86_64__) || defined(__aarch64__)
#define PAGE_SIZE 0x1000
#else
#error Sorry, Unimplemented!
#endif
Allocator::Allocator(LargestSection section)
{
g_section = section;
Block *current_ref{&head};
Block *start_block_ptr {(Block *)HHDM(section.address)};
Block& start_block = *start_block_ptr;
start_block = Block {
.size = section.size,
.next = nullptr
};
*start_block_ptr = start_block;
current_ref->next = start_block_ptr;
kout << "[Mem] Allocator created for memory section starting at 0x" << base::hex << section.address << Kt::newline;
}
int i = 1;
void* Allocator::Request(size_t size, bool phys) {
Block* current_block_ptr{head.next};
Block* current_prev_ptr{(Block *)&head};
while (true) {
if (current_block_ptr == nullptr) {
kerr << "An allocator was forced to return a Null pointer. (1)" << Kt::newline;
return nullptr;
}
if (current_prev_ptr == nullptr) {
kerr << "An allocator was forced to return a Null pointer. (2)" << Kt::newline;
return nullptr;
}
size_t descriptor_size = 8;
size_t total_size = size + descriptor_size;
if (current_block_ptr->size >= total_size) {
Block block_copy = *current_block_ptr;
BlockDescriptor* descriptor {(BlockDescriptor *)current_block_ptr};
descriptor->block_size = size;
void* block_start = (void *)(uint64_t)current_block_ptr + descriptor_size;
if (!block_copy.size) {
current_prev_ptr->next = block_copy.next;
}
else
{
block_copy.size -= total_size;
current_prev_ptr->next = (Block *)(uint64_t)descriptor + total_size;
*current_prev_ptr->next = block_copy;
}
if (phys) {
return (void *)SubHHDM(current_block_ptr);
}
return (void *)block_start;
} else {
if (current_block_ptr->next != nullptr) {
current_prev_ptr = current_block_ptr;
current_block_ptr = current_block_ptr->next;
continue;
} else {
kerr << "An allocator was forced to return a Null pointer. (3)" << Kt::newline;
return nullptr;
}
}
if (current_block_ptr != nullptr) {
if (current_block_ptr->next == nullptr) {
kerr << "An allocator was forced to return a Null pointer. (4)" << Kt::newline;
return nullptr;
}
current_block_ptr = current_block_ptr->next;
} else
{
kerr << "An allocator was forced to return a Null pointer. (5)" << Kt::newline;
return nullptr;
}
}
return nullptr;
}
void* Allocator::Realloc(void* ptr, size_t size) {
void *new_block = this->Request(size);
if (ptr == nullptr) {
return new_block;
}
if (new_block == nullptr) {
kerr << "Reallocation failed due to memory starvation" << Kt::newline;
return nullptr;
}
BlockDescriptor* descriptor = (BlockDescriptor*)((uint64_t)ptr - 8);
memcpy(new_block, ptr, descriptor->block_size);
this->Free(ptr);
return new_block;
}
void Allocator::Free(void *pagePtr) {
if (!IsHDDMVirtAddr((uint64_t)pagePtr)) {
pagePtr = (void *)HHDM(pagePtr);
}
BlockDescriptor* descriptor_ptr = (BlockDescriptor*)((uint64_t)pagePtr - 8);
BlockDescriptor descriptor = *descriptor_ptr;
Block* fmrNext = head.next;
Block* blockPtr = (Block *)pagePtr;
// Merge the descriptor with the block
Block* base = (Block *)((uint64_t)blockPtr - 8);
head.next = base;
// Set the full size
base->size = descriptor.block_size + 8;
// Attach the merged block to the structure
head.next->next = fmrNext;
}
void Allocator::Stress() {
// ~410 MiB
for (size_t i = 0; i < 100000; i++) {
kout << "[Mem] Stress allocation " << base::dec << i << ": " << "0x" << base::hex << (uint64_t)this->Request(PAGE_SIZE, false) << Kt::newline;
}
}
// Traverses the Allocator's linked list for debugging
void Allocator::Walk() {
Block* current = {head.next};
size_t i{0};
while (current != nullptr) {
kout << "Block " << base::dec << i << " {" << current->size << " bytes & address 0x" << base::hex << (uint64_t)current << "}" << Kt::newline;
current = current->next;
i++;
}
}
};
@@ -2,7 +2,7 @@
#include "Memmap.hpp"
namespace Memory {
class PageAllocator {
class Allocator {
LargestSection g_section;
struct Block {
@@ -10,15 +10,20 @@ namespace Memory {
Block* next;
};
struct BlockDescriptor {
size_t block_size;
};
Block head;
public:
PageAllocator(LargestSection section);
void* RequestPage(bool phys = false);
Allocator(LargestSection section);
void* Request(size_t size, bool phys = false);
void* Realloc(void* ptr, size_t size);
void Free(void *pagePtr);
void Stress();
void Walk();
};
extern PageAllocator* KernelPFA;
extern Allocator* g_allocator;
};
-131
View File
@@ -1,131 +0,0 @@
#include "PageAllocator.hpp"
#include "Memmap.hpp"
#include "HHDM.hpp"
#include <KernelTerminal/terminal.hpp>
namespace Memory
{
#if defined(__x86_64__) || defined(__aarch64__)
#define PAGE_SIZE 4096
#else
#error Sorry, Unimplemented!
#endif
PageAllocator::PageAllocator(LargestSection section)
{
g_section = section;
size_t pages = g_section.size / PAGE_SIZE;
Block *current_ref{&head};
Block *start_block_ptr {(Block *)HHDM(section.address)};
Block& start_block = *start_block_ptr;
start_block = Block {
.size = section.size,
.next = nullptr
};
*start_block_ptr = start_block;
current_ref->next = start_block_ptr;
kout << "[Mem] PageAllocator created for memory section starting at 0x" << Kt::base::hex << section.address << Kt::newline;
}
void* PageAllocator::RequestPage(bool phys) {
bool found_block = false;
Block* current_block_ptr{head.next};
Block* current_prev_ptr{(Block *)&head};
while (!found_block) {
if (current_block_ptr == nullptr) {
kerr << "A PageAllocator was forced to return a Null pointer. (1)" << Kt::newline;
return nullptr;
}
if (current_prev_ptr == nullptr) {
kerr << "A PageAllocator was forced to return a Null pointer. (2)" << Kt::newline;
return nullptr;
}
if (current_block_ptr->size >= 0x1000) { // 0x1000 == 4096
current_block_ptr->size -= 0x1000;
if (!current_block_ptr->size) {
current_prev_ptr->next = current_block_ptr->next;
return (void *)current_block_ptr;
}
Block block_copy = *current_block_ptr;
current_prev_ptr->next = (Block *)(uint64_t)current_block_ptr + 0x1000;
*current_prev_ptr->next = block_copy;
if (phys) {
return (void *)SubHHDM(current_block_ptr);
}
return (void *)current_block_ptr;
} else {
if (current_block_ptr->next != nullptr) {
current_prev_ptr = current_block_ptr;
current_block_ptr = current_block_ptr->next;
} else {
kerr << "A PageAllocator was forced to return a Null pointer. (3)" << Kt::newline;
return nullptr;
}
}
if (current_block_ptr != nullptr) {
if (current_block_ptr->next == nullptr) {
kerr << "A PageAllocator was forced to return a Null pointer. (4)" << Kt::newline;
return nullptr;
}
current_block_ptr = current_block_ptr->next;
} else
{
kerr << "A PageAllocator was forced to return a Null pointer. (5)" << Kt::newline;
return nullptr;
}
}
return nullptr;
}
void PageAllocator::Free(void *pagePtr) {
if (!IsHDDMVirtAddr((uint64_t)pagePtr)) {
pagePtr = (void *)HHDM(pagePtr);
}
Block* fmrNext = head.next;
Block* blockPtr = (Block *)pagePtr;
head.next = blockPtr;
head.next->size = 0x1000;
head.next->next = fmrNext;
}
void PageAllocator::Stress() {
// ~410 MiB
for (size_t i = 0; i < 100000; i++) {
kout << "[Mem] Stress allocation " << Kt::base::dec << i << ": " << "0x" << Kt::base::hex << (uint64_t)Memory::KernelPFA->RequestPage(false) << Kt::newline;
}
}
// Traverses the PageAllocator's linked list for debugging
void PageAllocator::Walk() {
Block* current = {head.next};
size_t i{0};
while (current != nullptr) {
kout << "Block " << Kt::base::dec << i << " {" << current->size << " bytes & address 0x" << Kt::base::hex << (uint64_t)current << "}" << Kt::newline;
current = current->next;
i++;
}
}
};