diff --git a/src/box86context.c b/src/box86context.c index e3c6f6e5..efe0d2c9 100755 --- a/src/box86context.c +++ b/src/box86context.c @@ -37,6 +37,7 @@ box86context_t *NewBox86Context(int argc) context->argv = (char**)calloc(context->argc, sizeof(char*)); pthread_mutex_init(&context->mutex_once, NULL); + pthread_mutex_init(&context->mutex_once2, NULL); return context; } @@ -93,6 +94,7 @@ void FreeBox86Context(box86context_t** context) FreeCallbackList(&(*context)->callbacks); pthread_mutex_destroy(&(*context)->mutex_once); + pthread_mutex_destroy(&(*context)->mutex_once2); free(*context); *context = NULL; diff --git a/src/box86context.h b/src/box86context.h index c566b53a..4094144d 100755 --- a/src/box86context.h +++ b/src/box86context.h @@ -58,6 +58,7 @@ typedef struct box86context_s { callbacklist_t *callbacks; // all callbacks pthread_mutex_t mutex_once; + pthread_mutex_t mutex_once2; library_t *libclib; // shortcut to libc library (if loaded, so probably yes) library_t *sdl1lib; // shortcut to SDL1 library (if loaded) diff --git a/src/callback.c b/src/callback.c index 451d8a36..840bc670 100755 --- a/src/callback.c +++ b/src/callback.c @@ -17,6 +17,7 @@ typedef struct onecallback_s { uintptr_t fnc; int nb_args; void* arg[10]; + int shared; } onecallback_t; KHASH_MAP_INIT_INT(callbacks, onecallback_t*) @@ -32,6 +33,7 @@ x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, voi callbacklist_t *callbacks = emu->context->callbacks; int stsize = 2*1024*1024; // 2MB stack (1MB is not enough for Xenonauts) void* stack = malloc(stsize); + if(!stack) {printf_log(LOG_NONE, "BOX86: Error, cannot allocate 2MB Stack for callback\n");} x86emu_t * newemu = NewX86Emu(emu->context, fnc, (uintptr_t)stack, stsize); SetupX86Emu(newemu, emu->shared_global, emu->globals); newemu->trace_start = emu->trace_start; @@ -50,12 +52,42 @@ x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, voi cb->arg[2] = arg3; cb->arg[3] = arg4; + cb->shared = 0; + return newemu; } -x86emu_t* AddSharedCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4) __attribute__((alias("AddCallback"))); -/*{ - // doesn't work for now +x86emu_t* AddSmallCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4) +{ + callbacklist_t *callbacks = emu->context->callbacks; + int stsize = 64*1024; // 64KB stack + void* stack = malloc(stsize); + if(!stack) {printf_log(LOG_NONE, "BOX86: Error, cannot allocate 64KB Stack for small callback\n");} + x86emu_t * newemu = NewX86Emu(emu->context, fnc, (uintptr_t)stack, stsize); + SetupX86Emu(newemu, emu->shared_global, emu->globals); + newemu->trace_start = emu->trace_start; + newemu->trace_end = emu->trace_end; + + onecallback_t * cb; + int ret; + khint_t k = kh_put(callbacks, callbacks->list, (uintptr_t)newemu, &ret); + cb = kh_value(callbacks->list, k) = (onecallback_t*)calloc(1, sizeof(onecallback_t)); + + cb->emu = newemu; + cb->fnc = fnc; + cb->nb_args = nb_args; + cb->arg[0] = arg1; + cb->arg[1] = arg2; + cb->arg[2] = arg3; + cb->arg[3] = arg4; + + cb->shared = 0; + + return newemu; +} + +x86emu_t* AddSharedCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4) //__attribute__((alias("AddCallback"))); +{ callbacklist_t *callbacks = emu->context->callbacks; x86emu_t * newemu = emu; @@ -71,9 +103,10 @@ x86emu_t* AddSharedCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg cb->arg[1] = arg2; cb->arg[2] = arg3; cb->arg[3] = arg4; + cb->shared = 1; return newemu; -}*/ +} onecallback_t* FindCallback(x86emu_t* emu) { @@ -93,7 +126,8 @@ void FreeCallback(x86emu_t* emu) if(k==kh_end(callbacks->list)) return; onecallback_t* cb = kh_value(callbacks->list, k); - FreeX86Emu(&cb->emu); + if(!cb->shared) + FreeX86Emu(&cb->emu); free(cb); kh_del(callbacks, callbacks->list, k); } @@ -105,6 +139,7 @@ uint32_t RunCallback(x86emu_t* emu) for (int i=cb->nb_args-1; i>=0; --i) // reverse order Push(emu, (uint32_t)cb->arg[i]); EmuCall(emu, cb->fnc); + R_ESP+=(cb->nb_args*4); return R_EAX; } printf_log(LOG_INFO, "Warning, Callback not found?!\n"); diff --git a/src/callback.h b/src/callback.h index 11d9307b..65ba6448 100755 --- a/src/callback.h +++ b/src/callback.h @@ -10,6 +10,7 @@ callbacklist_t* NewCallbackList(); void FreeCallbackList(callbacklist_t** callbacks); x86emu_t* AddCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4); +x86emu_t* AddSmallCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4); x86emu_t* AddSharedCallback(x86emu_t* emu, uintptr_t fnc, int nb_args, void* arg1, void* arg2, void* arg3, void* arg4); void FreeCallback(x86emu_t* emu); uint32_t RunCallback(x86emu_t* emu); diff --git a/src/threads.c b/src/threads.c index c841d12b..e4868cbd 100755 --- a/src/threads.c +++ b/src/threads.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "debug.h" #include "box86context.h" @@ -107,18 +108,36 @@ static void my_thread_once_callback() return; EmuCall(once_emu, once_fnc); } +static x86emu_t *once2_emu = NULL; +static uintptr_t once2_fnc = 0; +static void my_thread_once2_callback() +{ + if(!once2_emu) + return; + EmuCall(once2_emu, once2_fnc); +} int EXPORT my_pthread_once(x86emu_t* emu, void* once, void* cb) { - pthread_mutex_lock(&emu->context->mutex_once); // what if it deadlock here? + if(pthread_mutex_trylock(&emu->context->mutex_once)==EBUSY) + { + // 2nd level... + pthread_mutex_lock(&emu->context->mutex_once2); + once2_emu = emu; + once2_fnc = (uintptr_t)cb; + int ret = pthread_once(once, my_thread_once2_callback); + once_emu = NULL; + pthread_mutex_unlock(&emu->context->mutex_once2); + return ret; + } else { + once_emu = emu; + once_fnc = (uintptr_t)cb; + int ret = pthread_once(once, my_thread_once_callback); + once_emu = NULL; - once_emu = emu; - once_fnc = (uintptr_t)cb; - int ret = pthread_once(once, my_thread_once_callback); - once_emu = NULL; - - pthread_mutex_unlock(&emu->context->mutex_once); - return ret; + pthread_mutex_unlock(&emu->context->mutex_once); + return ret; + } } EXPORT int my_pthread_key_create(x86emu_t* emu, void* key, void* dtor) @@ -129,7 +148,7 @@ EXPORT int my_pthread_key_create(x86emu_t* emu, void* key, void* dtor) while (n