diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-19 10:32:17 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-19 10:32:17 -0400 |
| commit | 018e8aa592f6b39ebc52ff92dde0631194527859 (patch) | |
| tree | 69efc6a2e29449fe57346ce09e4951fb46783764 /pkmem.h | |
| parent | cc60670e234e9d7aedb4772a0312fbd1fa20da44 (diff) | |
pkmem: attempt to handle debug race conditions
Diffstat (limited to 'pkmem.h')
| -rw-r--r-- | pkmem.h | 45 |
1 files changed, 33 insertions, 12 deletions
@@ -163,13 +163,15 @@ static struct pk_membucket pk_buckets[PK_MAX_BUCKET_COUNT]; static size_t pk_bucket_head = 0; #ifdef PK_MEMORY_DEBUGGER +#include <stdatomic.h> struct pk_dbg_memblock { struct pk_memblock blk; struct pk_membucket *bkt; }; static struct pk_dbg_memblock debug_all_allocs[1024 * 1024]; -static size_t debug_alloc_head = 0; -static bool has_init_debug = false; +static atomic_size_t debug_alloc_head = 0; +static atomic_bool has_init_debug = false; +static mtx_t debug_alloc_mtx; #endif bool @@ -182,8 +184,13 @@ pk_memory_is_in_bucket(const void* ptr, const struct pk_membucket* bkt) void pk_memory_debug_print() { + size_t i, d; +#ifdef PK_MEMORY_DEBUGGER + size_t count = 0; + size_t dah = debug_alloc_head; +#endif PK_LOGV_INF("Memory Manager printout:\nBucket count: %li\n", pk_bucket_head); - for (size_t i = 0; i < pk_bucket_head; ++i) { + for (i = 0; i < pk_bucket_head; ++i) { PK_LOGV_INF("- bucket #%li\n", i); PK_LOGV_INF("\tdescription: %s\n", pk_buckets[i].description); PK_LOGV_INF("\tsize: %li\n", pk_buckets[i].size); @@ -196,14 +203,13 @@ pk_memory_debug_print() PK_LOGV_INF("\tptr: %p\n", (void *)pk_buckets[i].ptr); PK_LOGV_INF("\ttransient: %i\n", pk_buckets[i].transient); #ifdef PK_MEMORY_DEBUGGER - uint64_t count = 0; - for (size_t d = 0; d < debug_alloc_head; ++d) { + for (d = 0; d < dah; ++d) { if (debug_all_allocs[d].bkt == &pk_buckets[d] && debug_all_allocs[d].blk.size > 0) { count += 1; } } PK_LOGV_INF("\tdebug alloc count: %lu\n", count); - PK_LOGV_INF("\tdebug alloc last: %lu\n", debug_alloc_head); + PK_LOGV_INF("\tdebug alloc last: %lu\n", dah); #endif } } @@ -229,6 +235,11 @@ pk_memory_teardown_all() pk_bucket_destroy(&pk_buckets[i - 1]); } pk_bucket_head = 0; +#ifdef PK_MEMORY_DEBUGGER + debug_alloc_head = 0; + mtx_destroy(&debug_alloc_mtx); + has_init_debug = false; +#endif } static int64_t @@ -238,6 +249,7 @@ pk_bucket_create_inner(int64_t sz, bool transient, const char* description) #ifdef PK_MEMORY_DEBUGGER if (has_init_debug == false) { has_init_debug = true; + mtx_init(&debug_alloc_mtx, mtx_plain); memset(debug_all_allocs, 0, sizeof(struct pk_dbg_memblock) * 1024 * 1024); } #endif @@ -283,6 +295,9 @@ void pk_bucket_destroy(struct pk_membucket* bkt) { size_t i; +#ifdef PK_MEMORY_DEBUGGER + size_t dah; +#endif for (i = 0; i < pk_bucket_head; ++i) { if (&pk_buckets[i] == bkt) { if (pk_bucket_head == i + 1) @@ -302,9 +317,8 @@ pk_bucket_destroy(struct pk_membucket* bkt) bkt->transient = false; mtx_destroy(&bkt->mtx); #ifdef PK_MEMORY_DEBUGGER - size_t ii; - for (ii = debug_alloc_head+1; ii > 0; --ii) { - i = ii-1; + dah = debug_alloc_head; + for (i = dah; i > 0; --i) { if (debug_all_allocs[i].bkt == bkt) { debug_all_allocs[i].blk.data = NULL; debug_all_allocs[i].blk.size = 0u; @@ -317,7 +331,7 @@ void pk_bucket_reset(struct pk_membucket* bkt) { #ifdef PK_MEMORY_DEBUGGER - int64_t i; + size_t i; #endif if (bkt->transient != true) { PK_LOG_ERR("WARNING: pk_bucket_reset called on non-transient pk_membucket\n"); @@ -329,7 +343,7 @@ pk_bucket_reset(struct pk_membucket* bkt) bkt->blocks->data = bkt->ptr; bkt->blocks->size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount); #ifdef PK_MEMORY_DEBUGGER - for (i = debug_alloc_head; i > -1; --i) { + for (i = debug_alloc_head; i > 0; --i) { if (debug_all_allocs[i].bkt == bkt) { debug_all_allocs[i].blk.data = NULL; debug_all_allocs[i].blk.size = 0u; @@ -421,9 +435,10 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt) data = block->data + misalignment; #ifdef PK_MEMORY_DEBUGGER bool handled = bkt->transient; + struct pk_dbg_memblock* mb = nullptr; if (handled == false) { for (i = 0; i < debug_alloc_head; ++i) { - struct pk_dbg_memblock* mb = &debug_all_allocs[i]; + mb = &debug_all_allocs[i]; if (mb->bkt != NULL) continue; assert((mb->blk.size == 0 || (void*)(mb->blk.data) != data) && "mem address alloc'd twice!"); if (mb->blk.size == 0) { @@ -436,7 +451,9 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt) } } if (handled == false) { + mtx_lock(&debug_alloc_mtx); i = debug_alloc_head++; + mtx_unlock(&debug_alloc_mtx); debug_all_allocs[i].blk.data = (char*)data; debug_all_allocs[i].blk.size = sz; debug_all_allocs[i].bkt = bkt; @@ -463,6 +480,8 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt) prevBlock->size += misalignment; block->data += misalignment + sz; block->size = 0; // if you make it here, afterSize has already been handled + } else { + assert(true == false && "this shouldn't happen"); } bkt->allocs++; assert(data >= bkt->raw && "allocated data is before bucket data"); @@ -529,6 +548,7 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt) #ifdef PK_MEMORY_DEBUGGER size_t ii; bool found = bkt->transient; + mtx_lock(&debug_alloc_mtx); if (found == false) { for (ii = debug_alloc_head; ii > 0; --ii) { i = ii-1; @@ -547,6 +567,7 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt) } } } + mtx_unlock(&debug_alloc_mtx); assert(found && "[pkmem.h] double free or invalid ptr"); #endif bkt->allocs--; |
