diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-06-04 14:46:21 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-06-04 14:50:26 -0400 |
| commit | 08d54867148420da3bd7ce531beaeb34de975fcb (patch) | |
| tree | 0c0f0ef8f8629289472b7d86106d47aa4fea481d | |
| parent | a9a0920f431c76f31157edd42c6d055b673ed12f (diff) | |
pkmem.h: chkpt: major refactor for ad-hoc buckets
| -rw-r--r-- | pkmem-types.h | 6 | ||||
| -rw-r--r-- | pkmem.h | 732 | ||||
| -rw-r--r-- | test/pkmem.c | 5 | ||||
| -rw-r--r-- | test/pkmem.cpp | 473 |
4 files changed, 604 insertions, 612 deletions
diff --git a/pkmem-types.h b/pkmem-types.h index 7f7a2ac..2bf7752 100644 --- a/pkmem-types.h +++ b/pkmem-types.h @@ -54,6 +54,12 @@ pk_handle_validate_constexpr() struct pk_membucket; +enum PK_MEMBUCKET_FLAGS : uint64_t { + PK_MEMBUCKET_FLAG_NONE = (0), + PK_MEMBUCKET_FLAG_TRANSIENT = (1 << 01l), + PK_MEMBUCKET_FLAG_ALL = (0xFFFFFFFFFFFFFFFF), +}; + #endif /* PK_MEM_TYPES_H */ #ifdef PK_IMPL_MEM_TYPES @@ -16,12 +16,13 @@ # define PK_MAXIMUM_ALIGNMENT 64 #endif -struct pk_membucket* pk_bucket_create(const char* description, int64_t sz, bool transient); +size_t pk_mem_calculate_bkt_size(size_t sz, size_t reserved_block_count); +struct pk_membucket* pk_bucket_create(const char* description, int64_t sz, enum PK_MEMBUCKET_FLAGS flags); void pk_bucket_destroy(struct pk_membucket* bkt); void pk_bucket_reset(struct pk_membucket* bkt); +void pk_bucket_set_client_bucket(struct pk_membucket *bkt); -void pk_memory_debug_print(); -void pk_memory_flush(); +void pk_memory_debug_print(struct pk_membucket *bkt); void pk_memory_teardown_all(); bool pk_memory_is_in_bucket(const void* ptr, const struct pk_membucket* bkt); @@ -41,9 +42,9 @@ static inline void stupid_header_warnings_cpp() { (void)std::is_const<void>::val template <typename T> inline T* -pk_new(pk_membucket* bucket = nullptr) +pk_new(pk_membucket* bucket = NULL) { - void* ptr = nullptr; + void* ptr = NULL; if (bucket) { ptr = pk_new_bkt(sizeof(T), alignof(T), bucket); } else { @@ -57,15 +58,15 @@ pk_new(pk_membucket* bucket = nullptr) template <typename T> inline T* -pk_new(long count, pk_membucket* bucket = nullptr) +pk_new(long count, pk_membucket* bucket = NULL) { - char* ptr = nullptr; + char* ptr = NULL; if (bucket) { ptr = static_cast<char*>(pk_new_bkt(sizeof(T) * count, alignof(T), bucket)); } else { ptr = static_cast<char*>(pk_new_base(sizeof(T) * count, alignof(T))); } - if (ptr == nullptr) return nullptr; + if (ptr == NULL) return NULL; if IS_CONSTRUCTIBLE(T) { for (long i = 0; i < count; ++i) { new (ptr + (i * sizeof(T))) T{}; @@ -76,7 +77,7 @@ pk_new(long count, pk_membucket* bucket = nullptr) template <typename T> inline void -pk_delete(const T* ptr, pk_membucket* bucket = nullptr) +pk_delete(const T* ptr, pk_membucket* bucket = NULL) { if IS_DESTRUCTIBLE(T) { reinterpret_cast<const T*>(ptr)->~T(); @@ -90,7 +91,7 @@ pk_delete(const T* ptr, pk_membucket* bucket = nullptr) template <typename T> inline void -pk_delete(const T* ptr, long count, pk_membucket* bucket = nullptr) +pk_delete(const T* ptr, long count, pk_membucket* bucket = NULL) { if IS_DESTRUCTIBLE(T) { for (long i = 0; i < count; ++i) { @@ -118,311 +119,290 @@ pk_delete(const T* ptr, long count, pk_membucket* bucket = nullptr) static inline void pkmem_stupid_header_warnings() { (void)stdout; } #if defined(PK_MEMORY_DEBUGGER) -/* - * Note that certain aspects of this expect that you only have one non-transient bucket. - * If you need to track multiple non-transient buckets, these sections will need a refactor. - */ #endif -#ifndef PK_MAX_BUCKET_COUNT -# define PK_MAX_BUCKET_COUNT 8 -#endif +#define EXPECTED_PK_MEMBLOCK_SIZE 128 + +#define pk_memblock_blocks_idx(bkt, idx) ((bkt->block_capacity-1)-(idx)) +#define pk_bkt_data(bkt) ((char*)bkt + EXPECTED_PK_MEMBLOCK_SIZE) +#define pk_bkt_head(bkt) ((&bkt->data[0]) + bkt->head) +#define pk_bkt_data_sz(bkt) (size_t)((char*)&bkt->blocks[0] - &bkt->data[0]) struct pk_memblock { - char* data; + union { + char* data; + void* ptr; + }; size_t size; }; struct pk_membucket { - // the total size of the bucket, `blocks+ptr` + // 00 + mtx_t mtx; + // 40 + // the total size of the bucket, struct+data size_t size; - // the current head of the bucket: byte offset from `ptr`. + // 48 + // the current head of the bucket: byte offset from `data`. // All currently alloc'd data is before this offset size_t head; - // amount of lost bytes in this membucket, hopefully zero - size_t lostBytes; + // 56 + uint32_t block_capacity; + // 60 + uint32_t block_head_l; + // 64 + // this should ALWAYS point to the last block containing unalloced space in bkt + uint32_t block_head_r; + // 68 // the number of active allocations from this bucket - size_t allocs; - // the index of the last empty block. - // Should always point to `pk_memblock{ .data = ptr+head, .size=size-head }` - size_t lastEmptyBlockIndex; - // number of pk_memblocks in the `*blocks` array - size_t maxBlockCount; - // ptr to an array of pk_memblock to track ALL free space between ptr and ptr+sz - struct pk_memblock* blocks; + // -should correlate to blocks that have a sz > 0 + uint32_t alloc_count; + // 72 + struct pk_memblock *blocks; + // 80 + enum PK_MEMBUCKET_FLAGS flags; + // 88 + const char *description; + // 96 +#ifdef PK_MEMORY_DEBUGGER + uint32_t debug_bkt_index; + // 100 + uint32_t debug_head_l; + // 104 + uint32_t debug_head_r; + // 108 + char padding[4+(8*1)]; + // 120 + size_t debug_block_capacity; +#else + char padding[8*4]; +#endif + // 128 // starting point for alloc'd data - union { - char* ptr; - void* raw; - }; - const char* description; - mtx_t mtx; - bool transient; + // data[] is illegal in c++ (though it works in gcc/clang, but so does this) + char data[1]; }; -static struct pk_membucket pk_buckets[PK_MAX_BUCKET_COUNT]; -static size_t pk_bucket_head = 0; +static struct pk_membucket *client_bucket = NULL; #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 atomic_size_t debug_alloc_head_l = 0; -static atomic_size_t debug_alloc_head_r = 0; -static atomic_bool has_init_debug = false; -static mtx_t debug_alloc_mtx; +static struct pk_memblock *debug_allocs[16]; +static size_t debug_alloc_head = 0; +static mtx_t debug_mtx; #endif +size_t +pk_mem_calculate_bkt_size(size_t sz, size_t reserved_block_count) +{ + size_t base_size = EXPECTED_PK_MEMBLOCK_SIZE + sz + (sizeof(struct pk_memblock) * reserved_block_count); + // This trick ensures that our array of pk_memblocks at the end is mem-aligned. + // We do, however, still have to do the math when setting the ptr. + // Why? the user may have strict memory requirements and didn't call this function. + return base_size + (64 - (base_size % 64)); +} + bool pk_memory_is_in_bucket(const void* ptr, const struct pk_membucket* bkt) { - if (ptr >= bkt->raw && (const char*)ptr < bkt->ptr + bkt->size) return true; - return false; + return (ptr >= (void*)bkt && ptr < (void*)pk_bkt_head(bkt)); } void -pk_memory_debug_print() +pk_memory_debug_print(struct pk_membucket *bkt) { - size_t i; -#ifdef PK_MEMORY_DEBUGGER - size_t d; - size_t count = 0; - size_t dahl = debug_alloc_head_l; - size_t dahr = debug_alloc_head_r; -#endif - PK_LOGV_INF("Memory Manager printout:\nBucket count: %li\n", pk_bucket_head); - 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); - PK_LOGV_INF("\thead: %li\n", pk_buckets[i].head); - PK_LOGV_INF("\tlostBytes: %li\n", pk_buckets[i].lostBytes); - PK_LOGV_INF("\tallocs: %li\n", pk_buckets[i].allocs); - PK_LOGV_INF("\tlastEmptyBlockIndex: %li\n", pk_buckets[i].lastEmptyBlockIndex); - PK_LOGV_INF("\tmaxBlockCount: %li\n", pk_buckets[i].maxBlockCount); - PK_LOGV_INF("\tblocks: %p\n", (void *)pk_buckets[i].blocks); - PK_LOGV_INF("\tptr: %p\n", (void *)pk_buckets[i].ptr); - PK_LOGV_INF("\ttransient: %i\n", pk_buckets[i].transient); + PK_LOG_INF("pk_membucket details:\n"); + PK_LOGV_INF("\tbkt: %p\n", (void *)bkt); + PK_LOGV_INF("\tdescription: %s\n", bkt->description); + PK_LOGV_INF("\tsize: %lu\n", bkt->size); + PK_LOGV_INF("\thead: %lu\n", bkt->head); + PK_LOGV_INF("\tallocs: %u\n", bkt->alloc_count); + PK_LOGV_INF("\tblock head_l: %u\n", bkt->block_head_l); + PK_LOGV_INF("\tblock head_r: %u\n", bkt->block_head_r); + PK_LOGV_INF("\tflags: %lu\n", bkt->flags); #ifdef PK_MEMORY_DEBUGGER - for (d = 0; d < dahr; ++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 head_l: %lu\n", dahl); - PK_LOGV_INF("\tdebug alloc head_r: %lu\n", dahr); + PK_LOGV_INF("\tdebug index: %u\n", bkt->debug_bkt_index); + PK_LOGV_INF("\tdebug alloc head_l: %u\n", bkt->debug_head_l); + PK_LOGV_INF("\tdebug alloc head_r: %u\n", bkt->debug_head_r); + PK_LOGV_INF("\tdebug cappacity: %lu\n", bkt->debug_block_capacity); #endif - } -} - -void -pk_memory_flush() -{ - for (long i = pk_bucket_head - 1; i > -1; --i) { - if (pk_buckets[i].head != 0) break; - if (pk_buckets[i].transient == true) break; - pk_bucket_head--; - if (pk_buckets[i].raw == CAFE_BABE(void)) continue; - pk_bucket_destroy(&pk_buckets[i]); - } } void pk_memory_teardown_all() { - for (int64_t i = pk_bucket_head; i > 0; --i) { - if (pk_buckets[i - 1].ptr == nullptr) continue; - if (pk_buckets[i - 1].ptr == CAFE_BABE(char)) continue; - pk_bucket_destroy(&pk_buckets[i - 1]); - } - pk_bucket_head = 0; + client_bucket = NULL; #ifdef PK_MEMORY_DEBUGGER - debug_alloc_head_l = 0; - debug_alloc_head_r = 0; - mtx_destroy(&debug_alloc_mtx); - has_init_debug = false; + mtx_lock(&debug_mtx); + for (size_t i = 0; i < debug_alloc_head; ++i) { + if (debug_allocs[i] != NULL) { + free(debug_allocs[i]); + } + debug_allocs[i] = NULL; + } + debug_alloc_head = 0; + mtx_unlock(&debug_mtx); #endif } -static int64_t -pk_bucket_create_inner(int64_t sz, bool transient, const char* description) +struct pk_membucket* +pk_bucket_create(const char* description, int64_t sz, enum PK_MEMBUCKET_FLAGS flags) { - if (pk_bucket_head >= PK_MAX_BUCKET_COUNT) return -1; -#ifdef PK_MEMORY_DEBUGGER - if (has_init_debug == false) { - has_init_debug = true; - mtx_init(&debug_alloc_mtx, mtx_plain); - } -#endif - int64_t blockCount = sz * 0.01; - struct pk_membucket* bkt = &pk_buckets[pk_bucket_head]; + // 512 example: + // [000-127] pk_membucket + // [128-191] 64 bytes of data LOL + // [192-511] 20 pk_memblocks (20 is worst-case, start 16, 4 per 64 bytes) + assert(sz >= 512 && "[pkmem.h] bucket too small to track allocation data"); + struct pk_membucket* bkt = (struct pk_membucket*)aligned_alloc(64, sz); + if (bkt == NULL) return NULL; + mtx_init(&bkt->mtx, mtx_plain); bkt->size = sz; bkt->head = 0; - bkt->lostBytes = 0; - bkt->allocs = 0; - bkt->lastEmptyBlockIndex = 0; - bkt->maxBlockCount = blockCount < 10 ? 10 : blockCount; - bkt->blocks = (struct pk_memblock*)malloc(sz); - mtx_init(&bkt->mtx, mtx_plain); - assert(bkt->blocks != nullptr && "failed to allocate memory"); - bkt->ptr = ((char*)(bkt->blocks)) + (sizeof(struct pk_memblock) * bkt->maxBlockCount); - size_t misalignment = (size_t)(bkt->ptr) % PK_MAXIMUM_ALIGNMENT; - if (misalignment != 0) { - size_t moreBlocks = misalignment / sizeof(struct pk_memblock); - bkt->maxBlockCount += moreBlocks; - bkt->ptr += (PK_MAXIMUM_ALIGNMENT - misalignment); - } + bkt->block_capacity = 16; + bkt->block_head_l = 0; + bkt->block_head_r = 0; + bkt->alloc_count = 0; + bkt->flags = flags; bkt->description = description; - bkt->transient = transient; - struct pk_memblock* memBlock = (struct pk_memblock*)(bkt->blocks); - memBlock->data = bkt->ptr; - memBlock->size = sz - (sizeof(struct pk_memblock) * bkt->maxBlockCount); - return pk_bucket_head++; -} + char* blocks_addr = (char*)bkt + sz - (sizeof(struct pk_memblock) * bkt->block_capacity); + blocks_addr -= (size_t)blocks_addr % 64; + bkt->blocks = (struct pk_memblock*)blocks_addr; + bkt->block_capacity = (size_t)(((char*)bkt + sz) - blocks_addr) / sizeof(struct pk_memblock); -struct pk_membucket* -pk_bucket_create(const char* description, int64_t sz, bool transient) -{ - int64_t bkt_index = pk_bucket_create_inner(sz, transient, description); - // TODO some of of error handling - if (bkt_index < 0) { return nullptr; } - return &pk_buckets[bkt_index]; + bkt->blocks[pk_memblock_blocks_idx(bkt,0)].size = pk_bkt_data_sz(bkt); + bkt->blocks[pk_memblock_blocks_idx(bkt,0)].ptr = pk_bkt_data(bkt); + +#ifdef PK_MEMORY_DEBUGGER + mtx_lock(&debug_mtx); + bkt->debug_bkt_index = debug_alloc_head++; + mtx_unlock(&debug_mtx); + bkt->debug_head_l = 0; + bkt->debug_head_r = 0; + bkt->debug_block_capacity = 128; + debug_allocs[bkt->debug_bkt_index] = (struct pk_memblock*)aligned_alloc(alignof(struct pk_memblock), sizeof(struct pk_memblock) * 128); +#endif + + return bkt; } void pk_bucket_destroy(struct pk_membucket* bkt) { - size_t i; - for (i = 0; i < pk_bucket_head; ++i) { - if (&pk_buckets[i] == bkt) { - if (pk_bucket_head == i + 1) - pk_bucket_head--; - break; - } - } - if (bkt->blocks != NULL && bkt->blocks != CAFE_BABE(struct pk_memblock)) free(bkt->blocks); - bkt->size = 0; - bkt->head = 0; - bkt->lostBytes = 0; - bkt->allocs = 0; - bkt->lastEmptyBlockIndex = 0; - bkt->maxBlockCount = 0; - bkt->blocks = CAFE_BABE(struct pk_memblock); - bkt->ptr = CAFE_BABE(char); - bkt->transient = false; - mtx_destroy(&bkt->mtx); + assert(bkt != NULL); #ifdef PK_MEMORY_DEBUGGER - mtx_lock(&debug_alloc_mtx); - size_t dahl = debug_alloc_head_l; - size_t dahr = debug_alloc_head_r; - size_t found_dahl = dahl; - for (i = dahr; i > 0; --i) { - if (debug_all_allocs[i-1].bkt == bkt) { - if (i < found_dahl) { - if (found_dahl == dahr) { - dahr = i; - } - found_dahl = i; - } - debug_all_allocs[i-1].blk.data = NULL; - debug_all_allocs[i-1].blk.size = 0u; + mtx_lock(&debug_mtx); + assert(bkt->debug_bkt_index <= debug_alloc_head); + if (debug_allocs[bkt->debug_bkt_index] != NULL) free(debug_allocs[bkt->debug_bkt_index]); + debug_allocs[bkt->debug_bkt_index] = NULL; + while (debug_alloc_head > 0) { + if (debug_allocs[debug_alloc_head-1] != NULL) { + break; } + debug_alloc_head--; } - debug_alloc_head_l = found_dahl; - debug_alloc_head_r = dahr; -#ifdef PK_MEMORY_DEBUGGER_L2 - assert(debug_alloc_head_l <= debug_alloc_head_r); -#endif - mtx_unlock(&debug_alloc_mtx); + mtx_unlock(&debug_mtx); #endif + free(bkt); } void pk_bucket_reset(struct pk_membucket* bkt) { -#ifdef PK_MEMORY_DEBUGGER - size_t i; -#endif - if (bkt->transient != true) { + if (PK_HAS_FLAG(bkt->flags, PK_MEMBUCKET_FLAG_TRANSIENT) == true) { PK_LOG_ERR("WARNING: pk_bucket_reset called on non-transient pk_membucket\n"); } bkt->head = 0; - bkt->lostBytes = 0; - bkt->allocs = 0; - bkt->lastEmptyBlockIndex = 0; - bkt->blocks->data = bkt->ptr; - bkt->blocks->size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount); + bkt->block_capacity = 16; + char* blocks_addr = (char*)bkt + bkt->size - (sizeof(struct pk_memblock) * bkt->block_capacity); + blocks_addr -= (size_t)blocks_addr % 64; + bkt->blocks = (struct pk_memblock*)blocks_addr; + bkt->block_capacity = (size_t)(((char*)bkt + bkt->size) - blocks_addr) / sizeof(struct pk_memblock); + bkt->block_head_l = 0; + bkt->block_head_r = 0; + bkt->alloc_count = 0; + + bkt->blocks[pk_memblock_blocks_idx(bkt,0)].size = pk_bkt_data_sz(bkt); + bkt->blocks[pk_memblock_blocks_idx(bkt,0)].ptr = pk_bkt_data(bkt); + #ifdef PK_MEMORY_DEBUGGER - mtx_lock(&debug_alloc_mtx); - size_t dahl = debug_alloc_head_l; - size_t dahr = debug_alloc_head_r; - size_t found_dahl = dahl; - for (i = dahr; i > 0; --i) { - if (debug_all_allocs[i-1].bkt == bkt) { - if (i < found_dahl) { - if (found_dahl == dahr) { - dahr = i; - } - found_dahl = i; - } - debug_all_allocs[i-1].blk.data = NULL; - debug_all_allocs[i-1].blk.size = 0u; - } - } - debug_alloc_head_l = found_dahl; - debug_alloc_head_r = dahr; -#ifdef PK_MEMORY_DEBUGGER_L2 - assert(debug_alloc_head_l <= debug_alloc_head_r); -#endif - mtx_unlock(&debug_alloc_mtx); + bkt->debug_head_l = 0; + bkt->debug_head_r = 0; #endif } +void pk_bucket_set_client_bucket(struct pk_membucket *bkt) { + client_bucket = bkt; +} + void pk_bucket_insert_block(struct pk_membucket* bkt, const struct pk_memblock* block) { - int64_t index = bkt->lastEmptyBlockIndex; - while (index >= 0) { - struct pk_memblock* b = &bkt->blocks[index]; - struct pk_memblock* nb = &bkt->blocks[index + 1]; - if (b->data < block->data) { + // 2025-06-03 JCB + // Note that this function should only be called if we're INSERTING. + // This means that the block will never go at the END of the list - that would be an append. + // It can, however, be placed at the beginning, in which case the entire array shifts. + + struct pk_memblock* new_block; + struct pk_memblock* old_block; + size_t i, k; + + // 1. resize if needed + if (bkt->block_head_r+1 == bkt->block_capacity) { + if (bkt->blocks[pk_memblock_blocks_idx(bkt, bkt->block_head_r)].size < sizeof(struct pk_memblock)) { + PK_LOG_ERR("[pkmem.h] bkt out of memory when expanding memory blocks."); + exit(1); + } + // this is all that needs done, arr can just grow like this + bkt->blocks[pk_memblock_blocks_idx(bkt, bkt->block_head_r)].size -= sizeof(struct pk_memblock); + bkt->block_capacity += 1; + bkt->blocks -= 1; + } + + // 2. move all blocks forward until we pass the pointer + // reminder that these blocks are in REVERSE order + for (i = bkt->block_head_r+1; i > 0; --i) { + k = pk_memblock_blocks_idx(bkt, i); + new_block = &bkt->blocks[k]; + old_block = new_block+1; + *new_block = *old_block; + if (old_block->data < block->data) { break; } - nb->data = b->data; - nb->size = b->size; - index -= 1; } - struct pk_memblock *b = &bkt->blocks[index + 1]; - b->data = block->data; - b->size = block->size; - bkt->lastEmptyBlockIndex += 1; + if (i == 0) { + *old_block = *block; + } else { + *new_block = *block; + } + bkt->block_head_r += 1; } void -pk_bucket_collapse_empty_blocks(struct pk_membucket* bkt) +pk_bucket_collapse_blocks(struct pk_membucket* bkt) { - size_t i, ii; - for (ii = bkt->lastEmptyBlockIndex+1; ii > 0; --ii) { - i = ii-1; - struct pk_memblock* block = &bkt->blocks[i]; - if (block->size == 0 && i == bkt->lastEmptyBlockIndex) { - block->data = nullptr; - bkt->lastEmptyBlockIndex -= 1; - continue; - } - if (block->size > 0) { - continue; - } - for (size_t k = i; k < bkt->lastEmptyBlockIndex; ++k) { - bkt->blocks[k].data = bkt->blocks[k + 1].data; - bkt->blocks[k].size = bkt->blocks[k + 1].size; - } - bkt->lastEmptyBlockIndex -= 1; + // 1. loop through from (rev_idx)0 to head_r, shifting any blocks that have size 0 + struct pk_memblock* new_block; + struct pk_memblock* old_block; + size_t i, ii, bhr; + // there's an off by one annoynce here + // start with ii = 0 + // if we start with ii = 1, we might subtract from block_head_r when nothing was shifted + for (i = 0, ii = 0, bhr = bkt->block_head_r; (i + ii) <= bhr; ++i) { + new_block = &bkt->blocks[pk_memblock_blocks_idx(bkt, i)]; + if (new_block->size > 0) continue; + do { + old_block = new_block - ii; + if (old_block->size == 0) { + ii+=1; + } else { + break; + } + } while (i + ii <= bhr); + *new_block = *old_block; + old_block->size = 0; + old_block->ptr = NULL; } + bkt->block_head_r -= ii; } void* @@ -431,107 +411,86 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt) #ifdef PK_MEMORY_FORCE_MALLOC return malloc(sz); #endif - if (sz == 0) return nullptr; - if (bkt == nullptr) return nullptr; + if (sz == 0) return NULL; + if (bkt == NULL) return NULL; // TODO some type of error handling - if ((bkt->size - bkt->head) < (sz + alignment - 1)) return nullptr; - size_t i; + if ((bkt->size - bkt->head) < (sz + alignment - 1)) return NULL; + size_t i, k; size_t calculatedAlignment = alignment < PK_MINIMUM_ALIGNMENT ? PK_MINIMUM_ALIGNMENT : alignment; size_t misalignment = 0; - struct pk_memblock* prevBlock = nullptr; - struct pk_memblock* block = nullptr; - struct pk_memblock* nextBlock = nullptr; - void* data = nullptr; + struct pk_memblock tmp_blk; + struct pk_memblock* block = NULL; + void* data = NULL; mtx_lock(&bkt->mtx); - for (i = 0; i <= bkt->lastEmptyBlockIndex; ++i) { - struct pk_memblock* blk = &bkt->blocks[i]; - misalignment = (size_t)(blk->data) % calculatedAlignment; + + // find block + for (i = 0; i <= bkt->block_head_r; ++i) { + k = pk_memblock_blocks_idx(bkt, i); + tmp_blk = bkt->blocks[k]; + misalignment = (size_t)(tmp_blk.data) % calculatedAlignment; misalignment = (calculatedAlignment - misalignment) % calculatedAlignment; - if (blk->size >= sz + misalignment) { - block = blk; - if (i < bkt->lastEmptyBlockIndex && bkt->blocks[i + 1].data == block->data + block->size) { - nextBlock = &bkt->blocks[i + 1]; - } - if (i > 0 && i != bkt->lastEmptyBlockIndex && (bkt->blocks[i-1].data + bkt->blocks[i-1].size) == block->data) { - prevBlock = &bkt->blocks[i - 1]; - } - break; + if (tmp_blk.size < sz + misalignment) { + continue; } + block = &bkt->blocks[k]; + break; } - if (block == nullptr) { + if (block == NULL) { mtx_unlock(&bkt->mtx); - assert(block != nullptr && "memory corruption: not enough space in chosen bkt"); + assert(block != NULL && "memory corruption: not enough space in chosen bkt"); } data = block->data + misalignment; #ifdef PK_MEMORY_DEBUGGER - size_t dahr = debug_alloc_head_r; size_t ii; - if (bkt->transient == false) { - for (i = 0; i < dahr; ++i) { - if (debug_all_allocs[i].bkt != NULL) continue; - assert((debug_all_allocs[i].blk.size == 0 || (void*)(debug_all_allocs[i].blk.data) != data) && "mem address alloc'd twice!"); + if (PK_HAS_FLAG(bkt->flags, PK_MEMBUCKET_FLAG_TRANSIENT) == false) { + for (i = 0; i < bkt->debug_head_r; ++i) { + assert((debug_allocs[bkt->debug_bkt_index][i].size == 0 || (void*)(debug_allocs[bkt->debug_bkt_index][i].data) != data) && "mem address alloc'd twice!"); } - mtx_lock(&debug_alloc_mtx); - i = debug_alloc_head_l; - if (debug_alloc_head_l == debug_alloc_head_r) { - debug_alloc_head_l++; - debug_alloc_head_r++; + i = bkt->debug_head_l; + if (bkt->debug_head_l == bkt->debug_head_r) { + bkt->debug_head_l++; + bkt->debug_head_r++; } else { - for (ii = debug_alloc_head_l+1; ii <= dahr; ++ii) { - if (debug_all_allocs[ii].bkt == NULL) { - debug_alloc_head_l = ii; + for (ii = bkt->debug_head_l+1; ii <= bkt->debug_head_r; ++ii) { + if (debug_allocs[bkt->debug_bkt_index][ii].size == 0) { + bkt->debug_head_l = ii; break; } } } -#ifdef PK_MEMORY_DEBUGGER_L2 - assert(debug_alloc_head_l <= debug_alloc_head_r); -#endif - 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; + assert(bkt->debug_head_l <= bkt->debug_head_r); + debug_allocs[bkt->debug_bkt_index][i].data = (char*)data; + debug_allocs[bkt->debug_bkt_index][i].size = sz; } #endif - int64_t afterSize = block->size - (misalignment + sz); - if (block->data == bkt->ptr + bkt->head) { + if (block->data == pk_bkt_head(bkt)) { bkt->head += (sz + misalignment); } - if (afterSize > 0 && nextBlock == nullptr) { - struct pk_memblock newBlock; - memset(&newBlock, 0, sizeof(struct pk_memblock)); - newBlock.data = block->data + misalignment + sz; - newBlock.size = afterSize; - pk_bucket_insert_block(bkt, &newBlock); - } - if (prevBlock == nullptr && nextBlock == nullptr) { - block->size = misalignment; - } else if (nextBlock != nullptr) { - block->size = misalignment; - nextBlock->data -= afterSize; - nextBlock->size += afterSize; - } else if (prevBlock != nullptr) { - 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"); + + tmp_blk.data = block->data; + tmp_blk.size = misalignment; + block->data += misalignment + sz; + block->size -= misalignment + sz; + + if (tmp_blk.size > 0) { + pk_bucket_insert_block(bkt, &tmp_blk); } - bkt->allocs++; - assert(data >= bkt->raw && "allocated data is before bucket data"); - assert((char*)data <= bkt->ptr + bkt->size && "allocated data is after bucket data"); - pk_bucket_collapse_empty_blocks(bkt); + pk_bucket_collapse_blocks(bkt); + + bkt->alloc_count++; + assert(data >= (void*)pk_bkt_data(bkt) && "allocated data is before bucket data"); + assert((char*)data <= pk_bkt_data(bkt) + bkt->size && "allocated data is after bucket data"); #ifdef PK_MEMORY_DEBUGGER - if (!bkt->transient) { + if (PK_HAS_FLAG(bkt->flags, PK_MEMBUCKET_FLAG_TRANSIENT) == false) { + size_t k; int64_t debug_tracked_alloc_size = 0; - int64_t debug_bucket_alloc_size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount); - size_t dahr = debug_alloc_head_r; - for (i = 0; i < dahr; ++i) { - if (debug_all_allocs[i].bkt != bkt) continue; - debug_tracked_alloc_size += debug_all_allocs[i].blk.size; + int64_t debug_bucket_alloc_size = pk_bkt_data_sz(bkt); + for (i = 0; i < bkt->debug_head_r; ++i) { + debug_tracked_alloc_size += debug_allocs[bkt->debug_bkt_index][i].size; } - for (i = 0; i <= bkt->lastEmptyBlockIndex; ++i) { - debug_bucket_alloc_size -= bkt->blocks[i].size; + for (i = 0; i <= bkt->block_head_r; ++i) { + k = pk_memblock_blocks_idx(bkt, i); + debug_bucket_alloc_size -= bkt->blocks[k].size; } assert(debug_tracked_alloc_size == debug_bucket_alloc_size && "allocation size mismatch!"); } @@ -544,23 +503,8 @@ pk_new_bkt(size_t sz, size_t alignment, struct pk_membucket* bkt) void* pk_new_base(size_t sz, size_t alignment) { - struct pk_membucket* bkt = nullptr; - for (size_t i = 0; i < pk_bucket_head; ++i) { - if (pk_buckets[i].transient == true) { - continue; - } - if (pk_buckets[i].size - pk_buckets[i].head < sz + (alignment - 1)) { - continue; - } - bkt = &pk_buckets[i]; - break; - } - if (bkt == nullptr) { - int64_t bkt_index = pk_bucket_create_inner(PK_DEFAULT_BUCKET_SIZE, false, "pk_bucket internally created"); - // TODO some of of error handling - if (bkt_index >= 0) bkt = &pk_buckets[bkt_index]; - } - return pk_new_bkt(sz, alignment, bkt); + if (client_bucket == NULL) return NULL; + return pk_new_bkt(sz, alignment, client_bucket); } void* @@ -580,102 +524,112 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt) return free((void*)ptr); #endif #endif - size_t i; + size_t i, k; mtx_lock(&bkt->mtx); - assert(bkt->allocs > 0); - assert(ptr >= bkt->raw && (char*)ptr < bkt->ptr + bkt->size && "pointer not in memory bucket range"); + assert(bkt->alloc_count > 0); + assert(pk_memory_is_in_bucket(ptr, bkt) && "pointer not in memory bucket range"); assert(sz > 0 && "attempted to free pointer of size 0"); #ifdef PK_MEMORY_DEBUGGER - bool found = bkt->transient; - struct pk_dbg_memblock* mb; - mtx_lock(&debug_alloc_mtx); + bool found = PK_HAS_FLAG(bkt->flags, PK_MEMBUCKET_FLAG_TRANSIENT); + struct pk_memblock *debug_memblocks = debug_allocs[bkt->debug_bkt_index]; + struct pk_memblock *mb; if (found == false) { - size_t dahr = debug_alloc_head_r; - for (i = dahr; i > 0; --i) { - mb = &debug_all_allocs[i-1]; - if (mb->bkt != bkt) continue; - if (mb->blk.size == 0) continue; - if ((void*)(mb->blk.data) == ptr) { - assert(mb->blk.size == sz && "[pkmem.h] incorrect free size"); - mb->blk.size = 0; - mb->bkt = NULL; + for (i = bkt->debug_head_r+1; i > 0; --i) { + mb = &debug_memblocks[i-1]; + if (mb->size == 0) continue; + if ((void*)(mb->ptr) == ptr) { + assert(mb->size == sz && "[pkmem.h] incorrect free size"); + mb->ptr = NULL; + mb->size = 0; found = true; - if (i <= debug_alloc_head_l) { - debug_alloc_head_l = i-1; + if (i <= bkt->debug_head_l) { + bkt->debug_head_l = i-1; } - if (i == debug_alloc_head_r) { - debug_alloc_head_r--; + if (i == bkt->debug_head_r) { + bkt->debug_head_r--; } -#ifdef PK_MEMORY_DEBUGGER_L2 - assert(debug_alloc_head_l <= debug_alloc_head_r); -#endif + assert(bkt->debug_head_l <= bkt->debug_head_r); break; } } } - mtx_unlock(&debug_alloc_mtx); assert(found && "[pkmem.h] double free or invalid ptr"); #endif - bkt->allocs--; - if (bkt->allocs == 0) { + bkt->alloc_count--; + if (bkt->alloc_count == 0) { bkt->head = 0; - bkt->lastEmptyBlockIndex = 0; - bkt->blocks[0].data = bkt->ptr; - bkt->blocks[0].size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount); + bkt->block_head_l = 0; + bkt->block_head_r = 0; + bkt->blocks[0].data = pk_bkt_data(bkt); + bkt->blocks[0].size = pk_bkt_data_sz(bkt); +#ifdef PK_MEMORY_DEBUGGER + bkt->debug_head_l = 0; + bkt->debug_head_r = 0; + debug_allocs[bkt->debug_bkt_index][0].data = NULL; + debug_allocs[bkt->debug_bkt_index][0].size = 0; +#endif mtx_unlock(&bkt->mtx); return; } char* afterPtr = ((char*)(ptr))+sz; - struct pk_memblock* beforeBlk = nullptr; - struct pk_memblock* afterBlk = nullptr; - for (i = bkt->lastEmptyBlockIndex; i > 0; --i) { - if (bkt->blocks[i-1].data + bkt->blocks[i-1].size == ptr) { - beforeBlk = &bkt->blocks[i-1]; + struct pk_memblock* tmp_blk = NULL; + struct pk_memblock* beforeBlk = NULL; + struct pk_memblock* afterBlk = NULL; + for (i = bkt->block_head_r+1; i > 0 ; --i) { + k = pk_memblock_blocks_idx(bkt, i-2); + tmp_blk = &bkt->blocks[k]; + if (tmp_blk->data + tmp_blk->size == ptr) { + beforeBlk = tmp_blk; } - if (bkt->blocks[i].data == afterPtr) { - afterBlk = &bkt->blocks[i]; + tmp_blk -= 1; + if (i <= bkt->block_head_r+1 && tmp_blk->data == afterPtr) { + afterBlk = tmp_blk; break; } - if (bkt->blocks[i-1].data < (char*)ptr) { + tmp_blk += 1; + if (tmp_blk->data < (char*)ptr) { break; } } - if (ptr == bkt->ptr && afterBlk == nullptr && bkt->blocks[0].data == afterPtr) { - afterBlk = &bkt->blocks[0]; + if (ptr == &bkt->data[0] && afterBlk == NULL && bkt->blocks[pk_memblock_blocks_idx(bkt, 0)].data == afterPtr) { + afterBlk = &bkt->blocks[pk_memblock_blocks_idx(bkt, 0)]; } - if (afterBlk != nullptr && afterBlk->data == bkt->ptr + bkt->head) { + if (afterBlk != NULL && afterBlk->data == pk_bkt_head(bkt)) { bkt->head -= sz; - if (beforeBlk != nullptr) { + if (beforeBlk != NULL) { bkt->head -= beforeBlk->size; } } - if (beforeBlk == nullptr && afterBlk == nullptr) { + if (beforeBlk == NULL && afterBlk == NULL) { struct pk_memblock newBlock; memset(&newBlock, 0, sizeof(struct pk_memblock)); newBlock.data = (char*)ptr; newBlock.size = sz; pk_bucket_insert_block(bkt, &newBlock); - } else if (beforeBlk != nullptr && afterBlk != nullptr) { + } else if (beforeBlk != NULL && afterBlk != NULL) { beforeBlk->size += sz + afterBlk->size; + if (beforeBlk->data == pk_bkt_head(bkt)) { + bkt->block_head_r--; + } afterBlk->size = 0; - } else if (beforeBlk != nullptr) { + afterBlk->data = NULL; + } else if (beforeBlk != NULL) { beforeBlk->size += sz; - } else if (afterBlk != nullptr) { + } else if (afterBlk != NULL) { afterBlk->data -= sz; afterBlk->size += sz; } - pk_bucket_collapse_empty_blocks(bkt); + pk_bucket_collapse_blocks(bkt); #ifdef PK_MEMORY_DEBUGGER - if (!bkt->transient) { + if (PK_HAS_FLAG(bkt->flags, PK_MEMBUCKET_FLAG_TRANSIENT) == false) { int64_t debug_tracked_alloc_size = 0; - int64_t debug_bucket_alloc_size = bkt->size - (sizeof(struct pk_memblock) * bkt->maxBlockCount); - size_t dahr = debug_alloc_head_r; - for (i = 0; i < dahr; ++i) { - if (debug_all_allocs[i].bkt != bkt) continue; - debug_tracked_alloc_size += debug_all_allocs[i].blk.size; + int64_t debug_bucket_alloc_size = pk_bkt_data_sz(bkt); + for (i = 0; i < bkt->debug_head_r; ++i) { + debug_tracked_alloc_size += debug_allocs[bkt->debug_bkt_index][i].size; } - for (i = 0; i <= bkt->lastEmptyBlockIndex; ++i) { - debug_bucket_alloc_size -= bkt->blocks[i].size; + for (i = 0; i <= bkt->block_head_r; ++i) { + k = pk_memblock_blocks_idx(bkt, i); + debug_bucket_alloc_size -= bkt->blocks[k].size; } assert(debug_tracked_alloc_size == debug_bucket_alloc_size && "allocation size mismatch!"); } @@ -686,13 +640,7 @@ pk_delete_bkt(const void* ptr, size_t sz, struct pk_membucket* bkt) void pk_delete_base(const void* ptr, size_t sz) { - struct pk_membucket* bkt = nullptr; - for (size_t i = 0; i < pk_bucket_head; ++i) { - bkt = &pk_buckets[i]; - if (ptr >= bkt->raw && (char*)ptr < bkt->ptr + bkt->size) break; - } - assert(bkt != nullptr && "failed to determine correct memory bucket"); - pk_delete_bkt(ptr, sz, bkt); + pk_delete_bkt(ptr, sz, client_bucket); } void diff --git a/test/pkmem.c b/test/pkmem.c index 252428d..7614379 100644 --- a/test/pkmem.c +++ b/test/pkmem.c @@ -38,6 +38,7 @@ int main(int argc, char *argv[]) // pk_new_base { spinup_w_instr(); + pk_bucket_set_client_bucket(mt.bkt1); char *some_dang_string = (char*)pk_new_base(64, alignof(char*)); fprintf(stdout, "some_dang_string: %s: %p\n", some_dang_string, (void *)some_dang_string); pk_delete_base(some_dang_string, 64); @@ -64,9 +65,9 @@ int main(int argc, char *argv[]) if (zero_length_string != NULL) exit(1); if (strlen(three_length_string) != 2) exit(1); - if (mt.bkt1->allocs != 1) exit(1); + if (mt.bkt1->alloc_count != 1) exit(1); if (mt.bkt1->head != 3) exit(1); - if (mt.bkt1->lastEmptyBlockIndex != 0) exit(1); + if (mt.bkt1->block_head_r != 0) exit(1); PK_LOGV_INF("%s: %s\n", __FILE__, "handles zero-length alloc"); teardown(); diff --git a/test/pkmem.cpp b/test/pkmem.cpp index 98d2dd2..6a52f25 100644 --- a/test/pkmem.cpp +++ b/test/pkmem.cpp @@ -21,7 +21,9 @@ class FreeTest { void *ptrs[4]; FreeTest() : - bkt(pk_bucket_create("freetest", 1024 * 1024, false)) { } + bkt(pk_bucket_create("freetest", 1024 * 1024, PK_MEMBUCKET_FLAG_NONE)) { + pk_bucket_set_client_bucket(this->bkt); + } virtual ~FreeTest() { pk_bucket_destroy(this->bkt); } @@ -55,12 +57,12 @@ class FreeTest01 : public FreeTest { virtual ~FreeTest01() {} virtual void ensureState() override { - pk_mem_assert(3 == bkt->lastEmptyBlockIndex); + pk_mem_assert(3 == bkt->block_head_r); pk_mem_assert(80 == bkt->head); - pk_mem_assert(bkt->ptr + 00 == ptrs[0]); - pk_mem_assert(bkt->ptr + 64 == ptrs[1]); - pk_mem_assert(bkt->ptr + 16 == ptrs[2]); - pk_mem_assert(bkt->ptr + 8 == ptrs[3]); + pk_mem_assert(&bkt->data[0] + 00 == ptrs[0]); + pk_mem_assert(&bkt->data[0] + 64 == ptrs[1]); + pk_mem_assert(&bkt->data[0] + 16 == ptrs[2]); + pk_mem_assert(&bkt->data[0] + 8 == ptrs[3]); } }; @@ -89,17 +91,17 @@ class FreeTest02 : public FreeTest { virtual ~FreeTest02() {} virtual void ensureState() override { - pk_mem_assert(2 == bkt->lastEmptyBlockIndex); + pk_mem_assert(2 == bkt->block_head_r); pk_mem_assert(65 == bkt->head); - pk_mem_assert(bkt->ptr + 00 == ptrs[0]); - pk_mem_assert(bkt->ptr + 64 == ptrs[1]); - pk_mem_assert(bkt->ptr + 32 == ptrs[2]); + pk_mem_assert(&bkt->data[0] + 00 == ptrs[0]); + pk_mem_assert(&bkt->data[0] + 64 == ptrs[1]); + pk_mem_assert(&bkt->data[0] + 32 == ptrs[2]); - pk_mem_assert(bkt->ptr + 19 == bkt->blocks[0].data); - pk_mem_assert(13 == bkt->blocks[0].size); + pk_mem_assert(&bkt->data[0] + 19 == bkt->blocks[15].data); + pk_mem_assert(13 == bkt->blocks[15].size); - pk_mem_assert(bkt->ptr + 33 == bkt->blocks[1].data); - pk_mem_assert(31 == bkt->blocks[1].size); + pk_mem_assert(&bkt->data[0] + 33 == bkt->blocks[14].data); + pk_mem_assert(31 == bkt->blocks[14].size); } }; @@ -162,15 +164,36 @@ int main(int argc, char *argv[]) // signal(SIGABRT, handle_assert_abort); (void)argc; (void)argv; - int i; + // int i; // pk_new<T> pk_test_pkmem_spinup(true); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_basic_alloc); { + pk_membucket *bkt = pk_bucket_create("test-some-dang-string", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_bucket_set_client_bucket(bkt); + char *some_dang_string = pk_new<char>(64); + fprintf(stdout, "some_dang_string: %s: %p\n", some_dang_string, (void *)some_dang_string); + + fprintf(stdout, "debug block : size: %zu, data: %p\n", debug_allocs[0][0].size, debug_allocs[0][0].ptr); + pk_mem_assert(64 == debug_allocs[0][0].size); + pk_mem_assert((char*)bkt + EXPECTED_PK_MEMBLOCK_SIZE == debug_allocs[0][0].data); + + fprintf(stdout, "bkt->head : %lu\n", bkt->head); + pk_mem_assert(64 == bkt->head); + + fprintf(stdout, "blocks[15].data : %p\n", bkt->blocks[15].ptr); + pk_mem_assert(&bkt->data[0] + 64 == bkt->blocks[15].data); + + fprintf(stdout, "blocks[15].size : %li\n", bkt->blocks[15].size); + // 576 == 1024 - EXPECTED_PK_MEMBLOCK_SIZE - (sizeof(pk_memblock) * bkt->block_capacity) - 64 + pk_mem_assert(576 == bkt->blocks[15].size); + pk_delete<char>(some_dang_string, 64); + + pk_bucket_destroy(bkt); } pk_test_pkmem_teardown(); fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_basic_alloc); @@ -179,22 +202,25 @@ int main(int argc, char *argv[]) pk_test_pkmem_spinup(true); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_misalignment01); { - pk_membucket *bkt = pk_bucket_create("misalignment", 1024 * 1024, false); + pk_membucket *bkt = pk_bucket_create("misalignment", 1024 * 1024, PK_MEMBUCKET_FLAG_NONE); + pk_bucket_set_client_bucket(bkt); pk_new(1, 1, bkt); pk_new(1, 64, bkt); pk_new(9, 1, bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", bkt->lastEmptyBlockIndex); - pk_mem_assert(1 == bkt->lastEmptyBlockIndex); + fprintf(stdout, "block_head_r: %u\n", bkt->block_head_r); + pk_mem_assert(1 == bkt->block_head_r); - fprintf(stdout, "head : %li\n", bkt->head); + fprintf(stdout, "head : %li\n", bkt->head); pk_mem_assert(65 == bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)bkt->blocks[0].data); - pk_mem_assert(bkt->ptr + 10 == bkt->blocks[0].data); + fprintf(stdout, "blocks[15].data : %p\n", (void *)bkt->blocks[15].data); + pk_mem_assert(&bkt->data[0] + 10 == bkt->blocks[15].data); - fprintf(stdout, "blocks[0].size : %li\n", bkt->blocks[0].size); - pk_mem_assert(54 == bkt->blocks[0].size); + fprintf(stdout, "blocks[15].size : %li\n", bkt->blocks[15].size); + pk_mem_assert(54 == bkt->blocks[15].size); + + pk_bucket_destroy(bkt); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_misalignment01); pk_test_pkmem_teardown(); @@ -203,28 +229,31 @@ int main(int argc, char *argv[]) pk_test_pkmem_spinup(); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_misalignment02); { - pk_membucket *bkt = pk_bucket_create("misalignment", 1024 * 1024, false); + pk_membucket *bkt = pk_bucket_create("misalignment", 1024 * 1024, PK_MEMBUCKET_FLAG_NONE); + pk_bucket_set_client_bucket(bkt); pk_new(1, 1, bkt); pk_new(1, 64, bkt); pk_new(9, 16, bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", bkt->lastEmptyBlockIndex); - pk_mem_assert(2 == bkt->lastEmptyBlockIndex); + fprintf(stdout, "block_head_r: %u\n", bkt->block_head_r); + pk_mem_assert(2 == bkt->block_head_r); - fprintf(stdout, "head : %li\n", bkt->head); + fprintf(stdout, "head : %li\n", bkt->head); pk_mem_assert(65 == bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)bkt->blocks[0].data); - pk_mem_assert(bkt->ptr + 1 == bkt->blocks[0].data); + fprintf(stdout, "blocks[15].data : %p\n", (void *)bkt->blocks[15].data); + pk_mem_assert(&bkt->data[0] + 1 == bkt->blocks[15].data); - fprintf(stdout, "blocks[0].size : %li\n", bkt->blocks[0].size); - pk_mem_assert(15 == bkt->blocks[0].size); + fprintf(stdout, "blocks[15].size : %li\n", bkt->blocks[15].size); + pk_mem_assert(15 == bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)bkt->blocks[1].data); - pk_mem_assert(bkt->ptr + 25 == bkt->blocks[1].data); + fprintf(stdout, "blocks[14].data : %p\n", (void *)bkt->blocks[14].data); + pk_mem_assert(&bkt->data[0] + 25 == bkt->blocks[14].data); - fprintf(stdout, "blocks[1].size : %li\n", bkt->blocks[1].size); - pk_mem_assert(39 == bkt->blocks[1].size); + fprintf(stdout, "blocks[14].size : %li\n", bkt->blocks[14].size); + pk_mem_assert(39 == bkt->blocks[14].size); + + pk_bucket_destroy(bkt); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_misalignment02); pk_test_pkmem_teardown(); @@ -236,20 +265,20 @@ int main(int argc, char *argv[]) FreeTest01 ft{}; ft.ensureState(); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 2 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(6 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 2 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(6 == ft.bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)ft.bkt->blocks[1].data); - pk_mem_assert(ft.bkt->ptr + 12 == ft.bkt->blocks[1].data); - fprintf(stdout, "blocks[1].size : %li\n", ft.bkt->blocks[1].size); - pk_mem_assert(4 == ft.bkt->blocks[1].size); + fprintf(stdout, "blocks[14].data : %p\n", (void *)ft.bkt->blocks[14].data); + pk_mem_assert(&ft.bkt->data[0] + 12 == ft.bkt->blocks[14].data); + fprintf(stdout, "blocks[14].size : %li\n", ft.bkt->blocks[14].size); + pk_mem_assert(4 == ft.bkt->blocks[14].size); - fprintf(stdout, "blocks[2].data : %p\n", (void *)ft.bkt->blocks[2].data); - pk_mem_assert(ft.bkt->ptr + 32 == ft.bkt->blocks[2].data); - fprintf(stdout, "blocks[2].size : %li\n", ft.bkt->blocks[2].size); - pk_mem_assert(32 == ft.bkt->blocks[2].size); + fprintf(stdout, "blocks[13].data : %p\n", (void *)ft.bkt->blocks[13].data); + pk_mem_assert(&ft.bkt->data[0] + 32 == ft.bkt->blocks[13].data); + fprintf(stdout, "blocks[13].size : %li\n", ft.bkt->blocks[13].size); + pk_mem_assert(32 == ft.bkt->blocks[13].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_0000); pk_test_pkmem_teardown(); @@ -268,25 +297,25 @@ int main(int argc, char *argv[]) */ pk_delete(ft.ptrs[free_index], ft.sz[free_index], ft.bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(3 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(3 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(expected_head == ft.bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 0 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(8 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 0 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(8 == ft.bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)ft.bkt->blocks[1].data); - pk_mem_assert(ft.bkt->ptr + 12 == ft.bkt->blocks[1].data); - fprintf(stdout, "blocks[1].size : %li\n", ft.bkt->blocks[1].size); - pk_mem_assert(4 == ft.bkt->blocks[1].size); + fprintf(stdout, "blocks[14].data : %p\n", (void *)ft.bkt->blocks[14].data); + pk_mem_assert(&ft.bkt->data[0] + 12 == ft.bkt->blocks[14].data); + fprintf(stdout, "blocks[14].size : %li\n", ft.bkt->blocks[14].size); + pk_mem_assert(4 == ft.bkt->blocks[14].size); - fprintf(stdout, "blocks[2].data : %p\n", (void *)ft.bkt->blocks[2].data); - pk_mem_assert(ft.bkt->ptr + 32 == ft.bkt->blocks[2].data); - fprintf(stdout, "blocks[2].size : %li\n", ft.bkt->blocks[2].size); - pk_mem_assert(32 == ft.bkt->blocks[2].size); + fprintf(stdout, "blocks[13].data : %p\n", (void *)ft.bkt->blocks[13].data); + pk_mem_assert(&ft.bkt->data[0] + 32 == ft.bkt->blocks[13].data); + fprintf(stdout, "blocks[13].size : %li\n", ft.bkt->blocks[13].size); + pk_mem_assert(32 == ft.bkt->blocks[13].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_1000); pk_test_pkmem_teardown(); @@ -305,20 +334,20 @@ int main(int argc, char *argv[]) */ pk_delete(ft.ptrs[free_index], ft.sz[free_index], ft.bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(2 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(2 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(expected_head == ft.bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 2 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(6 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 2 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(6 == ft.bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)ft.bkt->blocks[1].data); - pk_mem_assert(ft.bkt->ptr + 12 == ft.bkt->blocks[1].data); - fprintf(stdout, "blocks[1].size : %li\n", ft.bkt->blocks[1].size); - pk_mem_assert(4 == ft.bkt->blocks[1].size); + fprintf(stdout, "blocks[14].data : %p\n", (void *)ft.bkt->blocks[14].data); + pk_mem_assert(&ft.bkt->data[0] + 12 == ft.bkt->blocks[14].data); + fprintf(stdout, "blocks[14].size : %li\n", ft.bkt->blocks[14].size); + pk_mem_assert(4 == ft.bkt->blocks[14].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_0100); pk_test_pkmem_teardown(); @@ -338,20 +367,20 @@ int main(int argc, char *argv[]) */ pk_delete(ft.ptrs[free_index], ft.sz[free_index], ft.bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(2 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(2 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(expected_head == ft.bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 2 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(6 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 2 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(6 == ft.bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)ft.bkt->blocks[1].data); - pk_mem_assert(ft.bkt->ptr + 12 == ft.bkt->blocks[1].data); - fprintf(stdout, "blocks[1].size : %li\n", ft.bkt->blocks[1].size); - pk_mem_assert(52 == ft.bkt->blocks[1].size); + fprintf(stdout, "blocks[14].data : %p\n", (void *)ft.bkt->blocks[14].data); + pk_mem_assert(&ft.bkt->data[0] + 12 == ft.bkt->blocks[14].data); + fprintf(stdout, "blocks[14].size : %li\n", ft.bkt->blocks[14].size); + pk_mem_assert(52 == ft.bkt->blocks[14].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_0010); pk_test_pkmem_teardown(); @@ -371,20 +400,20 @@ int main(int argc, char *argv[]) */ pk_delete(ft.ptrs[free_index], ft.sz[free_index], ft.bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(2 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(2 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(expected_head == ft.bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 2 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(14 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 2 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(14 == ft.bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)ft.bkt->blocks[1].data); - pk_mem_assert(ft.bkt->ptr + 32 == ft.bkt->blocks[1].data); - fprintf(stdout, "blocks[1].size : %li\n", ft.bkt->blocks[1].size); - pk_mem_assert(32 == ft.bkt->blocks[1].size); + fprintf(stdout, "blocks[14].data : %p\n", (void *)ft.bkt->blocks[14].data); + pk_mem_assert(&ft.bkt->data[0] + 32 == ft.bkt->blocks[14].data); + fprintf(stdout, "blocks[14].size : %li\n", ft.bkt->blocks[14].size); + pk_mem_assert(32 == ft.bkt->blocks[14].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_0001); pk_test_pkmem_teardown(); @@ -400,20 +429,20 @@ int main(int argc, char *argv[]) // [00-31 memblock pk_delete(ft.ptrs[0], ft.sz[0], ft.bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(2 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(2 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(65 == ft.bkt->head); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 0 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(32 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 0 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(32 == ft.bkt->blocks[15].size); - fprintf(stdout, "blocks[1].data : %p\n", (void *)ft.bkt->blocks[1].data); - pk_mem_assert(ft.bkt->ptr + 33 == ft.bkt->blocks[1].data); - fprintf(stdout, "blocks[1].size : %li\n", ft.bkt->blocks[1].size); - pk_mem_assert(31 == ft.bkt->blocks[1].size); + fprintf(stdout, "blocks[14].data : %p\n", (void *)ft.bkt->blocks[14].data); + pk_mem_assert(&ft.bkt->data[0] + 33 == ft.bkt->blocks[14].data); + fprintf(stdout, "blocks[14].size : %li\n", ft.bkt->blocks[14].size); + pk_mem_assert(31 == ft.bkt->blocks[14].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_after); pk_test_pkmem_teardown(); @@ -438,23 +467,23 @@ int main(int argc, char *argv[]) void *ptr4 = pk_new(31, 1, ft.bkt); void *ptr5 = pk_new( 1, 1, ft.bkt); - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(0 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(0 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(66 == ft.bkt->head); - fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); - pk_mem_assert(ft.bkt->ptr + 0 == ft.ptrs[0]); - fprintf(stdout, "ptr3 : %p\n", ptr3); - pk_mem_assert(ft.bkt->ptr + 19 == ptr3); - fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); - pk_mem_assert(ft.bkt->ptr + 32 == ft.ptrs[2]); - fprintf(stdout, "ptr4 : %p\n", ptr4); - pk_mem_assert(ft.bkt->ptr + 33 == ptr4); - fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); - pk_mem_assert(ft.bkt->ptr + 64 == ft.ptrs[1]); - fprintf(stdout, "ptr5 : %p\n", ptr5); - pk_mem_assert(ft.bkt->ptr + 65 == ptr5); + fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); + pk_mem_assert(&ft.bkt->data[0] + 0 == ft.ptrs[0]); + fprintf(stdout, "ptr3 : %p\n", ptr3); + pk_mem_assert(&ft.bkt->data[0] + 19 == ptr3); + fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); + pk_mem_assert(&ft.bkt->data[0] + 32 == ft.ptrs[2]); + fprintf(stdout, "ptr4 : %p\n", ptr4); + pk_mem_assert(&ft.bkt->data[0] + 33 == ptr4); + fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); + pk_mem_assert(&ft.bkt->data[0] + 64 == ft.ptrs[1]); + fprintf(stdout, "ptr5 : %p\n", ptr5); + pk_mem_assert(&ft.bkt->data[0] + 65 == ptr5); /* free [19-31] [00-18] (19) ptr0 @@ -468,28 +497,28 @@ int main(int argc, char *argv[]) pk_delete(ptr3, 13, ft.bkt); ptr3 = nullptr; - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(1 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(1 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(66 == ft.bkt->head); - fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); - pk_mem_assert(ft.bkt->ptr + 0 == ft.ptrs[0]); - fprintf(stdout, "ptr3 : %p\n", ptr3); + fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); + pk_mem_assert(&ft.bkt->data[0] + 0 == ft.ptrs[0]); + fprintf(stdout, "ptr3 : %p\n", ptr3); pk_mem_assert(nullptr == ptr3); - fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); - pk_mem_assert(ft.bkt->ptr + 32 == ft.ptrs[2]); - fprintf(stdout, "ptr4 : %p\n", ptr4); - pk_mem_assert(ft.bkt->ptr + 33 == ptr4); - fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); - pk_mem_assert(ft.bkt->ptr + 64 == ft.ptrs[1]); - fprintf(stdout, "ptr5 : %p\n", ptr5); - pk_mem_assert(ft.bkt->ptr + 65 == ptr5); - - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 19 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(13 == ft.bkt->blocks[0].size); + fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); + pk_mem_assert(&ft.bkt->data[0] + 32 == ft.ptrs[2]); + fprintf(stdout, "ptr4 : %p\n", ptr4); + pk_mem_assert(&ft.bkt->data[0] + 33 == ptr4); + fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); + pk_mem_assert(&ft.bkt->data[0] + 64 == ft.ptrs[1]); + fprintf(stdout, "ptr5 : %p\n", ptr5); + pk_mem_assert(&ft.bkt->data[0] + 65 == ptr5); + + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 19 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(13 == ft.bkt->blocks[15].size); /* free [32] which gets absorbed into 19-32 [19-32] (13) memblock @@ -498,28 +527,28 @@ int main(int argc, char *argv[]) pk_delete(ft.ptrs[2], ft.sz[2], ft.bkt); ft.ptrs[2] = nullptr; - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(1 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(1 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(66 == ft.bkt->head); - fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); - pk_mem_assert(ft.bkt->ptr + 0 == ft.ptrs[0]); - fprintf(stdout, "ptr3 : %p\n", ptr3); + fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); + pk_mem_assert(&ft.bkt->data[0] + 0 == ft.ptrs[0]); + fprintf(stdout, "ptr3 : %p\n", ptr3); pk_mem_assert(nullptr == ptr3); - fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); + fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); pk_mem_assert(nullptr == ft.ptrs[2]); - fprintf(stdout, "ptr4 : %p\n", ptr4); - pk_mem_assert(ft.bkt->ptr + 33 == ptr4); - fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); - pk_mem_assert(ft.bkt->ptr + 64 == ft.ptrs[1]); - fprintf(stdout, "ptr5 : %p\n", ptr5); - pk_mem_assert(ft.bkt->ptr + 65 == ptr5); - - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 19 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(14 == ft.bkt->blocks[0].size); + fprintf(stdout, "ptr4 : %p\n", ptr4); + pk_mem_assert(&ft.bkt->data[0] + 33 == ptr4); + fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); + pk_mem_assert(&ft.bkt->data[0] + 64 == ft.ptrs[1]); + fprintf(stdout, "ptr5 : %p\n", ptr5); + pk_mem_assert(&ft.bkt->data[0] + 65 == ptr5); + + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 19 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(14 == ft.bkt->blocks[15].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_before); pk_test_pkmem_teardown(); @@ -536,22 +565,22 @@ int main(int argc, char *argv[]) pk_delete(ft.ptrs[2], ft.sz[2], ft.bkt); ft.ptrs[2] = nullptr; - fprintf(stdout, "lastEmptyBlockIndex: %li\n", ft.bkt->lastEmptyBlockIndex); - pk_mem_assert(1 == ft.bkt->lastEmptyBlockIndex); - fprintf(stdout, "head : %li\n", ft.bkt->head); + fprintf(stdout, "block_head_r: %u\n", ft.bkt->block_head_r); + pk_mem_assert(1 == ft.bkt->block_head_r); + fprintf(stdout, "head : %li\n", ft.bkt->head); pk_mem_assert(65 == ft.bkt->head); - fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); - pk_mem_assert(ft.bkt->ptr + 0 == ft.ptrs[0]); - fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); + fprintf(stdout, "ptr0 : %p\n", ft.ptrs[0]); + pk_mem_assert(&ft.bkt->data[0] + 0 == ft.ptrs[0]); + fprintf(stdout, "ptr2 : %p\n", ft.ptrs[2]); pk_mem_assert(nullptr == ft.ptrs[2]); - fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); - pk_mem_assert(ft.bkt->ptr + 64 == ft.ptrs[1]); + fprintf(stdout, "ptr1 : %p\n", ft.ptrs[1]); + pk_mem_assert(&ft.bkt->data[0] + 64 == ft.ptrs[1]); - fprintf(stdout, "blocks[0].data : %p\n", (void *)ft.bkt->blocks[0].data); - pk_mem_assert(ft.bkt->ptr + 19 == ft.bkt->blocks[0].data); - fprintf(stdout, "blocks[0].size : %li\n", ft.bkt->blocks[0].size); - pk_mem_assert(45 == ft.bkt->blocks[0].size); + fprintf(stdout, "blocks[15].data : %p\n", (void *)ft.bkt->blocks[15].data); + pk_mem_assert(&ft.bkt->data[0] + 19 == ft.bkt->blocks[15].data); + fprintf(stdout, "blocks[15].size : %li\n", ft.bkt->blocks[15].size); + pk_mem_assert(45 == ft.bkt->blocks[15].size); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_free_between); pk_test_pkmem_teardown(); @@ -560,37 +589,37 @@ int main(int argc, char *argv[]) fprintf(stdout, "[pkmem.cpp] start: %s\n", test_alloc_strings); { size_t diff; - pk_membucket *bkt = pk_bucket_create(test_free_between, PK_DEFAULT_BUCKET_SIZE, false); + pk_membucket *bkt = pk_bucket_create(test_free_between, PK_DEFAULT_BUCKET_SIZE, PK_MEMBUCKET_FLAG_NONE); char *str1 = pk_new<char>(16, bkt); char *str2 = pk_new<char>(16, bkt); pk_handle *handle1 = pk_new<pk_handle>(bkt); pk_handle *handle2 = pk_new<pk_handle>(bkt); - fprintf(stdout, "ptr : %p\n", (void *)bkt->ptr); - fprintf(stdout, "str1 : %p\n", (void *)str1); - fprintf(stdout, "str2 : %p\n", (void *)str2); - fprintf(stdout, "handle1 : %p\n", (void *)handle1); - fprintf(stdout, "handle2 : %p\n", (void *)handle2); + fprintf(stdout, "ptr : %p\n", (void *)&bkt->data[0]); + fprintf(stdout, "str1 : %p\n", (void *)str1); + fprintf(stdout, "str2 : %p\n", (void *)str2); + fprintf(stdout, "handle1 : %p\n", (void *)handle1); + fprintf(stdout, "handle2 : %p\n", (void *)handle2); - diff = str1 - bkt->ptr; - fprintf(stdout, "str1 - ptr : %zu\n", diff); + diff = str1 - &bkt->data[0]; + fprintf(stdout, "str1 - ptr : %zu\n", diff); pk_mem_assert(diff == 0); diff = str2 - str1; - fprintf(stdout, "str2 - str1 : %zu\n", diff); + fprintf(stdout, "str2 - str1 : %zu\n", diff); pk_mem_assert(diff == 16); - diff = str2 - bkt->ptr; - fprintf(stdout, "str2 - ptr : %zu\n", diff); + diff = str2 - &bkt->data[0]; + fprintf(stdout, "str2 - ptr : %zu\n", diff); pk_mem_assert(diff == 16); diff = (char *)handle1 - str1; - fprintf(stdout, "handle1 - str1 : %zu\n", diff); + fprintf(stdout, "handle1 - str1 : %zu\n", diff); pk_mem_assert(diff == 32); diff = (char *)handle2 - (char *)handle1; - fprintf(stdout, "handle2 - handle1 : %zu\n", diff); + fprintf(stdout, "handle2 - handle1 : %zu\n", diff); pk_mem_assert(diff == 8); pk_bucket_destroy(bkt); @@ -599,29 +628,32 @@ int main(int argc, char *argv[]) pk_test_pkmem_teardown(); // assert bucket count + /* pk_test_pkmem_spinup(false); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_bucket_count01); do { for (i = 0; i < PK_MAX_BUCKET_COUNT; ++i) { - pk_membucket *bkt = pk_bucket_create("lol", 1024, false); + pk_membucket *bkt = pk_bucket_create("lol", 1024, PK_MEMBUCKET_FLAG_NONE); pk_mem_assert(bkt != nullptr); (void)bkt; } - pk_membucket *bkt = pk_bucket_create("lol", 1024, false); + pk_membucket *bkt = pk_bucket_create("lol", 1024, PK_MEMBUCKET_FLAG_NONE); pk_mem_assert(bkt == nullptr); } while(false); fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_bucket_count01); pk_test_pkmem_teardown(); + */ // assert no buckets available on pk_new with full memory + /* pk_test_pkmem_spinup(false); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_bucket_count02); do { for (i = 0; i < PK_MAX_BUCKET_COUNT; ++i) { - pk_membucket *bkt = pk_bucket_create("lol2", 1024, false); + pk_membucket *bkt = pk_bucket_create("lol2", 1024, PK_MEMBUCKET_FLAG_NONE); char *asdf = pk_new<char>(768, bkt); pk_mem_assert(asdf != nullptr); } @@ -631,15 +663,17 @@ int main(int argc, char *argv[]) while(false); fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_bucket_count02); pk_test_pkmem_teardown(); + */ // assert no buckets available on pk_new with full memory + /* pk_test_pkmem_spinup(false); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_bucket_count03); do { pk_membucket *bkt = nullptr; for (i = 0; i < PK_MAX_BUCKET_COUNT; ++i) { - bkt = pk_bucket_create("lol3", 1024, false); + bkt = pk_bucket_create("lol3", 1024, PK_MEMBUCKET_FLAG_NONE); char *asdf = pk_new<char>(768, bkt); pk_mem_assert(asdf != nullptr); } @@ -649,76 +683,79 @@ int main(int argc, char *argv[]) while(false); fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_bucket_count03); pk_test_pkmem_teardown(); + */ pk_test_pkmem_spinup(false); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_bucket_count04); { - pk_membucket *bkt1 = pk_bucket_create("bucket1", 1024, false); - pk_membucket *bkt2 = pk_bucket_create("bucket2", 1024, false); - pk_membucket *bkt3 = pk_bucket_create("bucket3", 1024, false); - pk_membucket *bkt4 = pk_bucket_create("bucket4", 1024, false); + pk_membucket *bkt1 = pk_bucket_create("bucket1", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_membucket *bkt2 = pk_bucket_create("bucket2", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_membucket *bkt3 = pk_bucket_create("bucket3", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_membucket *bkt4 = pk_bucket_create("bucket4", 1024, PK_MEMBUCKET_FLAG_NONE); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(4 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(4 == debug_alloc_head); pk_bucket_destroy(bkt4); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(3 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(3 == debug_alloc_head); pk_bucket_destroy(bkt3); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(2 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(2 == debug_alloc_head); pk_bucket_destroy(bkt2); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(1 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(1 == debug_alloc_head); pk_bucket_destroy(bkt1); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(0 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(0 == debug_alloc_head); } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_bucket_count04); pk_test_pkmem_teardown(); /* 2025-01-06 JCB * buckets are stored in an array. - * pk_bucket_head is only an *indicator* of how many buckets have been + * debug_alloc_head is only an *indicator* of how many buckets have been * created total, and the index of the next available. */ pk_test_pkmem_spinup(false); fprintf(stdout, "[pkmem.cpp] start: %s\n", test_bucket_count05); { - pk_membucket *bkt1 = pk_bucket_create("bucket1", 1024, false); - pk_membucket *bkt2 = pk_bucket_create("bucket2", 1024, false); - pk_membucket *bkt3 = pk_bucket_create("bucket3", 1024, false); - pk_membucket *bkt4 = pk_bucket_create("bucket4", 1024, false); + pk_membucket *bkt1 = pk_bucket_create("bucket1", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_membucket *bkt2 = pk_bucket_create("bucket2", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_membucket *bkt3 = pk_bucket_create("bucket3", 1024, PK_MEMBUCKET_FLAG_NONE); + pk_membucket *bkt4 = pk_bucket_create("bucket4", 1024, PK_MEMBUCKET_FLAG_NONE); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(4 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(4 == debug_alloc_head); pk_bucket_destroy(bkt1); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(4 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(4 == debug_alloc_head); pk_bucket_destroy(bkt2); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(4 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(4 == debug_alloc_head); pk_bucket_destroy(bkt3); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(4 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(4 == debug_alloc_head); pk_bucket_destroy(bkt4); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(3 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(0 == debug_alloc_head); + /* pk_memory_flush(); - fprintf(stdout, "pk_bucket_head: %li\n", pk_bucket_head); - pk_mem_assert(0 == pk_bucket_head); + fprintf(stdout, "debug_alloc_head: %li\n", debug_alloc_head); + pk_mem_assert(0 == debug_alloc_head); + */ } fprintf(stdout, "[pkmem.cpp] end: %s\n\n", test_bucket_count05); pk_test_pkmem_teardown(); |
