about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2022-10-26 13:48:28 +0200
committerptitSeb <sebastien.chev@gmail.com>2022-10-26 13:48:28 +0200
commitbf75d6496f411bbbacc2d0687a32f0043c704438 (patch)
tree55ef5368d12fcc742758a9cb11321c339719de19 /src
parentfb7f134c064b189d3f91606a9257360e7be789c3 (diff)
downloadbox64-bf75d6496f411bbbacc2d0687a32f0043c704438.tar.gz
box64-bf75d6496f411bbbacc2d0687a32f0043c704438.zip
Made a custom implementation of pthread_once
Diffstat (limited to 'src')
-rwxr-xr-xsrc/box64context.c8
-rwxr-xr-xsrc/dynarec/arm64/arm64_lock.S12
-rwxr-xr-xsrc/dynarec/arm64/arm64_lock.h3
-rwxr-xr-xsrc/dynarec/native_lock.h1
-rwxr-xr-xsrc/include/box64context.h2
-rwxr-xr-xsrc/libtools/threads.c30
6 files changed, 31 insertions, 25 deletions
diff --git a/src/box64context.c b/src/box64context.c
index e4fd522b..46860a08 100755
--- a/src/box64context.c
+++ b/src/box64context.c
@@ -79,8 +79,6 @@ int unlockMutex()
             ret|=(1<<B);                \
         }
 
-    GO(my_context->mutex_once, 5)
-    GO(my_context->mutex_once2, 6)
     GO(my_context->mutex_trace, 7)
     #ifdef DYNAREC
     GO(my_context->mutex_dyndump, 8)
@@ -102,8 +100,6 @@ void relockMutex(int locks)
         if(locks&(1<<B))                \
             pthread_mutex_trylock(&A);  \
 
-    GO(my_context->mutex_once, 5)
-    GO(my_context->mutex_once2, 6)
     GO(my_context->mutex_trace, 7)
     #ifdef DYNAREC
     GO(my_context->mutex_dyndump, 8)
@@ -121,8 +117,6 @@ static void init_mutexes(box64context_t* context)
     pthread_mutexattr_t attr;
     pthread_mutexattr_init(&attr);
     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
-    pthread_mutex_init(&context->mutex_once, &attr);
-    pthread_mutex_init(&context->mutex_once2, &attr);
     pthread_mutex_init(&context->mutex_trace, &attr);
 #ifndef DYNAREC
     pthread_mutex_init(&context->mutex_lock, &attr);
@@ -292,8 +286,6 @@ void FreeBox64Context(box64context_t** context)
 
     finiAllHelpers(ctx);
 
-    pthread_mutex_destroy(&ctx->mutex_once);
-    pthread_mutex_destroy(&ctx->mutex_once2);
     pthread_mutex_destroy(&ctx->mutex_trace);
 #ifndef DYNAREC
     pthread_mutex_destroy(&ctx->mutex_lock);
diff --git a/src/dynarec/arm64/arm64_lock.S b/src/dynarec/arm64/arm64_lock.S
index 9d097ff5..92132bad 100755
--- a/src/dynarec/arm64/arm64_lock.S
+++ b/src/dynarec/arm64/arm64_lock.S
@@ -16,6 +16,7 @@
 .global arm64_lock_read_dq
 .global arm64_lock_write_dq
 .global arm64_lock_xchg
+.global arm64_lock_xchg_d
 .global arm64_lock_storeifnull
 .global arm64_lock_storeifref
 
@@ -100,6 +101,17 @@ arm64_lock_xchg_0:
     mov     x0, x2
     ret
 
+arm64_lock_xchg_d:
+    dmb     ish
+arm64_lock_xchg_d_0:
+    // address is x0, value is x1, return old value in x0
+    ldaxr   w2, [x0]
+    stlxr   w3, w1, [x0]
+    cbnz    w3, arm64_lock_xchg_d_0
+    dmb     ish
+    mov     w0, w2
+    ret
+
 arm64_lock_storeifnull:
     dmb     ish
 arm64_lock_storeifnull_0:
diff --git a/src/dynarec/arm64/arm64_lock.h b/src/dynarec/arm64/arm64_lock.h
index 8f6bd14d..76a1551c 100755
--- a/src/dynarec/arm64/arm64_lock.h
+++ b/src/dynarec/arm64/arm64_lock.h
@@ -30,6 +30,9 @@ extern int arm64_lock_write_dq(uint64_t a, uint64_t b, void* addr);
 // Atomicaly exchange value at [p] with val, return old p
 extern uintptr_t arm64_lock_xchg(void* p, uintptr_t val);
 
+// Atomicaly exchange value at [p] with val, return old p
+extern uint32_t arm64_lock_xchg_d(void* p, uint32_t val);
+
 // Atomicaly store value to [p] only if [p] is NULL. Return new [p] value (so val or old)
 extern void* arm64_lock_storeifnull(void*p, void* val);
 
diff --git a/src/dynarec/native_lock.h b/src/dynarec/native_lock.h
index 056947fd..e2070901 100755
--- a/src/dynarec/native_lock.h
+++ b/src/dynarec/native_lock.h
@@ -15,6 +15,7 @@
 #define native_lock_read_dq(A, B, C)        arm64_lock_read_dq(A, B, C)

 #define native_lock_write_dq(A, B, C)       arm64_lock_write_dq(A, B, C)

 #define native_lock_xchg(A, B)              arm64_lock_xchg(A, B)

+#define native_lock_xchg_d(A, B)            arm64_lock_xchg_d(A, B)

 #define native_lock_storeifref(A, B, C)     arm64_lock_storeifref(A, B, C)

 #define native_lock_storeifnull(A, B)       arm64_lock_storeifnull(A, B)

 

diff --git a/src/include/box64context.h b/src/include/box64context.h
index 17f4a2a0..da1f91af 100755
--- a/src/include/box64context.h
+++ b/src/include/box64context.h
@@ -122,8 +122,6 @@ typedef struct box64context_s {
     kh_defaultversion_t *weakdefver;    // the weak default version for symbols (the XXX@@vvvv of symbols)
     vkprocaddess_t      vkprocaddress;
 
-    pthread_mutex_t     mutex_once;
-    pthread_mutex_t     mutex_once2;
     pthread_mutex_t     mutex_trace;
     #ifndef DYNAREC
     pthread_mutex_t     mutex_lock;     // dynarec build will use their own mecanism
diff --git a/src/libtools/threads.c b/src/libtools/threads.c
index e09f5085..02a5de14 100755
--- a/src/libtools/threads.c
+++ b/src/libtools/threads.c
@@ -27,6 +27,7 @@
 #include "bridge.h"
 #ifdef DYNAREC
 #include "dynablock.h"
+#include "dynarec/native_lock.h"
 #endif
 
 //void _pthread_cleanup_push_defer(void* buffer, void* routine, void* arg);	// declare hidden functions
@@ -669,25 +670,24 @@ static void* findcleanup_routineFct(void* fct)
 
 #undef SUPER
 
-// once_callback
-// Don't use a "GO" scheme, once callback are only called once by definition
+// custom implementation of pthread_once...
 static __thread uintptr_t my_once_callback_fct = 0;
-static void my_once_callback()
-{
-	if(my_once_callback_fct) {
-	    EmuCall(thread_get_emu(), my_once_callback_fct);  // avoid DynaCall for now
-    	//RunFunction(my_context, my_once_callback_fct, 0, 0);
-	}
-}
-
 int EXPORT my_pthread_once(x64emu_t* emu, int* once, void* cb)
 {
 	(void)emu;
-	void * n = GetNativeFnc((uintptr_t)cb);
-	if(n)
-		return pthread_once(once, n);
-	my_once_callback_fct = (uintptr_t)cb;
-	return pthread_once(once, my_once_callback);
+	#ifdef DYNAREC
+	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);
+	old = *once;
+	*once = 1;
+	pthread_mutex_unlock(my_context->)mutex_lock);
+	#endif
+	if(old)
+		return 0;
+	EmuCall(thread_get_emu(), (uintptr_t)cb);  // avoid DynaCall for now
+	return 0;
 }
 EXPORT int my___pthread_once(x64emu_t* emu, void* once, void* cb) __attribute__((alias("my_pthread_once")));