diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2022-10-26 13:48:28 +0200 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2022-10-26 13:48:28 +0200 |
| commit | bf75d6496f411bbbacc2d0687a32f0043c704438 (patch) | |
| tree | 55ef5368d12fcc742758a9cb11321c339719de19 /src | |
| parent | fb7f134c064b189d3f91606a9257360e7be789c3 (diff) | |
| download | box64-bf75d6496f411bbbacc2d0687a32f0043c704438.tar.gz box64-bf75d6496f411bbbacc2d0687a32f0043c704438.zip | |
Made a custom implementation of pthread_once
Diffstat (limited to 'src')
| -rwxr-xr-x | src/box64context.c | 8 | ||||
| -rwxr-xr-x | src/dynarec/arm64/arm64_lock.S | 12 | ||||
| -rwxr-xr-x | src/dynarec/arm64/arm64_lock.h | 3 | ||||
| -rwxr-xr-x | src/dynarec/native_lock.h | 1 | ||||
| -rwxr-xr-x | src/include/box64context.h | 2 | ||||
| -rwxr-xr-x | src/libtools/threads.c | 30 |
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"))); |