diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-05-10 16:23:46 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-05-10 16:24:01 +0200 |
| commit | 92dd53177f0119c0638c057ea7da5204046846d0 (patch) | |
| tree | 1df6ea01d55f4f7008cd7b972260fd4b22518250 | |
| parent | fe9e5bf21db4acca9b567f7ea36b084837ae7648 (diff) | |
| download | box64-92dd53177f0119c0638c057ea7da5204046846d0.tar.gz box64-92dd53177f0119c0638c057ea7da5204046846d0.zip | |
Improved custom memory allocator
| -rw-r--r-- | src/custommem.c | 86 | ||||
| -rwxr-xr-x | src/dynarec/dynablock.c | 3 | ||||
| -rwxr-xr-x | src/wrapped/wrappedlibc.c | 2 |
3 files changed, 70 insertions, 21 deletions
diff --git a/src/custommem.c b/src/custommem.c index 8c8807d7..8d7925ab 100644 --- a/src/custommem.c +++ b/src/custommem.c @@ -116,14 +116,14 @@ typedef struct blockmark_s { #define PREV_BLOCK(b) (blockmark_t*)(((uintptr_t)(b) - (b)->prev.size) - sizeof(blockmark_t)) #define LAST_BLOCK(b, s) (blockmark_t*)(((uintptr_t)(b)+(s))-sizeof(blockmark_t)) -static void printBlock(blockmark_t* b, void* start) +void printBlock(blockmark_t* b, void* start) { - printf_log(LOG_INFO, "========== Block is:\n"); + printf_log(LOG_NONE, "========== Block is:\n"); do { - printf_log(LOG_INFO, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size); + printf_log(LOG_NONE, "%c%p, fill=%d, size=0x%x (prev=%d/0x%x)\n", b==start?'*':' ', b, b->next.fill, b->next.size, b->prev.fill, b->prev.size); b = NEXT_BLOCK(b); } while(b->next.x32); - printf_log(LOG_INFO, "===================\n"); + printf_log(LOG_NONE, "===================\n"); } // get first subblock free in block. Return NULL if no block, else first subblock free (mark included), filling size @@ -241,7 +241,7 @@ static size_t freeBlock(void *block, void* sub, void** pstart) s->next.size += n->next.size + sizeof(blockmark_t); n2->prev.size = s->next.size; } - if(pstart && (uintptr_t)*pstart>(uintptr_t)sub) { + if(pstart && (uintptr_t)*pstart>(uintptr_t)s) { *pstart = (void*)s; } // return free size at current block (might be bigger) @@ -289,6 +289,62 @@ static size_t sizeBlock(void* sub) return s->next.size; } +// return 1 if block is coherent, 0 if not (and printf the issues) +int printBlockCoherent(int i) +{ + if(i<0 || i>=n_blocks) { + printf_log(LOG_NONE, "Error, %d should be between 0 and %d\n", i, n_blocks); + return 0; + } + int ret = 1; + blockmark_t* m = (blockmark_t*)p_blocks[i].block; + // check if first is correct + blockmark_t* first = getNextFreeBlock(m); + if(p_blocks[i].first && p_blocks[i].first!=first) {printf_log(LOG_NONE, "First %p and stored first %p differs for block %d\n", first, p_blocks[i].first, i); ret = 0;} + // check if maxfree is correct, with no hint + size_t maxfree = getMaxFreeBlock(m, p_blocks[i].size, NULL); + if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree without hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree); ret = 0;} + // check if maxfree from first is correct + maxfree = getMaxFreeBlock(m, p_blocks[i].size, p_blocks[i].first); + if(maxfree != p_blocks[i].maxfree) {printf_log(LOG_NONE, "Maxfree with hint %zd and stored maxfree %zd differs for block %d\n", maxfree, p_blocks[i].maxfree); ret = 0;} + // check chain + blockmark_t* last = (blockmark_t*)(((uintptr_t)m)+p_blocks[i].size-sizeof(blockmark_t)); + while(m<last) { + blockmark_t* n = NEXT_BLOCK(m); + if(!m->next.fill && !n->next.fill && n!=last) { + printf_log(LOG_NONE, "Chain contains 2 subsequent free blocks %p (%d) and %p (%d) for block %d\n", m, m->next.size, n, n->next.size, i); + ret = 0; + } + m = n; + } + if(m!=last) { + printf_log(LOG_NONE, "Last block %p is behond expexted block %p for block %d\n", m, last, i); + ret = 0; + } + + return ret; +} + +void testAllBlocks() +{ + size_t total = 0; + size_t fragmented_free = 0; + size_t max_free = 0; + for(int i=0; i<n_blocks; ++i) { + printBlockCoherent(i); + total += p_blocks[i].size; + if(max_free<p_blocks[i].maxfree) + max_free = p_blocks[i].maxfree; + blockmark_t* m = (blockmark_t*)p_blocks[i].block; + while(m->next.x32) { + if(!m->next.fill) + fragmented_free += m->next.size; + m = NEXT_BLOCK(m); + } + } + printf_log(LOG_NONE, "Total %d blocks, for %zd allocated memory, max_free %zd, toatal fragmented free %zd\n", n_blocks, total, max_free, fragmented_free); +} + #define THRESHOLD (128-2*sizeof(blockmark_t)) static size_t roundSize(size_t size) @@ -320,9 +376,7 @@ void* customMalloc(size_t size) if(sub) { if(rsize-size<THRESHOLD) size = rsize; - void* ret = allocBlock(p_blocks[i].block, sub, size, NULL); - if(sub==p_blocks[i].first) - p_blocks[i].first = getNextFreeBlock(sub); + void* ret = allocBlock(p_blocks[i].block, sub, size, &p_blocks[i].first); if(rsize==p_blocks[i].maxfree) p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first); mutex_unlock(&mutex_blocks); @@ -359,8 +413,8 @@ void* customMalloc(size_t size) n->prev.fill = 0; n->prev.size = m->next.size; // alloc 1st block - void* ret = allocBlock(p_blocks[i].block, p, size, NULL); - p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, NULL); + void* ret = allocBlock(p_blocks[i].block, p, size, &p_blocks[i].first); + p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first); mutex_unlock(&mutex_blocks); return ret; } @@ -383,7 +437,7 @@ void* customRealloc(void* p, size_t size) && (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) { void* sub = (void*)(addr-sizeof(blockmark_t)); if(expandBlock(p_blocks[i].block, sub, size)) { - if(sub<p_blocks[i].first && p+size<p_blocks[i].first) + if(sub<p_blocks[i].first && p+size>=p_blocks[i].first) p_blocks[i].first = getNextFreeBlock(sub); p_blocks[i].maxfree = getMaxFreeBlock(p_blocks[i].block, p_blocks[i].size, p_blocks[i].first); mutex_unlock(&mutex_blocks); @@ -411,10 +465,7 @@ void customFree(void* p) if ((addr>(uintptr_t)p_blocks[i].block) && (addr<((uintptr_t)p_blocks[i].block+p_blocks[i].size))) { void* sub = (void*)(addr-sizeof(blockmark_t)); - void* n = NEXT_BLOCK((blockmark_t*)sub); - size_t newfree = freeBlock(p_blocks[i].block, sub, NULL); - if(sub<=p_blocks[i].first) - p_blocks[i].first = getPrevFreeBlock(n); + size_t newfree = freeBlock(p_blocks[i].block, sub, &p_blocks[i].first); if(p_blocks[i].maxfree < newfree) p_blocks[i].maxfree = newfree; mutex_unlock(&mutex_blocks); return; @@ -563,10 +614,7 @@ void FreeDynarecMap(uintptr_t addr) if ((addr>(uintptr_t)list->chunks[i].block) && (addr<((uintptr_t)list->chunks[i].block+list->chunks[i].size))) { void* sub = (void*)(addr-sizeof(blockmark_t)); - void* n = NEXT_BLOCK((blockmark_t*)sub); - size_t newfree = freeBlock(list->chunks[i].block, sub, NULL); - if(sub<=list->chunks[i].first) - list->chunks[i].first = getPrevFreeBlock(n); + size_t newfree = freeBlock(list->chunks[i].block, sub, &list->chunks[i].first); if(list->chunks[i].maxfree < newfree) list->chunks[i].maxfree = newfree; return; diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 758e7c30..c0053a1b 100755 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -212,6 +212,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t block->x64_addr = (void*)addr; if(sigsetjmp(&dynarec_jmpbuf, 1)) { printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr); + FreeDynablock(block, 0); if(need_lock) mutex_unlock(&my_context->mutex_dyndump); return NULL; @@ -223,7 +224,7 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t block = NULL; } // check size - if(block && (block->x64_size || (!block->x64_size && !block->done))) { + if(block) { int blocksz = block->x64_size; if(blocksz>my_context->max_db_size) my_context->max_db_size = blocksz; diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index aee46157..c51f37d1 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -2654,7 +2654,7 @@ EXPORT int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot) if(prot& PROT_EXEC) addDBFromAddressRange((uintptr_t)addr, len); else - cleanDBFromAddressRange((uintptr_t)addr, len, 0); + cleanDBFromAddressRange((uintptr_t)addr, len, 1); } #endif if(!ret && len) |