120 lines
2.9 KiB
C++
120 lines
2.9 KiB
C++
|
|
#include <stdlib.h>
|
|
|
|
#include <stddef.h>
|
|
#include "os/tty.hpp"
|
|
|
|
namespace
|
|
{
|
|
inline const size_t INIT_MALLOC_SPACE_ELEMENTS = 1024 * 1024;
|
|
inline const size_t INIT_MALLOC_SPACE_BYTES = INIT_MALLOC_SPACE_ELEMENTS * alignof(max_align_t);
|
|
|
|
max_align_t gInitMallocSpace[INIT_MALLOC_SPACE_ELEMENTS];
|
|
|
|
struct MallocBlock
|
|
{
|
|
size_t elements;
|
|
MallocBlock* nextBlock;
|
|
};
|
|
struct AllocInfo
|
|
{
|
|
size_t elements;
|
|
};
|
|
static_assert(sizeof(MallocBlock) <= alignof(max_align_t));
|
|
static_assert(sizeof(AllocInfo) <= alignof(max_align_t));
|
|
|
|
MallocBlock* gNextBlock = []()
|
|
{
|
|
MallocBlock* initialBlock = reinterpret_cast<MallocBlock*>(gInitMallocSpace);
|
|
initialBlock->elements = INIT_MALLOC_SPACE_ELEMENTS;
|
|
initialBlock->nextBlock = nullptr;
|
|
return initialBlock;
|
|
}();
|
|
}
|
|
|
|
void __ba_registerAllocatableMemory(void* memory, size_t size) noexcept
|
|
{
|
|
if (size < sizeof(max_align_t))
|
|
{
|
|
return;
|
|
}
|
|
MallocBlock* newBlock = static_cast<MallocBlock*>(memory);
|
|
newBlock->nextBlock = gNextBlock;
|
|
newBlock->elements = size / sizeof(max_align_t);
|
|
gNextBlock = newBlock;
|
|
}
|
|
|
|
extern "C"
|
|
{
|
|
void abort()
|
|
{
|
|
tty::write("Abort called!");
|
|
__asm__ volatile("hlt");
|
|
while(true) {};
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
void* malloc(size_t size) noexcept
|
|
{
|
|
if (size == 0)
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
const size_t requiredElements = (size + sizeof(max_align_t) - 1) / sizeof(max_align_t) + 1;
|
|
MallocBlock* prevBlock = nullptr;
|
|
for (MallocBlock* block = gNextBlock; block != nullptr; block = block->nextBlock)
|
|
{
|
|
if (block->elements >= requiredElements)
|
|
{
|
|
MallocBlock* newBlock = nullptr;
|
|
if (block->elements > requiredElements)
|
|
{
|
|
newBlock = reinterpret_cast<MallocBlock*>(reinterpret_cast<max_align_t*>(block) + requiredElements);
|
|
newBlock->nextBlock = block->nextBlock;
|
|
newBlock->elements = block->elements - requiredElements;
|
|
}
|
|
else
|
|
{
|
|
newBlock = block->nextBlock;
|
|
}
|
|
if (prevBlock != nullptr)
|
|
{
|
|
prevBlock->nextBlock = newBlock;
|
|
}
|
|
else
|
|
{
|
|
gNextBlock = newBlock;
|
|
}
|
|
AllocInfo* allocInfo = reinterpret_cast<AllocInfo*>(block);
|
|
allocInfo->elements = requiredElements;
|
|
return reinterpret_cast<max_align_t*>(block) + 1;
|
|
}
|
|
prevBlock = block;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void free(void* memory) noexcept
|
|
{
|
|
if (memory == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
MallocBlock* block = reinterpret_cast<MallocBlock*>(static_cast<max_align_t*>(memory) - 1);
|
|
block->nextBlock = gNextBlock;
|
|
gNextBlock = block;
|
|
}
|
|
|
|
int __cxa_atexit(void (*func)(void*), void* arg, void* dsoHandle)
|
|
{
|
|
(void) func;
|
|
(void) arg;
|
|
(void) dsoHandle;
|
|
|
|
// NOOP for now
|
|
// TODO
|
|
return 0;
|
|
}
|
|
} // extern "C"
|