diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-11-11 20:47:10 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-11-11 20:47:10 +0100 |
| commit | 6a1b9e050a488cb5b2e1217fd3a01e484c3d7bb7 (patch) | |
| tree | ee38007ce576f32a13b6c8f9ec298002300d74ba /src/dynarec/dynablock.c | |
| parent | 6675b43dd0d7eb567227bea204ee663b1e7aab4a (diff) | |
| download | box64-6a1b9e050a488cb5b2e1217fd3a01e484c3d7bb7.tar.gz box64-6a1b9e050a488cb5b2e1217fd3a01e484c3d7bb7.zip | |
[DYNAREC] Changed Dynarec a bit to try stabilise program using many threads and a JIT (help RimWorld Linux, but not enough to be 100% stable)
Diffstat (limited to 'src/dynarec/dynablock.c')
| -rwxr-xr-x | src/dynarec/dynablock.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/src/dynarec/dynablock.c b/src/dynarec/dynablock.c index 469357a7..8a1a37e2 100755 --- a/src/dynarec/dynablock.c +++ b/src/dynarec/dynablock.c @@ -56,12 +56,14 @@ dynablocklist_t* NewDynablockList(uintptr_t text, int textsz, int direct) return ret; } -void FreeDynablock(dynablock_t* db) +void FreeDynablock(dynablock_t* db, int need_lock) { if(db) { - dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone); if(db->gone) return; // already in the process of deletion! + dynarec_log(LOG_DEBUG, "FreeDynablock(%p), db->block=%p x64=%p:%p parent=%p, father=%p, with %d son(s) already gone=%d\n", db, db->block, db->x64_addr, db->x64_addr+db->x64_size, db->parent, db->father, db->sons_size, db->gone); + if(need_lock) + pthread_mutex_lock(&my_context->mutex_dyndump); db->done = 0; db->gone = 1; // remove from direct if there @@ -77,16 +79,18 @@ void FreeDynablock(dynablock_t* db) // remove and free the sons for (int i=0; i<db->sons_size; ++i) { dynablock_t *son = (dynablock_t*)arm64_lock_xchg(&db->sons[i], 0); - FreeDynablock(son); + FreeDynablock(son, 0); } // only the father free the DynarecMap if(!db->father) { dynarec_log(LOG_DEBUG, " -- FreeDyrecMap(%p, %d)\n", db->block, db->size); FreeDynarecMap(db, (uintptr_t)db->block, db->size); + free(db->sons); + free(db->instsize); } - free(db->sons); - free(db->instsize); free(db); + if(need_lock) + pthread_mutex_unlock(&my_context->mutex_dyndump); } } @@ -100,7 +104,7 @@ void FreeDynablockList(dynablocklist_t** dynablocks) if((*dynablocks)->direct) { for (int i=0; i<(*dynablocks)->textsz; ++i) { if((*dynablocks)->direct[i] && !(*dynablocks)->direct[i]->father) - FreeDynablock((*dynablocks)->direct[i]); + FreeDynablock((*dynablocks)->direct[i], 1); } free((*dynablocks)->direct); } @@ -117,7 +121,7 @@ void MarkDynablock(dynablock_t* db) db = db->father; // mark only father if(db->need_test) return; // already done - db->need_test = 1; // test only blocks that can be marked (and so deleted) + db->need_test = 1; setJumpTableDefault64(db->x64_addr); for(int i=0; i<db->sons_size; ++i) setJumpTableDefault64(db->sons[i]->x64_addr); @@ -199,7 +203,7 @@ int FreeRangeDynablock(dynablocklist_t* dynablocks, uintptr_t addr, uintptr_t si } // purge the list kh_foreach_value(blocks, db, - FreeDynablock(db); + FreeDynablock(db, 1); ); kh_destroy(dynablocks, blocks); // check emptyness @@ -268,6 +272,7 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c if (!*created) return block; + pthread_mutex_lock(&my_context->mutex_dyndump); if(!dynablocks->direct) { dynablock_t** p = (dynablock_t**)calloc(dynablocks->textsz, sizeof(dynablock_t*)); if(arm64_lock_storeifnull(&dynablocks->direct, p)!=p) @@ -282,12 +287,14 @@ dynablock_t *AddNewDynablock(dynablocklist_t* dynablocks, uintptr_t addr, int* c dynablock_t* tmp = (dynablock_t*)arm64_lock_storeifnull(&dynablocks->direct[addr-dynablocks->text], block); if(tmp != block) { // a block appeard! + pthread_mutex_unlock(&my_context->mutex_dyndump); free(block); *created = 0; return tmp; } *created = 1; + pthread_mutex_lock(&my_context->mutex_dyndump); return block; } @@ -303,7 +310,7 @@ void cancelFillBlock() return NULL if block is not found / cannot be created. Don't create if create==0 */ -static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current) +static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr, int create, dynablock_t* current, int need_lock) { // try the quickest way first: get parent of current and check if ok! dynablocklist_t *dynablocks = NULL; @@ -332,19 +339,19 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t if(!created) return block; // existing block... - #if 0 - if(box64_dynarec_dump) - pthread_mutex_lock(&my_context->mutex_dyndump); - #endif // fill the block block->x64_addr = (void*)addr; - pthread_mutex_lock(&my_context->mutex_dyndump); + if(need_lock) + pthread_mutex_lock(&my_context->mutex_dyndump); if(sigsetjmp(&dynarec_jmpbuf, 1)) { printf_log(LOG_INFO, "FillBlock at %p triggered a segfault, cancelling\n", (void*)addr); + if(need_lock) + pthread_mutex_unlock(&my_context->mutex_dyndump); return NULL; } void* ret = FillBlock64(block, filladdr); - pthread_mutex_unlock(&my_context->mutex_dyndump); + if(need_lock) + pthread_mutex_unlock(&my_context->mutex_dyndump); if(!ret) { dynarec_log(LOG_DEBUG, "Fillblock of block %p for %p returned an error\n", block, (void*)addr); void* old = (void*)arm64_lock_storeifref(&dynablocks->direct[addr-dynablocks->text], 0, block); @@ -355,10 +362,6 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t free(block); block = NULL; } - #if 0 - if(box64_dynarec_dump) - pthread_mutex_unlock(&my_context->mutex_dyndump); - #endif // check size if(block && block->x64_size) { int blocksz = block->x64_size; @@ -388,19 +391,22 @@ static dynablock_t* internalDBGetBlock(x64emu_t* emu, uintptr_t addr, uintptr_t dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** current) { - dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current); + dynablock_t *db = internalDBGetBlock(emu, addr, addr, create, *current, 1); if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) { + if(pthread_mutex_trylock(&my_context->mutex_dyndump)) + return NULL; dynablock_t *father = db->father?db->father:db; uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size); if(hash!=father->hash) { + father->done = 0; // invalidating the block dynarec_log(LOG_DEBUG, "Invalidating block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr); // no more current if it gets invalidated too if(*current && father->x64_addr>=(*current)->x64_addr && (father->x64_addr+father->x64_size)<(*current)->x64_addr) *current = NULL; // Free father, it's now invalid! - FreeDynablock(father); + FreeDynablock(father, 0); // start again... (will create a new block) - db = internalDBGetBlock(emu, addr, addr, create, *current); + db = internalDBGetBlock(emu, addr, addr, create, *current, 0); } else { father->need_test = 0; protectDB((uintptr_t)father->x64_addr, father->x64_size); @@ -409,6 +415,7 @@ dynablock_t* DBGetBlock(x64emu_t* emu, uintptr_t addr, int create, dynablock_t** for(int i=0; i<father->sons_size; ++i) addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block); } + pthread_mutex_unlock(&my_context->mutex_dyndump); } return db; } @@ -417,16 +424,19 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr) { dynarec_log(LOG_DEBUG, "Creating AlternateBlock at %p for %p\n", (void*)addr, (void*)filladdr); int create = 1; - dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL); + dynablock_t *db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 1); if(db && db->done && db->block && (db->need_test || (db->father && db->father->need_test))) { + if(pthread_mutex_trylock(&my_context->mutex_dyndump)) + return NULL; dynablock_t *father = db->father?db->father:db; uint32_t hash = X31_hash_code(father->x64_addr, father->x64_size); if(hash!=father->hash) { + father->done = 0; // invalidating the block dynarec_log(LOG_DEBUG, "Invalidating alt block %p from %p:%p (hash:%X/%X) with %d son(s) for %p\n", father, father->x64_addr, father->x64_addr+father->x64_size, hash, father->hash, father->sons_size, (void*)addr); // Free father, it's now invalid! - FreeDynablock(father); + FreeDynablock(father, 0); // start again... (will create a new block) - db = internalDBGetBlock(emu, addr, filladdr, create, NULL); + db = internalDBGetBlock(emu, addr, filladdr, create, NULL, 0); } else { father->need_test = 0; protectDB((uintptr_t)father->x64_addr, father->x64_size); @@ -435,6 +445,7 @@ dynablock_t* DBAlternateBlock(x64emu_t* emu, uintptr_t addr, uintptr_t filladdr) for(int i=0; i<father->sons_size; ++i) addJumpTableIfDefault64(father->sons[i]->x64_addr, father->sons[i]->block); } + pthread_mutex_unlock(&my_context->mutex_dyndump); } return db; } |