feat(heap): Create new HeapAllocator implementation
This commit is contained in:
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -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
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
+95
-11
@@ -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;
|
||||||
|
return (Header*)(block - sizeof(Header));
|
||||||
|
}
|
||||||
|
|
||||||
HeapAllocator::HeapAllocator(LargestSection section)
|
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++;
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -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,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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user