You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
4.8 KiB
206 lines
4.8 KiB
|
|
#include "alloc.h"
|
|
#include "string.h"
|
|
#include "print.h"
|
|
#include "types.h"
|
|
|
|
|
|
#if false
|
|
static void* leakcheckMalloc(size_t size, const char* file, s32 line) {
|
|
ULE_TYPES_H_FTAG;
|
|
return malloc(size);
|
|
}
|
|
|
|
static void* leakcheckCalloc(size_t maxNumOfElements, size_t elementSize, const char* file, s32 line) {
|
|
ULE_TYPES_H_FTAG;
|
|
return calloc(maxNumOfElements, elementSize);
|
|
}
|
|
|
|
static void* leakcheckRealloc(void* buffer, size_t newSize, const char* file, s32 line) {
|
|
ULE_TYPES_H_FTAG;
|
|
return realloc(buffer, newSize);
|
|
}
|
|
|
|
static void leakcheckFree(void* ptr, const char* file, s32 line) {
|
|
ULE_TYPES_H_FTAG;
|
|
free(ptr);
|
|
}
|
|
|
|
#define malloc(size) leakcheckMalloc(size, __FILE__, __LINE__)
|
|
#define calloc(numElements, size) leakcheckCalloc(numElements, size, __FILE__, __LINE__)
|
|
#define realloc(buffer, newSize) leakcheckRealloc(buffer, newSize, __FILE__, __LINE__)
|
|
#define free(ptr) leakcheckFree(ptr, __FILE__, __LINE__)
|
|
|
|
static void dumpLeaks() {
|
|
void* address;
|
|
size_t size;
|
|
const char* file;
|
|
s32 line;
|
|
for (;;) {
|
|
println("%p - %lu, %s:%d", address, size, file, line);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// system allocators
|
|
void* pMalloc(size_t size) {
|
|
ULE_TYPES_H_FTAG;
|
|
void* p = malloc(size);
|
|
|
|
if (!p) {
|
|
die("Out of memory!n\nfailed to malloc %p with size %u\n", p, size);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
void* pMalloc(size_t size, void* allocatorState) {
|
|
ULE_TYPES_H_FTAG;
|
|
return pMalloc(size);
|
|
}
|
|
|
|
void* pCalloc(size_t maxNumOfElements, size_t elementSize) {
|
|
ULE_TYPES_H_FTAG;
|
|
void* p = calloc(maxNumOfElements, elementSize);
|
|
|
|
if (!p) {
|
|
die("Out of memory!\nfailed to calloc %p with %u elements of size %u\n", p, maxNumOfElements, elementSize);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
void* pCalloc(size_t maxNumOfElements, size_t elementSize, void* allocatorState) {
|
|
ULE_TYPES_H_FTAG;
|
|
return pCalloc(maxNumOfElements, elementSize);
|
|
}
|
|
|
|
void* pRealloc(void* buffer, size_t newSize) {
|
|
ULE_TYPES_H_FTAG;
|
|
void* p = realloc(buffer, newSize);
|
|
|
|
if (!p) {
|
|
//pFree(buffer); // if we ever *don't* terminate the program at this point, we should free |buffer|
|
|
die("Out of memory!\nfailed to realloc %p with size: %u\n", buffer, newSize);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
void* pRealloc(void* buffer, size_t newSize, void* allocatorState) {
|
|
ULE_TYPES_H_FTAG;
|
|
return pRealloc(buffer, newSize);
|
|
}
|
|
|
|
void pFree(void* ptr) {
|
|
ULE_TYPES_H_FTAG;
|
|
free(ptr);
|
|
}
|
|
void pFree(void* ptr, void* allocatorState) {
|
|
ULE_TYPES_H_FTAG;
|
|
pFree(ptr);
|
|
}
|
|
|
|
void pFree(const void* ptr) {
|
|
ULE_TYPES_H_FTAG;
|
|
pFree((void*) ptr);
|
|
}
|
|
void pFree(const void* ptr, void* allocatorState) {
|
|
ULE_TYPES_H_FTAG;
|
|
pFree((void*) ptr, allocatorState);
|
|
}
|
|
|
|
#ifdef malloc
|
|
#undef malloc
|
|
#endif
|
|
#ifdef calloc
|
|
#undef calloc
|
|
#endif
|
|
#ifdef realloc
|
|
#undef realloc
|
|
#endif
|
|
#ifdef free
|
|
#undef free
|
|
#endif
|
|
|
|
static bool DefaultAllocatorInited = false;
|
|
static Allocator DefaultAllocator;
|
|
static void defaultAllocatorInit() {
|
|
ULE_TYPES_H_FTAG;
|
|
DefaultAllocator.state = null;
|
|
DefaultAllocator.mallocate = pMalloc;
|
|
DefaultAllocator.callocate = pCalloc;
|
|
DefaultAllocator.reallocate = pRealloc;
|
|
DefaultAllocator.free = pFree;
|
|
DefaultAllocatorInited = true;
|
|
}
|
|
|
|
Allocator* Allocator::GetDefault() {
|
|
ULE_TYPES_H_FTAG;
|
|
if (!DefaultAllocatorInited) defaultAllocatorInit();
|
|
return &DefaultAllocator;
|
|
}
|
|
|
|
//================================================================================
|
|
// alignment should be a power of 2
|
|
static u64 alignForward2(u64 ptr, size_t alignment) {
|
|
ULE_TYPES_H_FTAG;
|
|
u64 p, a, modulo;
|
|
|
|
p = ptr;
|
|
a = alignment;
|
|
modulo = p & (a - 1);
|
|
|
|
if (modulo != 0) {
|
|
p += a - modulo;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
static u64 alignForward(u64 ptr, size_t alignment) {
|
|
ULE_TYPES_H_FTAG;
|
|
return ((ptr + alignment - 1) / alignment) * alignment;
|
|
}
|
|
|
|
//================================================================================
|
|
// Scratch/Arena
|
|
Arena* Arena::Init(u32 sizeInBytes) {
|
|
ULE_TYPES_H_FTAG;
|
|
Arena* arena = (Arena*) pMalloc(sizeof(Arena));
|
|
arena->index = 0;
|
|
arena->buffer = (u8*) pMalloc(sizeof(u8) * sizeInBytes);
|
|
arena->bufferSizeInBytes = sizeInBytes;
|
|
return arena;
|
|
}
|
|
void* Arena::Alloc(u32 sizeInBytes) {
|
|
ULE_TYPES_H_FTAG;
|
|
u8* p = this->buffer + this->index;
|
|
u32 offset = (u32) alignForward2((u64) p, 64);
|
|
|
|
if ((void*)(offset + sizeInBytes) <= (this->buffer + this->bufferSizeInBytes)) {
|
|
void* ptr = &this->buffer[offset];
|
|
this->index += offset + sizeInBytes;
|
|
|
|
String::memset(ptr, 0, sizeInBytes);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
void Arena::Clear() {
|
|
ULE_TYPES_H_FTAG;
|
|
this->index = 0;
|
|
}
|
|
//================================================================================
|
|
|
|
struct StackAllocator {
|
|
u32 bufferSize;
|
|
u32 index;
|
|
u8* buffer;
|
|
};
|
|
|
|
struct PoolAllocator {
|
|
u8* buffer;
|
|
};
|
|
|
|
|
|
|