From 687cfd78500882b8451148bfeb513a70e83d9431 Mon Sep 17 00:00:00 2001 From: Alex Baines Date: Sun, 16 Feb 2020 22:47:42 +0000 Subject: [PATCH] linux memory tracking --- platform_linux/linux_4ed.cpp | 16 ++++++ platform_linux/linux_4ed_functions.cpp | 69 ++++++++++++++++++++++---- 2 files changed, 76 insertions(+), 9 deletions(-) diff --git a/platform_linux/linux_4ed.cpp b/platform_linux/linux_4ed.cpp index 1405ac18..66444b7f 100644 --- a/platform_linux/linux_4ed.cpp +++ b/platform_linux/linux_4ed.cpp @@ -140,6 +140,13 @@ struct Linux_Input_Chunk { Linux_Input_Chunk_Persistent pers; }; +struct Linux_Memory_Tracker_Node { + Linux_Memory_Tracker_Node* prev; + Linux_Memory_Tracker_Node* next; + String_Const_u8 location; + u64 size; +}; + struct Linux_Vars { Thread_Context tctx; Arena *frame_arena; @@ -173,6 +180,10 @@ struct Linux_Vars { Node timer_objects; System_Mutex global_frame_mutex; + pthread_mutex_t memory_tracker_mutex; + Linux_Memory_Tracker_Node* memory_tracker_head; + Linux_Memory_Tracker_Node* memory_tracker_tail; + int memory_tracker_count; Arena* clipboard_arena; String_Const_u8 clipboard_contents; @@ -1552,6 +1563,11 @@ linux_epoll_process(struct epoll_event* events, int num_events) { int main(int argc, char **argv){ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&linuxvars.memory_tracker_mutex, &attr); + // NOTE(allen): context setup { Base_Allocator* alloc = get_base_allocator_system(); diff --git a/platform_linux/linux_4ed_functions.cpp b/platform_linux/linux_4ed_functions.cpp index f6044e78..2cebb4d0 100644 --- a/platform_linux/linux_4ed_functions.cpp +++ b/platform_linux/linux_4ed_functions.cpp @@ -616,20 +616,42 @@ system_condition_variable_signal(System_Condition_Variable cv){ internal void system_condition_variable_free(System_Condition_Variable cv){ Linux_Object* object = *(Linux_Object**)&cv; - //LINUX_FN_DEBUG("%p", object); + LINUX_FN_DEBUG("%p", &object->condition_variable); Assert(object->kind == LinuxObjectKind_ConditionVariable); pthread_cond_destroy(&object->condition_variable); linux_free_object(object); } +#define MEMORY_PREFIX_SIZE 64 + internal void* system_memory_allocate(u64 size, String_Const_u8 location){ - void* result = mmap( - NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - // TODO(andrew): Allocation tracking? - //LINUX_FN_DEBUG("%" PRIu64 ", %.*s %p", size, (int)location.size, location.str, result); - return result; + static_assert(MEMORY_PREFIX_SIZE >= sizeof(Memory_Annotation_Node)); + u64 adjusted_size = size + MEMORY_PREFIX_SIZE; + + Assert(adjusted_size > size); + + const int prot = PROT_READ | PROT_WRITE; + const int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + void* result = mmap(NULL, adjusted_size, prot, flags, -1, 0); + + if(result == MAP_FAILED) { + perror("mmap"); + return NULL; + } + + Linux_Memory_Tracker_Node* node = (Linux_Memory_Tracker_Node*)result; + node->location = location; + node->size = size; + + pthread_mutex_lock(&linuxvars.memory_tracker_mutex); + zdll_push_back(linuxvars.memory_tracker_head, linuxvars.memory_tracker_tail, node); + linuxvars.memory_tracker_count++; + pthread_mutex_unlock(&linuxvars.memory_tracker_mutex); + + return (u8*)result + MEMORY_PREFIX_SIZE; } internal b32 @@ -645,14 +667,43 @@ system_memory_set_protection(void* ptr, u64 size, u32 flags){ internal void system_memory_free(void* ptr, u64 size){ - //LINUX_FN_DEBUG("%p / %ld", ptr, size); - munmap(ptr, size); + u64 adjusted_size = size + MEMORY_PREFIX_SIZE; + Linux_Memory_Tracker_Node* node = (Linux_Memory_Tracker_Node*)((u8*)ptr - MEMORY_PREFIX_SIZE); + + pthread_mutex_lock(&linuxvars.memory_tracker_mutex); + zdll_remove(linuxvars.memory_tracker_head, linuxvars.memory_tracker_tail, node); + linuxvars.memory_tracker_count--; + pthread_mutex_unlock(&linuxvars.memory_tracker_mutex); + + if(munmap(node, adjusted_size) == -1) { + perror("munmap"); + } } internal Memory_Annotation system_memory_annotation(Arena* arena){ LINUX_FN_DEBUG(); - // TODO; + + Memory_Annotation result; + Memory_Annotation_Node** ptr = &result.first; + + pthread_mutex_lock(&linuxvars.memory_tracker_mutex); + + for(Linux_Memory_Tracker_Node* node = linuxvars.memory_tracker_head; node; node = node->next) { + *ptr = push_array(arena, Memory_Annotation_Node, 1); + (*ptr)->location = node->location; + (*ptr)->size = node->size; + (*ptr)->address = (u8*)node + MEMORY_PREFIX_SIZE; + ptr = &(*ptr)->next; + result.count++; + } + + pthread_mutex_unlock(&linuxvars.memory_tracker_mutex); + + *ptr = NULL; + result.last = CastFromMember(Memory_Annotation_Node, next, ptr); + + return result; } internal void