summaryrefslogtreecommitdiff
path: root/pkmem.h
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-05-19 10:32:17 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-05-19 10:32:17 -0400
commit018e8aa592f6b39ebc52ff92dde0631194527859 (patch)
tree69efc6a2e29449fe57346ce09e4951fb46783764 /pkmem.h
parentcc60670e234e9d7aedb4772a0312fbd1fa20da44 (diff)
pkmem: attempt to handle debug race conditions
Diffstat (limited to 'pkmem.h')
-rw-r--r--pkmem.h45
1 files changed, 33 insertions, 12 deletions
diff --git a/pkmem.h b/pkmem.h
index e8e5714..a83aea5 100644
--- a/pkmem.h
+++ b/pkmem.h
@@ -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--;