further allocator work, incomplete but will eventually return

This commit is contained in:
Matthew 2025-04-21 14:44:41 +10:00
parent 8c45c914f0
commit 16e3732bbe
9 changed files with 129 additions and 123 deletions

View File

@ -6,17 +6,13 @@ read_only FLNode FL_NIL_NODE = {0};
// ::Allocator::Util::Header::
usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
static inline usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
{
Assert(IsPow2(alignment), "Alignment provided to CalcPaddingWithHeader is not a power of two");
uintptr modulo = ptr & (alignment-1);
uintptr padding = 0;
uintptr padding = CalcPadding(ptr, alignment);
uintptr needed_space = (uintptr)header_size;
if (modulo != 0)
padding = alignment - modulo;
if (padding < needed_space)
{
needed_space -= padding;
@ -30,20 +26,44 @@ usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size)
return (usize)padding;
}
static inline usize CalcPadding(uintptr ptr, uintptr alignment)
{
Assert(IsPow2(alignment), "CalcPadding failure: IsPow2 failed");
uintptr padding = 0;
uintptr modulo = ptr & (alignment-1);
if (modulo != 0)
padding = alignment - modulo;
return (usize)padding;
}
// ::Allocator::Arena::Start::
static Arena *ArenaInit(rawptr buffer, usize length)
static Arena *ArenaInit(rawptr buffer, usize size)
{
Arena *arena = (Arena *)buffer;
buffer = PtrAdd(buffer, ARENA_HEADER_SIZE);
arena->buffer = buffer;
arena->length = length;
arena->length = size;
arena->pos = 0;
return arena;
}
static Arena *ArenaCreate(usize size)
{
u8 *mem = MemAllocZeroed(size);
return ArenaInit(mem, size);
}
static Arena *ArenaCreateDebug(usize size, u32 init_line_no)
{
u8 *mem = MemAllocZeroed(size);
return ArenaInitDebug(mem, size, init_line_no);
}
static rawptr ArenaAllocAlign(Arena *arena, usize size, usize align)
{
rawptr ptr = NULL;
@ -87,9 +107,9 @@ static void DeallocArena(Arena *arena)
MemFree(arena, arena->length);
}
static Arena * ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no)
static Arena * ArenaInitDebug(rawptr buffer, usize size, u32 init_line_no)
{
Arena *arena = ArenaInit(buffer, length);
Arena *arena = ArenaInit(buffer, size);
arena->init_line_no = init_line_no;
return arena;
}
@ -113,48 +133,7 @@ static void InitAllocator(usize init_size)
ALLOC.tree = FLMemAlloc(sizeof(RBTree));
RBTreeInit(ALLOC.tree);
AllocInfo *info = CreateAllocInfo(ALLOC.buffer);
RBTreeFindOrInsert(ALLOC.tree, init_size, info);
}
static AllocInfo *CreateAllocInfo(rawptr ptr)
{
AllocInfo *info = FLMemAlloc(sizeof(AllocInfo));
info->ptrs = FLMemAlloc(sizeof(rawptr *));
info->ptrs[0] = ptr;
info->count = 1;
}
static void AllocInfoAdd(AllocInfo *info, rawptr ptr)
{
rawptr *ptrs = FLMemAlloc(sizeof(rawptr) * (info->count+1));
MemCpy(ptrs, info->ptrs, sizeof(rawptr) * (info->count+1));
FLMemFree(info->ptrs);
info->ptrs = ptrs;
}
static void AllocInfoRemove(AllocInfo *info, rawptr ptr)
{
u32 index = UINT32_MAX;
for (u32 i = 0; i < info->count; i++)
{
if (info->ptrs[i] == ptr)
{
index = i;
break;
}
}
Assert(index != UINT32_MAX, "AllocInfoRemove called with invalid pointer");
rawptr *ptrs = FLMemAlloc(sizeof(rawptr) * (info->count-1));
MemCpy(ptrs, info->ptrs, index);
MemCpy(&ptrs[index], &info->ptrs[index+1], info->count-index-1);
FLMemFree(info->ptrs);
info->ptrs = ptrs;
info->count -= 1;
RBTreeInsert(ALLOC.tree, init_size, ALLOC.buffer);
}
static void DeinitAlloc()
@ -171,22 +150,29 @@ static rawptr AllocAlign(usize size, usize alignment)
{
if (size == 0) return NULL;
usize padding = 0;
if (alignment < 8)
alignment = 8;
RBNode *node = P_RB_NIL;
rawptr mem = NULL;
if (!RBTreeSearchNearest(ALLOC.tree, size, &node))
if (!RBTreeSearchNearest(ALLOC.tree, size + alignment, &node))
{
AllocGrow(size);
RBTreeSearchNearest(ALLOC.tree, size, &node);
RBTreeSearchNearest(ALLOC.tree, size + alignment, &node);
}
u64 alloc_size = node->key;
rawptr free_alloc = node->bucket.last->data;
RBTreeDelete(ALLOC.tree, alloc_size, free_alloc);
usize padding = CalcPadding(uintptr(free_alloc), alignment);
uintptr new_addr = uintptr(free_alloc) + size + padding;
RBTreeInsert(ALLOC.tree, alloc_size - size - padding, rawptr(new_addr));
HashTablePushRawptrU64(ALLOC.hash_table, free_alloc, size + padding);
return free_alloc;
}
// TODO: finish allocator
// need an idea
static void Free(rawptr ptr)
{
if (ptr == NULL) return;
@ -199,8 +185,7 @@ static void AllocGrow(usize size)
usize grow_size = size < ALLOC.grow_size ? ALLOC.grow_size : ALLOC.grow_size + size;
MemRealloc(ALLOC.buffer, ALLOC.size, ALLOC.size + grow_size);
AllocInfo *info = CreateAllocInfo(ALLOC.buffer + ALLOC.size); // TODO: check this if things fuck up it could be wrong
RBTreeFindOrInsert(ALLOC.tree, grow_size, info);
RBTreeInsert(ALLOC.tree, grow_size, ALLOC.buffer + ALLOC.size); // TODO: check this if things fuck up it could be wrong
ALLOC.size += grow_size;
ALLOC.free_size += grow_size;
@ -341,7 +326,7 @@ static void FreeListGrow(FLAlloc *alloc, usize alloc_size)
alloc->lists[i]->head = node;
}
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment)
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, usize alignment)
{
if (size == 0) return NULL;
@ -388,7 +373,7 @@ static rawptr FreeListAlloc(FLAlloc *alloc, usize size)
return FreeListAllocAlign(alloc, size, DEFAULT_ALIGNMENT);
}
static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, u32 alignment)
static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, usize alignment)
{
u32 ticket = __atomic_fetch_add(&alloc->ticket, 1, __ATOMIC_SEQ_CST);
while (ticket != alloc->next_ticket);

View File

@ -2,7 +2,8 @@
// ::Allocator::Util::Header::
usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size);
static inline usize CalcPaddingWithHeader(uintptr ptr, uintptr alignment, usize header_size);
static inline usize CalcPadding(uintptr ptr, uintptr alignment);
// ::Allocator::Arena::Header::
@ -22,13 +23,15 @@ typedef struct TempArena
u64 pos;
} TempArena;
static Arena *ArenaInit(rawptr buffer, usize length);
static Arena *ArenaInit(rawptr buffer, usize size);
static Arena *ArenaCreate(usize size);
static Arena *ArenaCreateDebug(usize size, u32 init_line_no);
static Arena *ArenaInitDebug(rawptr buffer, usize size, u32 init_line_no);
static rawptr ArenaAllocAlign(Arena *arena, usize size, usize align);
static rawptr ArenaAlloc(Arena *arena, usize size);
static void ArenaFree(Arena *arena);
static void ArenaFreeZeroed(Arena *arena);
static void DeallocArena(Arena *arena);
static Arena *ArenaInitDebug(rawptr buffer, usize length, u32 init_line_no);
// ::Allocator::GlobalAlloc::Header::
@ -50,9 +53,6 @@ typedef struct Allocator
} Allocator;
static void InitAllocator(usize init_size);
static AllocInfo *CreateAllocInfo(rawptr ptr);
static void AllocInfoAdd(AllocInfo *info, rawptr ptr);
static void AllocInfoRemove(AllocInfo *info, rawptr ptr);
static void DeinitAlloc();
static void AllocGrow(usize size);
static rawptr Alloc(usize size);
@ -98,8 +98,8 @@ static rawptr FLMemAllocZeroed(usize size);
static void FLMemFree(rawptr ptr);
static void _FreeListInit(FreeList **alloc, usize size);
static void FreeListInit(FLAlloc *alloc, usize size);
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, u32 alignment);
static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, u32 alignment);
static rawptr _FreeListAllocAlign(FreeList *alloc, usize size, usize alignment);
static rawptr FreeListAllocAlign(FLAlloc *alloc, usize size, usize alignment);
static rawptr FreeListAlloc(FLAlloc *alloc, usize size);
static void _FreeListFree(FreeList *alloc, rawptr ptr);
static void FreeListFree(FLAlloc *alloc, rawptr ptr);

View File

@ -55,4 +55,5 @@ typedef enum ModelAssetTag_e
MODEL_ASSET_TAG_MAX,
} ModelAssetTag;
static rawptr LoadTextureAsset(TextureAsset asset_id);
static rawptr LoadShaderAsset(ShaderAsset asset_id);

View File

@ -32,7 +32,7 @@ static inline void RBTreePushDataNode(RBDataNode *first, RBDataNode *last, rawpt
RBQueuePush(first, last, data_node);
}
static inline RBNode *RBTreeInitNode(u32 key, rawptr value)
static inline RBNode *RBTreeInitNode(u64 key, rawptr value)
{
RBNode *node = FLMemAllocZeroed(sizeof(RBNode));
node->parent = node->left = node->right = P_RB_NIL;
@ -44,9 +44,9 @@ static inline RBNode *RBTreeInitNode(u32 key, rawptr value)
return node;
}
static void RBTreeInsert(RBTree *tree, u32 key, rawptr value)
static void RBTreeInsert(RBTree *tree, u64 key, rawptr value)
{
RBNode *existing_node = P_RB_NIL;
RBNode *node = P_RB_NIL;
node->left = node->right = tree->nil;
node->color = RB_RED;
@ -66,14 +66,14 @@ static void RBTreeInsert(RBTree *tree, u32 key, rawptr value)
if (curr_node->key == key)
{
RBTreeInitDataNode(curr_node->bucket.first, curr_node->bucket.last, value);
RBTreePushDataNode(curr_node->bucket.first, curr_node->bucket.last, value);
break;
}
else if (curr_node->key < key)
{
if (curr_node->right == tree->nil)
{
RBNode *node = RBTreeInitNode(key, value);
node = RBTreeInitNode(key, value);
node->parent = curr_node;
curr_node->right = node;
break;
@ -87,7 +87,7 @@ static void RBTreeInsert(RBTree *tree, u32 key, rawptr value)
{
if (curr_node->left == tree->nil)
{
RBNode *node = RBTreeInitNode(key, value);
node = RBTreeInitNode(key, value);
node->parent = curr_node;
curr_node->left = node;
break;
@ -100,7 +100,7 @@ static void RBTreeInsert(RBTree *tree, u32 key, rawptr value)
}
}
if (node->parent->color != RB_BLACK && existing_node != P_RB_NIL)
if (node->parent->color != RB_BLACK && node != P_RB_NIL)
RBTreeCorrect(tree, node);
}
@ -147,12 +147,12 @@ static void RBTreeCorrect(RBTree *tree, RBNode *node)
} while ((p = node->parent));
}
static void RBTreeDelete(RBTree *tree, u32 key, rawptr value)
static void RBTreeDelete(RBTree *tree, u64 key, rawptr value)
{
RBNode *node = NULL;
Assert(RBTreeSearch(tree, key, &node), "Unable to find node in RBTreeDelete");
if (node->bucket.first.data != value)
if (node->bucket.first->data != value)
{
Assert(node->bucket.first->next != P_RB_DN_NIL, "RBTreeDelete Failure: unable to find value to delete");
RBDataNode *data_node = node->bucket.first->next;
@ -186,7 +186,7 @@ static void RBTreeDelete(RBTree *tree, u32 key, rawptr value)
ln = ln->left;
node->key = ln->key;
node->data = ln->data;
node->bucket = ln->bucket;
if (node->right == ln)
node->right = tree->nil;
@ -198,13 +198,13 @@ static void RBTreeDelete(RBTree *tree, u32 key, rawptr value)
else if (node->color == RB_BLACK && node->left != tree->nil)
{
node->key = node->left->key;
node->data = node->left->data;
node->bucket = node->left->bucket;
node->left = tree->nil;
}
else if (node->color == RB_BLACK && node->right != tree->nil)
{
node->key = node->right->key;
node->data = node->right->data;
node->bucket = node->right->bucket;
node->right = tree->nil;
}
else if (node->color == RB_RED && node->right == tree->nil && node->left == tree->nil)
@ -286,20 +286,21 @@ static void RBTreeDelete(RBTree *tree, u32 key, rawptr value)
}
}
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node)
static b32 RBTreeSearchNearest(RBTree *tree, u64 key, RBNode **out_node)
{
if (tree->root == tree->nil) return false;
RBNode *node = tree->root;
RBNode *nearest = tree->root;
u32 nearest_diff = UINT32_MAX;
u64 nearest_diff = UINT64_MAX;
while (true)
{
if (node == tree->nil)
break;
u32 diff = Abs(node->key - key);
u64 diff = node->key - key;
diff = Abs(diff);
if (diff == 0)
{
@ -324,7 +325,7 @@ static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **out_node)
return *out_node != tree->nil;
}
static b32 RBTreeSearch(RBTree *tree, u32 key, RBNode **out_node)
static b32 RBTreeSearch(RBTree *tree, u64 key, RBNode **out_node)
{
if (tree->root == tree->nil) return false;
@ -477,30 +478,36 @@ static HashNode *HashTablePush(HashTable *table, u64 hash, KeyValuePair value)
return node;
}
static HashNode *HashTablePushU32(HashTable *table, u64 key, u32 value)
static HashNode *HashTablePushU64U32(HashTable *table, u64 key, u32 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u32 = value });
}
static HashNode *HashTablePushU64(HashTable *table, u64 key, u64 value)
static HashNode *HashTablePushU64U64(HashTable *table, u64 key, u64 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_u64 = value });
}
static HashNode *HashTablePushString8(HashTable *table, u64 key, String8 value)
static HashNode *HashTablePushU64String8(HashTable *table, u64 key, String8 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_string = value });
}
static HashNode *HashTablePushRawptr(HashTable *table, u64 key, rawptr value)
static HashNode *HashTablePushU64Rawptr(HashTable *table, u64 key, rawptr value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_u64 = key, .value_rawptr = value });
}
static HashNode *HashTablePushRawptrU64(HashTable *table, rawptr key, u64 value)
{
u64 hash = HashFromString(String8Struct(&key));
return HashTablePush(table, hash, (KeyValuePair){ .key_rawptr = key, .value_u64 = value });
}
static KeyValuePair *HashTableSearchU64(HashTable *table, u64 key)
{
KeyValuePair *result = NULL;
@ -520,6 +527,25 @@ static KeyValuePair *HashTableSearchU64(HashTable *table, u64 key)
return result;
}
static KeyValuePair *HashTableSearchRawptr(HashTable *table, rawptr key)
{
KeyValuePair *result = NULL;
u64 hash = HashFromString(String8Struct(&key));
u64 index = hash % table->cap;
HashList *list = table->lists + index;
for (HashNode *node = list->first; node != P_HT_NIL; node = node->next)
{
if (node->v.key_rawptr == key)
{
result = &node->v;
break;
}
}
return result;
}
// ::DataStructures::HashTable::Functions::End::

View File

@ -43,7 +43,7 @@ typedef struct RBNode
struct RBNode *child[2];
};
struct RBNode *parent;
u32 key;
u64 key;
RBBucket bucket;
RBNodeColor color;
} RBNode;
@ -55,12 +55,12 @@ typedef struct RBTree
} RBTree;
static void RBTreeInit (RBTree *tree);
static inline RBNode *RBTreeInitNode(u32 key, rawptr value);
static inline RBNode *RBTreeInitNode(u64 key, rawptr value);
static inline void RBTreePushDataNode(RBDataNode *first, RBDataNode *last, rawptr value);
static RBNode *RBTreeFindOrInsert(RBTree *tree, u32 key, rawptr value);
static b32 RBTreeSearchNearest(RBTree *tree, u32 key, RBNode **node);
static b32 RBTreeSearch (RBTree *tree, u32 key, RBNode **node);
static void RBTreeDelete (RBTree *tree, u32 key, rawptr value);
static void RBTreeInsert(RBTree *tree, u64 key, rawptr value);
static b32 RBTreeSearchNearest(RBTree *tree, u64 key, RBNode **node);
static b32 RBTreeSearch (RBTree *tree, u64 key, RBNode **node);
static void RBTreeDelete (RBTree *tree, u64 key, rawptr value);
static void RBTreeLeftRotate (RBTree *tree, RBNode *node);
static void RBTreeRightRotate(RBTree *tree, RBNode *node);
static void RBTreeRotate (RBTree *tree, RBNode *node, RBNodeDir dir);
@ -78,6 +78,7 @@ typedef struct KeyValuePair
union
{
u64 key_u64;
rawptr key_rawptr;
};
union
{
@ -114,9 +115,10 @@ static void HashTableConcatInPlace(HashList *list, HashList *to_concat);
static u64 HashTableHash(String8 str);
static HashNode *HashListPop(HashList *list);
static KeyValuePair *HashTableSearchU64(HashTable *table, u64 key);
static KeyValuePair *HashTableSearchRawptr(HashTable *table, rawptr key);
static HashNode *HashTablePush(HashTable *table, u64 hash, KeyValuePair value);
static HashNode *HashTablePushU32(HashTable *table, u64 key, u32 value);
static HashNode *HashTablePushU64(HashTable *table, u64 key, u64 value);
static HashNode *HashTablePushString8(HashTable *table, u64 key, String8 value);
static HashNode *HashTablePushRawptr(HashTable *table, u64 key, rawptr value);
static HashNode *HashTablePushU64U32(HashTable *table, u64 key, u32 value);
static HashNode *HashTablePushU64U64(HashTable *table, u64 key, u64 value);
static HashNode *HashTablePushU64String8(HashTable *table, u64 key, String8 value);
static HashNode *HashTablePushU64Rawptr(HashTable *table, u64 key, rawptr value);

View File

@ -9,8 +9,8 @@
#include "fastlz/fastlz.c"
#include "platform/platform.c"
#include "ds.c"
#include "util.c"
#include "ds.c"
#include "allocators.c"
#include "renderer.c"
#include "game.c"
@ -58,17 +58,9 @@ int main(int argc, char **argv)
return 0;
#endif
u8 *mem = (u8 *)MemAllocZeroed(MB(64));
Arena *arena = ArenaInitDebug(mem, MB(64), __LINE__);
usize renderer_mem_size = MB(16);
usize game_mem_size = MB(16);
rawptr renderer_mem = ArenaAlloc(arena, renderer_mem_size);
Arena *renderer_arena = ArenaInitDebug(renderer_mem, renderer_mem_size, 2);
rawptr game_mem = ArenaAlloc(arena, game_mem_size);
Arena *game_arena = ArenaInitDebug(game_mem, game_mem_size, 3);
Arena *arena = ArenaCreateDebug(MB(32), __LINE__);
Arena *renderer_arena = ArenaCreateDebug(MB(16), __LINE__);
Arena *game_arena = ArenaCreateDebug(MB(16), __LINE__);
Assert(CreatePlatformWindow(WINDOW_NAME), "Failed to initialize the window");

View File

@ -14,9 +14,9 @@
#include "fastlz/fastlz.h"
#include "shared_types.h"
#include "util.h"
#include "ds.h"
#include "platform/platform.h"
#include "util.h"
#include "allocators.h"
#include "renderer.h"
#include "game.h"

View File

@ -2,7 +2,6 @@
void RunTests()
{
GlobalFreeListInit(MB(32));
TestFreeListAlloc();
TestHashTable();
}
@ -60,7 +59,7 @@ void TestHashTable()
for (u64 i = 1; i < 2000; i++)
{
HashTablePushU64(&table, i*3, i);
HashTablePushU64U64(&table, i*3, i);
}
for (u64 i = 1; i < 2000; i++)

View File

@ -169,6 +169,7 @@ void MemCpy(rawptr dst, rawptr src, usize size)
DefMathImpl(Min);
DefMathImpl(Max);
DefMathImpl(Clamp);
DefMathImpl(Abs);
// ::Util::Math::Functions::End::