about summary refs log tree commit diff stats
path: root/src/libtools
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2023-02-12 16:38:12 +0100
committerptitSeb <sebastien.chev@gmail.com>2023-02-12 16:38:12 +0100
commit96a7d1e7ec0fa1266304779389359804e6108795 (patch)
tree889bec6cc539ff6a6ea655b56d293c874480700e /src/libtools
parent2d2a65b616b1bb4250cfdc1d300f7bbc14685a3a (diff)
downloadbox64-96a7d1e7ec0fa1266304779389359804e6108795.tar.gz
box64-96a7d1e7ec0fa1266304779389359804e6108795.zip
[DYNAREC] Use custom mutex, improved Signal while FillBlocks64 and atomic handling
Diffstat (limited to 'src/libtools')
-rwxr-xr-xsrc/libtools/signals.c44
-rwxr-xr-xsrc/libtools/threads.c38
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