diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2023-02-12 16:38:12 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2023-02-12 16:38:12 +0100 |
| commit | 96a7d1e7ec0fa1266304779389359804e6108795 (patch) | |
| tree | 889bec6cc539ff6a6ea655b56d293c874480700e /src/libtools | |
| parent | 2d2a65b616b1bb4250cfdc1d300f7bbc14685a3a (diff) | |
| download | box64-96a7d1e7ec0fa1266304779389359804e6108795.tar.gz box64-96a7d1e7ec0fa1266304779389359804e6108795.zip | |
[DYNAREC] Use custom mutex, improved Signal while FillBlocks64 and atomic handling
Diffstat (limited to 'src/libtools')
| -rwxr-xr-x | src/libtools/signals.c | 44 | ||||
| -rwxr-xr-x | src/libtools/threads.c | 38 |
2 files changed, 46 insertions, 36 deletions
diff --git a/src/libtools/signals.c b/src/libtools/signals.c index f2121f73..e9fc475f 100755 --- a/src/libtools/signals.c +++ b/src/libtools/signals.c @@ -31,6 +31,7 @@ #ifdef DYNAREC #include "dynablock.h" #include "../dynarec/dynablock_private.h" +#include "dynarec_native.h" #endif @@ -266,6 +267,8 @@ static void sigstack_key_alloc() { pthread_key_create(&sigstack_key, sigstack_destroy); } +//1<<8 is mutex_dyndump +#define is_dyndump_locked (1<<8) uint64_t RunFunctionHandler(int* exit, x64_ucontext_t* sigcontext, uintptr_t fnc, int nargs, ...) { if(fnc==0 || fnc==1) { @@ -698,7 +701,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void *old_code = -1; // re-init the value to allow another segfault at the same place if(used_stack) // release stack new_ss->ss_flags = 0; - relockMutex(Locks); + //relockMutex(Locks); // do not relock mutex, because of the siglongjmp, whatever was running is canceled + if(Locks & is_dyndump_locked) + CancelBlock64(); siglongjmp(ejb->jmpbuf, 1); } printf_log(LOG_INFO, "Warning, context has been changed in Sigactionhanlder%s\n", (sigcontext->uc_mcontext.gregs[X64_RIP]!=sigcontext_copy.uc_mcontext.gregs[X64_RIP])?" (EIP changed)":""); @@ -738,7 +743,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void printf_log(LOG_DEBUG, "Sigactionhanlder main function returned (exit=%d, restorer=%p)\n", exits, (void*)restorer); if(exits) { - relockMutex(Locks); + //relockMutex(Locks); // the thread will exit, so no relock there + if(Locks & is_dyndump_locked) + CancelBlock64(); exit(ret); } if(restorer) @@ -746,9 +753,9 @@ void my_sigactionhandler_oldcode(int32_t sig, int simple, siginfo_t* info, void relockMutex(Locks); } -extern __thread void* current_helper; +extern void* current_helper; #ifdef DYNAREC -static pthread_mutex_t mutex_dynarec_prot; +static uint32_t mutex_dynarec_prot = 0; #endif extern int box64_quit; @@ -792,14 +799,14 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) int Locks = unlockMutex(); uint32_t prot = getProtection((uintptr_t)addr); #ifdef DYNAREC - if((Locks & (1<<8)) && (sig==SIGSEGV) && current_helper) {//1<<8 is mutex_dyndump + if((Locks & is_dyndump_locked) && (sig==SIGSEGV) && current_helper) { relockMutex(Locks); cancelFillBlock(); // Segfault inside a Fillblock, cancel it's creation... } dynablock_t* db = NULL; int db_searched = 0; if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && (prot&PROT_CUSTOM)) { - pthread_mutex_lock(&mutex_dynarec_prot); + mutex_lock(&mutex_dynarec_prot); // check if SMC inside block db = FindDynablockFromNativeAddress(pc); db_searched = 1; @@ -878,22 +885,24 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) } else { dynarec_log(LOG_INFO, "Dynablock unprotected, getting out!\n"); } - relockMutex(Locks); - pthread_mutex_unlock(&mutex_dynarec_prot); + //relockMutex(Locks); + if(Locks & is_dyndump_locked) + CancelBlock64(); + mutex_unlock(&mutex_dynarec_prot); siglongjmp(ejb->jmpbuf, 2); } dynarec_log(LOG_INFO, "Warning, Auto-SMC (%p for db %p/%p) detected, but jmpbuffer not ready!\n", (void*)addr, db, (void*)db->x64_addr); } // done if((prot&PROT_WRITE) || (prot&PROT_DYNAREC)) { - pthread_mutex_unlock(&mutex_dynarec_prot); + mutex_unlock(&mutex_dynarec_prot); // if there is no write permission, don't return and continue to program signal handling relockMutex(Locks); return; } - pthread_mutex_unlock(&mutex_dynarec_prot); + mutex_unlock(&mutex_dynarec_prot); } else if ((sig==SIGSEGV) && (addr) && (info->si_code == SEGV_ACCERR) && ((prot&(PROT_READ|PROT_WRITE))==(PROT_READ|PROT_WRITE))) { - pthread_mutex_lock(&mutex_dynarec_prot); + mutex_lock(&mutex_dynarec_prot); db = FindDynablockFromNativeAddress(pc); db_searched = 1; if(db && db->x64_addr>= addr && (db->x64_addr+db->x64_size)<addr) { @@ -910,7 +919,7 @@ void my_box64signalhandler(int32_t sig, siginfo_t* info, void * ucntx) glitch_addr = addr; glitch_prot = prot; relockMutex(Locks); - pthread_mutex_unlock(&mutex_dynarec_prot); + mutex_unlock(&mutex_dynarec_prot); return; // try again } dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for %p, db=%p, prot=0x%x\n", pc, addr, db, prot); @@ -932,14 +941,14 @@ dynarec_log(/*LOG_DEBUG*/LOG_INFO, "Repeated SIGSEGV with Access error on %p for refreshProtection((uintptr_t)addr); relockMutex(Locks); sched_yield(); // give time to the other process - pthread_mutex_unlock(&mutex_dynarec_prot); + mutex_unlock(&mutex_dynarec_prot); return; // try again } glitch2_pc = NULL; glitch2_addr = NULL; glitch2_prot = 0; } - pthread_mutex_unlock(&mutex_dynarec_prot); + mutex_unlock(&mutex_dynarec_prot); } if(!db_searched) db = FindDynablockFromNativeAddress(pc); @@ -1482,12 +1491,7 @@ EXPORT int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2) #ifdef DYNAREC static void atfork_child_dynarec_prot(void) { - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); - pthread_mutex_init(&mutex_dynarec_prot, &attr); - - pthread_mutexattr_destroy(&attr); + native_lock_store(&mutex_dynarec_prot, 0); } #endif void init_signal_helper(box64context_t* context) diff --git a/src/libtools/threads.c b/src/libtools/threads.c index 7e70b160..0877335b 100755 --- a/src/libtools/threads.c +++ b/src/libtools/threads.c @@ -80,50 +80,50 @@ void CleanStackSize(box64context_t* context) threadstack_t *ts; if(!context || !context->stacksizes) return; - pthread_mutex_lock(&context->mutex_thread); + mutex_lock(&context->mutex_thread); kh_foreach_value(context->stacksizes, ts, box_free(ts)); kh_destroy(threadstack, context->stacksizes); context->stacksizes = NULL; - pthread_mutex_unlock(&context->mutex_thread); + mutex_unlock(&context->mutex_thread); } void FreeStackSize(kh_threadstack_t* map, uintptr_t attr) { - pthread_mutex_lock(&my_context->mutex_thread); + mutex_lock(&my_context->mutex_thread); khint_t k = kh_get(threadstack, map, attr); if(k!=kh_end(map)) { box_free(kh_value(map, k)); kh_del(threadstack, map, k); } - pthread_mutex_unlock(&my_context->mutex_thread); + mutex_unlock(&my_context->mutex_thread); } void AddStackSize(kh_threadstack_t* map, uintptr_t attr, void* stack, size_t stacksize) { khint_t k; int ret; - pthread_mutex_lock(&my_context->mutex_thread); + mutex_lock(&my_context->mutex_thread); k = kh_put(threadstack, map, attr, &ret); threadstack_t* ts = kh_value(map, k) = (threadstack_t*)box_calloc(1, sizeof(threadstack_t)); ts->stack = stack; ts->stacksize = stacksize; - pthread_mutex_unlock(&my_context->mutex_thread); + mutex_unlock(&my_context->mutex_thread); } // return stack from attr (or from current emu if attr is not found..., wich is wrong but approximate enough?) int GetStackSize(x64emu_t* emu, uintptr_t attr, void** stack, size_t* stacksize) { if(emu->context->stacksizes && attr) { - pthread_mutex_lock(&my_context->mutex_thread); + mutex_lock(&my_context->mutex_thread); khint_t k = kh_get(threadstack, emu->context->stacksizes, attr); if(k!=kh_end(emu->context->stacksizes)) { threadstack_t* ts = kh_value(emu->context->stacksizes, k); *stack = ts->stack; *stacksize = ts->stacksize; - pthread_mutex_unlock(&my_context->mutex_thread); + mutex_unlock(&my_context->mutex_thread); return 1; } - pthread_mutex_unlock(&my_context->mutex_thread); + mutex_unlock(&my_context->mutex_thread); } // should a Warning be emited? *stack = emu->init_stack; @@ -680,10 +680,10 @@ int EXPORT my_pthread_once(x64emu_t* emu, int* once, void* cb) int old = native_lock_xchg_d(once, 1); #else int old = *once; // outside of the mutex in case once is badly formed - pthread_mutex_lock(&my_context->mutex_lock); + mutex_lock(&my_context->mutex_lock); old = *once; *once = 1; - pthread_mutex_unlock(&my_context->mutex_lock); + mutex_unlock(&my_context->mutex_lock); #endif if(old) return 0; @@ -837,7 +837,11 @@ typedef struct mutexes_block_s { } mutexes_block_t; static mutexes_block_t *mutexes = NULL; +#ifdef DYNAREC +static uint32_t mutex_mutexes = 0; +#else static pthread_mutex_t mutex_mutexes = PTHREAD_MUTEX_INITIALIZER; +#endif static mutexes_block_t* NewMutexesBlock() { @@ -847,7 +851,7 @@ static mutexes_block_t* NewMutexesBlock() } static int NewMutex() { - pthread_mutex_lock(&mutex_mutexes); + mutex_lock(&mutex_mutexes); if(!mutexes) { mutexes = NewMutexesBlock(); } @@ -864,10 +868,10 @@ static int NewMutex() { for (int i=0; i<MUTEXES_SIZE; ++i) if(!m->taken[i]) { m->taken[i] = 1; - pthread_mutex_unlock(&mutex_mutexes); + mutex_unlock(&mutex_mutexes); return j*MUTEXES_SIZE + i; } - pthread_mutex_unlock(&mutex_mutexes); + mutex_unlock(&mutex_mutexes); printf_log(LOG_NONE, "Error: NewMutex unreachable part reached\n"); return (int)-1; // error!!!! } @@ -876,13 +880,13 @@ void FreeMutex(int k) { if(!mutexes) return; //??? - pthread_mutex_lock(&mutex_mutexes); + mutex_lock(&mutex_mutexes); mutexes_block_t* m = mutexes; for(int i=0; i<k/MUTEXES_SIZE; ++i) m = m->next; m->taken[k%MUTEXES_SIZE] = 0; ++m->n_free; - pthread_mutex_unlock(&mutex_mutexes); + mutex_unlock(&mutex_mutexes); } void FreeAllMutexes(mutexes_block_t* m) @@ -1307,6 +1311,7 @@ void fini_pthread_helper(box64context_t* context) } } +#ifndef DYNAREC int checkUnlockMutex(void* m) { pthread_mutex_t* mutex = (pthread_mutex_t*)m; @@ -1316,3 +1321,4 @@ int checkUnlockMutex(void* m) } return 0; } +#endif \ No newline at end of file |