#include "memorymanagement.hpp"
#include <cstdint>
#include <new>
#include "assert.hpp"
struct MemoryManager::MemoryChunk
{
MemoryChunk *next;
MemoryChunk *prev;
bool allocated;
std::size_t size;
std::uint8_t data[];
};
static MemoryManager *activeMemoryManager = nullptr;
MemoryManager::MemoryManager(void *area, std::size_t size)
{
activeMemoryManager = this;
if (size < sizeof(MemoryChunk)) {
head = nullptr;
return;
}
head = new(area) MemoryChunk;
head->allocated = false;
head->prev = nullptr;
head->next = nullptr;
head->size = size - sizeof(MemoryChunk);
}
MemoryManager::~MemoryManager()
{
if (activeMemoryManager == this) {
activeMemoryManager = nullptr;
}
}
void *
MemoryManager::malloc(std::size_t size)
{
MemoryChunk *result = nullptr;
for (MemoryChunk *chunk = head; chunk != nullptr; chunk = chunk->next) {
if (chunk->size >= size && !chunk->allocated) {
result = chunk;
break;
}
}
if (result == nullptr) {
return nullptr;
}
if (result->size >= size + sizeof(MemoryChunk) + 1) {
MemoryChunk *tail = new(result->data + size) MemoryChunk;
tail->allocated = false;
tail->size = result->size - size - sizeof(MemoryChunk);
tail->prev = result;
tail->next = result->next;
if (tail->next != nullptr) {
tail->next->prev = tail;
}
result->size = size;
result->next = tail;
}
result->allocated = true;
return result->data;
}
void
MemoryManager::free(void *ptr)
{
MemoryChunk *chunk = static_cast<MemoryChunk *>(ptr) - 1;
chunk->allocated = false;
if (chunk->prev != nullptr && !chunk->prev->allocated) {
chunk->prev->next = chunk->next;
chunk->prev->size += chunk->size + sizeof(MemoryChunk);
if (chunk->next != nullptr) {
chunk->next->prev = chunk->prev;
}
chunk = chunk->prev;
}
if (chunk->next != nullptr && !chunk->next->allocated) {
chunk->size += chunk->next->size + sizeof(MemoryChunk);
chunk->next = chunk->next->next;
if (chunk->next != nullptr) {
chunk->next->prev = chunk;
}
}
}
void *
operator new(std::size_t size)
{
kassert(activeMemoryManager != nullptr, "Memory management isn't ready!");
return activeMemoryManager->malloc(size);
}
void *
operator new[](std::size_t size)
{
kassert(activeMemoryManager != nullptr, "Memory management isn't ready!");
return activeMemoryManager->malloc(size);
}
void
operator delete(void *ptr)
{
if (activeMemoryManager != nullptr) {
activeMemoryManager->free(ptr);
}
}
void
operator delete[](void *ptr)
{
if (activeMemoryManager != nullptr) {
activeMemoryManager->free(ptr);
}
}
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/tos
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/tos
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master