feat(heap): Create new HeapAllocator implementation

This commit is contained in:
Daniel Hammer
2025-03-15 11:29:05 +01:00
parent 2b6c2fa827
commit ff347b1da5
8 changed files with 125 additions and 36 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ ARCH := x86_64
# Default user QEMU flags. These are appended to the QEMU command calls. # Default user QEMU flags. These are appended to the QEMU command calls.
QEMUFLAGS := -m 2G -s -S QEMUFLAGS := -m 2G -s -S
override IMAGE_NAME := template-$(ARCH) override IMAGE_NAME := os220-$(ARCH)
# Toolchain for building the 'limine' executable for the host. # Toolchain for building the 'limine' executable for the host.
HOST_CC := cc HOST_CC := cc
+1 -1
View File
@@ -7,7 +7,7 @@
#include "Spinlock.hpp" #include "Spinlock.hpp"
namespace kcp { namespace kcp {
void Spinlock::Aquire() { void Spinlock::Acquire() {
while (atomic_flag.test_and_set(std::memory_order_acquire)); while (atomic_flag.test_and_set(std::memory_order_acquire));
} }
+1 -1
View File
@@ -11,7 +11,7 @@ namespace kcp {
class Spinlock { class Spinlock {
std::atomic_flag atomic_flag{ATOMIC_FLAG_INIT}; std::atomic_flag atomic_flag{ATOMIC_FLAG_INIT};
public: public:
void Aquire(); void Acquire();
void Release(); void Release();
}; };
}; };
+4 -1
View File
@@ -75,7 +75,10 @@ namespace kcp
size_t pages = 0; size_t pages = 0;
public: public:
noHeapVector() { noHeapVector() {
kout << "NoMallocVector: constructor called" << Kt::newline; // We shouldn't have used KernelOutStream in this constructor, will crash if used in a global object
// due to global constructors
// kout << "NoMallocVector: constructor called" << Kt::newline;
pages = 0; pages = 0;
this->sz = 0; this->sz = 0;
this->array = nullptr; this->array = nullptr;
+6 -8
View File
@@ -89,20 +89,18 @@ extern "C" void kmain() {
Memory::PageFrameAllocator pmm(Memory::Scan(memmap_request.response)); Memory::PageFrameAllocator pmm(Memory::Scan(memmap_request.response));
Memory::g_pfa = &pmm; Memory::g_pfa = &pmm;
Memory::HeapAllocator heap{};
Memory::g_heap = &heap;
heap.Walk();
} else { } else {
Panic("Guru Meditation Error: System memory map missing!", nullptr); Panic("System memory map missing!", nullptr);
} }
#if defined (__x86_64__) #if defined (__x86_64__)
Hal::IDTInitialize(); Hal::IDTInitialize();
#endif #endif
kcp::noHeapVector<int> hello{};
hello.push_back(10);
hello.push_back(20);
hello.push_back(30);
kout << base::dec << hello.at(0) << hello.at(1) << hello.at(2) << newline;
hcf(); hcf();
} }
+96 -12
View File
@@ -14,38 +14,122 @@
#include <Platform/Util.hpp> #include <Platform/Util.hpp>
#include <Common/Panic.hpp> #include <Common/Panic.hpp>
#include <CppLib/Vector.hpp>
#include "PageFrameAllocator.hpp"
namespace Memory namespace Memory
{ {
constexpr size_t metadata_size = 8; // 8 bytes HeapAllocator::Header* HeapAllocator::GetHeader(void* block) {
uintptr_t ptr = (uintptr_t)block;
HeapAllocator::HeapAllocator(LargestSection section) return (Header*)(block - sizeof(Header));
}
size_t HeapAllocator::GetAllocatedBlockSize(void* ptr) {
Header* header = GetHeader(ptr);
return header->size;
}
void HeapAllocator::InsertToFreelist(void* ptr, std::size_t size) {
auto prev_next = head.next;
head.next = (Node*)ptr;
head.next->next = prev_next;
head.next->size = size;
}
void HeapAllocator::InsertPageToFreelist() {
InsertToFreelist(Memory::g_pfa->Allocate(), 0x1000);
}
void HeapAllocator::InsertPagesToFreelist(std::size_t n) {
auto ptr = Memory::g_pfa->ReallocConsecutive(nullptr, n);
size_t size = 0x1000 * n;
InsertToFreelist(ptr, size);
kout << "HeapAllocator: expanded heap by " << base::dec << n << " pages" << Kt::newline;
}
HeapAllocator::HeapAllocator()
{ {
kout << "HeapAllocator: constructor called" << Kt::newline; kout << "HeapAllocator: constructor called" << Kt::newline;
InsertPagesToFreelist(8);
} }
void* HeapAllocator::Request(size_t size) { void* HeapAllocator::Request(size_t size) {
return nullptr; Node* current = head.next;
Node* prev = &head;
size_t sizeNeeded = size + sizeof(Header);
while (current != nullptr) {
if (current->size >= sizeNeeded) {
// Unlink the node
auto locatedBlockSize = current->size;
prev->next = current->next;
Header* header = (Header*)current;
header->size = size;
void* block = (void*)((uintptr_t)header + sizeof(Header));
if (locatedBlockSize > sizeNeeded) {
void* rest = (void*)((uintptr_t)header + sizeNeeded);
auto newBlockSize = locatedBlockSize - sizeNeeded;
InsertToFreelist(rest, newBlockSize);
}
return block;
}
prev = current;
current = current->next;
}
// First pass allocation failed
size_t pagesNeeded = size / 0x1000;
InsertPagesToFreelist(pagesNeeded);
return Request(size);
} }
void* HeapAllocator::Realloc(void* ptr, size_t size) { void* HeapAllocator::Realloc(void* ptr, size_t size) {
return nullptr; auto new_block = Request(size);
if (ptr != nullptr && new_block != nullptr) {
memcpy(new_block, ptr, size);
Free(ptr);
}
return new_block;
} }
void HeapAllocator::Free(void* ptr) { void HeapAllocator::Free(void* ptr) {
Header* header = GetHeader(ptr);
auto size = header->size;
auto actualSize = size + sizeof(Header);
void* actualBlock = (void*)header;
auto prev_next = head.next;
// Relink the full node back into the list
head.next = (Node*)actualBlock;
head.next->size = actualSize;
head.next->next = prev_next;
} }
// Traverses the Allocator's linked list for debugging // Traverses the Allocator's linked list for debugging
void HeapAllocator::Walk() { void HeapAllocator::Walk() {
// Node* current = {head.next}; Node* current = {head.next};
// size_t i{0}; size_t i{0};
// while (current != nullptr) { while (current != nullptr) {
// kout << "Block " << base::dec << i << " {" << current->size << " bytes & address 0x" << base::hex << (uint64_t)current << "}" << Kt::newline; kout << "HeapAllocator: " << base::dec << i << " " << current->size << " bytes & address 0x" << base::hex << (uint64_t)current << Kt::newline;
// current = current->next; current = current->next;
// i++; i++;
// } }
} }
}; };
+10 -7
View File
@@ -3,25 +3,28 @@
namespace Memory { namespace Memory {
class HeapAllocator { class HeapAllocator {
LargestSection g_section;
struct Node { struct Node {
size_t size; size_t size;
Node* next; Node* next;
}; };
struct Metadata { struct Header {
size_t size; std::size_t size;
}; }__attribute__((packed));
Node head{0, 0}; Node head{};
Header* GetHeader(void* block);
void InsertToFreelist(void* ptr, std::size_t size);
void InsertPageToFreelist();
void InsertPagesToFreelist(std::size_t n);
public: public:
HeapAllocator(LargestSection section); HeapAllocator();
void* Request(size_t size); void* Request(size_t size);
void* Realloc(void* ptr, size_t size); void* Realloc(void* ptr, size_t size);
void Free(void *pagePtr); void Free(void *pagePtr);
void Walk(); void Walk();
size_t GetAllocatedBlockSize(void* ptr);
}; };
extern HeapAllocator* g_heap; extern HeapAllocator* g_heap;
+6 -5
View File
@@ -6,11 +6,10 @@
#include "PageFrameAllocator.hpp" #include "PageFrameAllocator.hpp"
#include "HHDM.hpp" #include "HHDM.hpp"
#include <Libraries/Memory.hpp> #include <Libraries/Memory.hpp>
#include <Terminal/Terminal.hpp> #include <Terminal/Terminal.hpp>
#include <CppLib/Spinlock.hpp> #include <CppLib/Spinlock.hpp>
#include <Common/Panic.hpp>
namespace Memory { namespace Memory {
PageFrameAllocator::PageFrameAllocator(LargestSection section) { PageFrameAllocator::PageFrameAllocator(LargestSection section) {
@@ -26,7 +25,7 @@ namespace Memory {
} }
void* PageFrameAllocator::Allocate() { void* PageFrameAllocator::Allocate() {
Lock.Aquire(); Lock.Acquire();
Page* current = head.next; Page* current = head.next;
Page* prev = &head; Page* prev = &head;
@@ -64,7 +63,9 @@ namespace Memory {
auto first = Allocate(); auto first = Allocate();
for (int i = 0; i < n - 1; i++) { for (int i = 0; i < n - 1; i++) {
Allocate(); if (Allocate() == nullptr) {
Panic("PageFrameAllocator Reallocation failed", nullptr);
};
} }
if (ptr != nullptr) { if (ptr != nullptr) {
@@ -76,7 +77,7 @@ namespace Memory {
} }
void PageFrameAllocator::Free(void* ptr) { void PageFrameAllocator::Free(void* ptr) {
Lock.Aquire(); Lock.Acquire();
auto prev_next = head.next; auto prev_next = head.next;
head.next = (Page*)ptr; head.next = (Page*)ptr;