Files
raddebugger/src/demon/demon_common.c
T
2024-01-10 19:57:50 -08:00

271 lines
6.5 KiB
C

// Copyright (c) 2024 Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
// NOTE(allen): State Safety Helper
internal B32
demon_access_begin(void){
B32 result = 0;
if (demon_primary_thread){
Assert(demon_run_state);
result = 1;
}
else{
os_mutex_take(demon_state_mutex);
if (demon_run_state){
os_mutex_drop(demon_state_mutex);
}
else{
result = 1;
}
}
return(result);
}
internal void
demon_access_end(void){
if (!demon_primary_thread){
os_mutex_drop(demon_state_mutex);
}
}
////////////////////////////////
// NOTE(allen): Entity System
internal void
demon_common_init(void){
// access control mechanism
demon_state_mutex = os_mutex_alloc();
// time
demon_time = 1;
// setup arena
demon_ent_arena = arena_alloc();
// setup map
demon_ent_map = push_array(demon_ent_arena, DEMON_Map, 1);
demon_ent_map->bucket_count = 4093;
demon_ent_map->buckets = push_array(demon_ent_arena, DEMON_MapSlot*, demon_ent_map->bucket_count);
// setup entity memory
U64 reserve_size_unaligned = (DEMON_ENTITY_CAP)*sizeof(DEMON_Entity);
U64 reserve_size = AlignPow2(reserve_size_unaligned, DEMON_ENTITY_CMT_SIZE);
demon_ent_cmt = demon_ent_pos = demon_ent_base = (DEMON_Entity*)os_reserve(reserve_size);
demon_ent_opl = demon_ent_base + (reserve_size/sizeof(DEMON_Entity));
Assert(demon_ent_base != 0);
// setup root
demon_ent_root = demon_ent_alloc();
demon_ent_root->kind = DEMON_EntityKind_Root;
}
internal DEMON_Entity*
demon_ent_alloc(void){
DEMON_Entity *result = demon_ent_free;
if (result != 0){
SLLStackPop(demon_ent_free);
}
else{
if (demon_ent_pos < demon_ent_opl){
if (ensure_commit(&demon_ent_cmt, demon_ent_pos + 1, DEMON_ENTITY_CMT_SIZE)){
result = demon_ent_pos;
demon_ent_pos += 1;
}
}
}
if (result != 0){
U32 gen = result->gen;
MemoryZeroStruct(result);
result->gen = gen;
}
return(result);
}
//- handle <-> entity pointer
internal DEMON_Entity*
demon_ent_ptr_from_handle(DEMON_Handle handle){
Assert(demon_ent_base != 0);
DEMON_Entity *result = 0;
U32 index = (U32)(handle & 0xFFFFFFFF);
U64 count = (U64)(demon_ent_pos - demon_ent_base);
if (0 < index && index < count){
DEMON_Entity *entity = demon_ent_base + index;
U32 gen = (U32)(handle >> 32);
if (gen == entity->gen){
result = entity;
}
}
return(result);
}
internal DEMON_Handle
demon_ent_handle_from_ptr(DEMON_Entity *entity){
Assert(demon_ent_base != 0);
DEMON_Handle result = {0};
if (demon_ent_base < entity && entity < demon_ent_pos){
U32 index = (U32)(entity - demon_ent_base);
U64 gen = entity->gen;
result = (gen << 32) | index;
}
return(result);
}
//- high level entity alloc,init,release
internal DEMON_Entity*
demon_ent_new(DEMON_Entity *parent, DEMON_EntityKind kind, U64 id){
Assert(demon_ent_base != 0);
DEMON_Entity *result = demon_ent_alloc();
if (result != 0){
result->kind = kind;
result->id = id;
result->arch = parent->arch;
result->parent = parent;
DLLPushBack(parent->first, parent->last, result);
demon_ent_map_save(kind, id, result);
}
return(result);
}
internal void
demon_ent_release_single(DEMON_Entity *entity){
switch (entity->kind){
case DEMON_EntityKind_Process: demon_proc_count -= 1; break;
case DEMON_EntityKind_Thread: demon_thread_count -= 1; break;
case DEMON_EntityKind_Module: demon_module_count -= 1; break;
}
demon_accel_free(entity);
demon_os_entity_cleanup(entity);
DEMON_MapRef ref = demon_ent_map_find(entity->kind, entity->id);
demon_ent_map_erase(ref);
entity->gen += 1;
}
internal void
demon_ent_release_children(DEMON_Entity *root){
Assert(demon_ent_base != 0);
if (root->first != 0){
for (DEMON_Entity *node = root->first;
node != 0;
node = node->next){
demon_ent_release_children(node);
demon_ent_release_single(node);
}
root->last->next = demon_ent_free;
demon_ent_free = root->first;
root->first = 0;
root->last = 0;
}
}
internal void
demon_ent_release_root_and_children(DEMON_Entity *root){
Assert(demon_ent_base != 0);
Assert(root->parent != 0);
// release children
demon_ent_release_children(root);
// release root
DEMON_Entity *parent = root->parent;
demon_ent_release_single(root);
DLLRemove(parent->first, parent->last, root);
SLLStackPush(demon_ent_free, root);
}
//- entity map
internal U64
demon_ent_map_hash(U16 kind, U64 id){
U64 result = ((U64)kind << 32) ^ id;
return(result);
}
internal void
demon_ent_map_save(U16 kind, U64 id, DEMON_Entity *entity){
Assert(demon_ent_base != 0);
DEMON_Map *map = demon_ent_map;
// allocate a new slot
DEMON_MapSlot *slot = map->free_slots;
if (slot != 0){
SLLStackPop(map->free_slots);
}
else{
slot = push_array_no_zero(demon_ent_arena, DEMON_MapSlot, 1);
}
// fill slot
slot->kind = kind;
slot->id = id;
slot->entity = entity;
// insert into bucket
U64 hash = demon_ent_map_hash(kind, id);
U64 bucket_index = hash%map->bucket_count;
SLLStackPush(map->buckets[bucket_index], slot);
}
internal DEMON_MapRef
demon_ent_map_find(U16 kind, U64 id){
Assert(demon_ent_base != 0);
DEMON_Map *map = demon_ent_map;
// scan bucket
DEMON_MapRef result = {0};
U64 hash = demon_ent_map_hash(kind, id);
U64 bucket_index = hash%map->bucket_count;
for (DEMON_MapSlot **ptr = &map->buckets[bucket_index], *slot = 0;
*ptr != 0;
ptr = &slot->next){
slot = *ptr;
if (slot->kind == kind && slot->id == id){
result.slot = slot;
result.ptr_to_slot = ptr;
break;
}
}
return(result);
}
internal DEMON_Entity*
demon_ent_map_entity_from_id(U16 kind, U64 id){
DEMON_Entity *result = 0;
DEMON_MapRef ref = demon_ent_map_find(kind, id);
if (ref.slot != 0){
result = ref.slot->entity;
}
return(result);
}
internal void
demon_ent_map_erase(DEMON_MapRef ref){
Assert(demon_ent_base != 0);
DEMON_Map *map = demon_ent_map;
// move slot to free list
if (ref.slot != 0){
*ref.ptr_to_slot = ref.slot->next;
SLLStackPush(map->free_slots, ref.slot);
}
}
////////////////////////////////
// NOTE(allen): Event Helpers
internal DEMON_Event*
demon_push_event(Arena *arena, DEMON_EventList *list, DEMON_EventKind kind){
DEMON_EventNode *n = push_array(arena, DEMON_EventNode, 1);
DEMON_Event *result = &n->v;
SLLQueuePush(list->first, list->last, n);
list->count += 1;
result->kind = kind;
return(result);
}