diff --git a/GNUmakefile b/GNUmakefile index 5d338f6..add7591 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -8,7 +8,7 @@ ARCH := x86_64 # Default user QEMU flags. These are appended to the QEMU command calls. QEMUFLAGS := -m 2G -s -S -override IMAGE_NAME := template-$(ARCH) +override IMAGE_NAME := os220-$(ARCH) # Toolchain for building the 'limine' executable for the host. HOST_CC := cc diff --git a/kernel/src/CppLib/Spinlock.cpp b/kernel/src/CppLib/Spinlock.cpp index c1db6d6..a41ceb0 100644 --- a/kernel/src/CppLib/Spinlock.cpp +++ b/kernel/src/CppLib/Spinlock.cpp @@ -7,7 +7,7 @@ #include "Spinlock.hpp" namespace kcp { - void Spinlock::Aquire() { + void Spinlock::Acquire() { while (atomic_flag.test_and_set(std::memory_order_acquire)); } diff --git a/kernel/src/CppLib/Spinlock.hpp b/kernel/src/CppLib/Spinlock.hpp index d0711fd..77112ac 100644 --- a/kernel/src/CppLib/Spinlock.hpp +++ b/kernel/src/CppLib/Spinlock.hpp @@ -11,7 +11,7 @@ namespace kcp { class Spinlock { std::atomic_flag atomic_flag{ATOMIC_FLAG_INIT}; public: - void Aquire(); + void Acquire(); void Release(); }; }; \ No newline at end of file diff --git a/kernel/src/CppLib/Vector.hpp b/kernel/src/CppLib/Vector.hpp index 6adcf38..94e67de 100644 --- a/kernel/src/CppLib/Vector.hpp +++ b/kernel/src/CppLib/Vector.hpp @@ -75,7 +75,10 @@ namespace kcp size_t pages = 0; public: 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; this->sz = 0; this->array = nullptr; diff --git a/kernel/src/Main.cpp b/kernel/src/Main.cpp index 92909ce..6d947e7 100644 --- a/kernel/src/Main.cpp +++ b/kernel/src/Main.cpp @@ -89,20 +89,18 @@ extern "C" void kmain() { Memory::PageFrameAllocator pmm(Memory::Scan(memmap_request.response)); Memory::g_pfa = &pmm; + Memory::HeapAllocator heap{}; + Memory::g_heap = &heap; + + heap.Walk(); + } else { - Panic("Guru Meditation Error: System memory map missing!", nullptr); + Panic("System memory map missing!", nullptr); } #if defined (__x86_64__) Hal::IDTInitialize(); #endif - kcp::noHeapVector 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(); } diff --git a/kernel/src/Memory/Heap.cpp b/kernel/src/Memory/Heap.cpp index eeb19c9..2e13ae9 100644 --- a/kernel/src/Memory/Heap.cpp +++ b/kernel/src/Memory/Heap.cpp @@ -14,38 +14,122 @@ #include #include +#include + +#include "PageFrameAllocator.hpp" namespace Memory { - constexpr size_t metadata_size = 8; // 8 bytes - - HeapAllocator::HeapAllocator(LargestSection section) + HeapAllocator::Header* HeapAllocator::GetHeader(void* block) { + uintptr_t ptr = (uintptr_t)block; + 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; + InsertPagesToFreelist(8); } 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) { - 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) { + 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 void HeapAllocator::Walk() { - // Node* current = {head.next}; - // size_t i{0}; + Node* 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++; - // } + while (current != nullptr) { + kout << "HeapAllocator: " << base::dec << i << " " << current->size << " bytes & address 0x" << base::hex << (uint64_t)current << Kt::newline; + current = current->next; + i++; + } } }; \ No newline at end of file diff --git a/kernel/src/Memory/Heap.hpp b/kernel/src/Memory/Heap.hpp index b551524..ac49c2a 100644 --- a/kernel/src/Memory/Heap.hpp +++ b/kernel/src/Memory/Heap.hpp @@ -3,25 +3,28 @@ namespace Memory { class HeapAllocator { - LargestSection g_section; - struct Node { size_t size; Node* next; }; - struct Metadata { - size_t size; - }; + struct Header { + 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: - HeapAllocator(LargestSection section); + HeapAllocator(); void* Request(size_t size); void* Realloc(void* ptr, size_t size); void Free(void *pagePtr); void Walk(); + size_t GetAllocatedBlockSize(void* ptr); }; extern HeapAllocator* g_heap; diff --git a/kernel/src/Memory/PageFrameAllocator.cpp b/kernel/src/Memory/PageFrameAllocator.cpp index 05da1fd..6815058 100644 --- a/kernel/src/Memory/PageFrameAllocator.cpp +++ b/kernel/src/Memory/PageFrameAllocator.cpp @@ -6,11 +6,10 @@ #include "PageFrameAllocator.hpp" #include "HHDM.hpp" - #include #include - #include +#include namespace Memory { PageFrameAllocator::PageFrameAllocator(LargestSection section) { @@ -26,7 +25,7 @@ namespace Memory { } void* PageFrameAllocator::Allocate() { - Lock.Aquire(); + Lock.Acquire(); Page* current = head.next; Page* prev = &head; @@ -64,7 +63,9 @@ namespace Memory { auto first = Allocate(); for (int i = 0; i < n - 1; i++) { - Allocate(); + if (Allocate() == nullptr) { + Panic("PageFrameAllocator Reallocation failed", nullptr); + }; } if (ptr != nullptr) { @@ -76,7 +77,7 @@ namespace Memory { } void PageFrameAllocator::Free(void* ptr) { - Lock.Aquire(); + Lock.Acquire(); auto prev_next = head.next; head.next = (Page*)ptr;