diff --git a/src/gba/gba-thread.c b/src/gba/gba-thread.c index a8292b7f6..f6ba956da 100644 --- a/src/gba/gba-thread.c +++ b/src/gba/gba-thread.c @@ -147,10 +147,14 @@ static THREAD_ENTRY _GBAThreadRun(void* context) { } } MutexLock(&threadContext->stateMutex); - if (threadContext->state == THREAD_INTERRUPTED) { + if (threadContext->state == THREAD_PAUSING) { threadContext->state = THREAD_PAUSED; ConditionWake(&threadContext->stateCond); } + if (threadContext->state == THREAD_INTERRUPTING) { + threadContext->state = THREAD_INTERRUPTED; + ConditionWake(&threadContext->stateCond); + } while (threadContext->state == THREAD_PAUSED) { ConditionWait(&threadContext->stateCond, &threadContext->stateMutex); } @@ -280,15 +284,18 @@ void GBAThreadJoin(struct GBAThread* threadContext) { free(threadContext->rewindBuffer); } -void GBAThreadTryPause(struct GBAThread* threadContext) { +void GBAThreadInterrupt(struct GBAThread* threadContext) { MutexLock(&threadContext->stateMutex); threadContext->savedState = threadContext->state; - threadContext->state = THREAD_INTERRUPTED; _waitOnInterrupt(threadContext); - threadContext->state = THREAD_PAUSED; + threadContext->state = THREAD_INTERRUPTING; if (threadContext->debugger && threadContext->debugger->state == DEBUGGER_RUNNING) { threadContext->debugger->state = DEBUGGER_EXITING; } + ConditionWake(&threadContext->stateCond); + while (threadContext->state == THREAD_INTERRUPTING) { + ConditionWait(&threadContext->stateCond, &threadContext->stateMutex); + } MutexUnlock(&threadContext->stateMutex); } @@ -304,7 +311,7 @@ void GBAThreadPause(struct GBAThread* threadContext) { if (threadContext->debugger && threadContext->debugger->state == DEBUGGER_RUNNING) { threadContext->debugger->state = DEBUGGER_EXITING; } - threadContext->state = THREAD_PAUSED; + threadContext->state = THREAD_PAUSING; frameOn = 0; } MutexUnlock(&threadContext->stateMutex); @@ -320,7 +327,7 @@ void GBAThreadUnpause(struct GBAThread* threadContext) { int frameOn = 1; MutexLock(&threadContext->stateMutex); _waitOnInterrupt(threadContext); - if (threadContext->state == THREAD_PAUSED) { + if (threadContext->state == THREAD_PAUSED || threadContext->state == THREAD_PAUSING) { threadContext->state = THREAD_RUNNING; ConditionWake(&threadContext->stateCond); } diff --git a/src/gba/gba-thread.h b/src/gba/gba-thread.h index 249739d8f..5a04d2fb8 100644 --- a/src/gba/gba-thread.h +++ b/src/gba/gba-thread.h @@ -14,10 +14,12 @@ typedef void (*ThreadCallback)(struct GBAThread* threadContext); enum ThreadState { THREAD_INITIALIZED = -1, THREAD_RUNNING = 0, - THREAD_INTERRUPTED = 1, - THREAD_PAUSED = 2, - THREAD_EXITING = 3, - THREAD_SHUTDOWN = 4 + THREAD_INTERRUPTED, + THREAD_INTERRUPTING, + THREAD_PAUSED, + THREAD_PAUSING, + THREAD_EXITING, + THREAD_SHUTDOWN }; struct GBASync { diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c index 5b557e30d..80660b1f0 100644 --- a/src/platform/sdl/sdl-events.c +++ b/src/platform/sdl/sdl-events.c @@ -95,7 +95,7 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents context->sync.audioWait = event->type != SDL_KEYDOWN; return; case SDLK_LEFTBRACKET: - GBAThreadTryPause(context); + GBAThreadInterrupt(context); GBARewind(context, 10); GBAThreadContinue(context); return; @@ -134,7 +134,7 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents case SDLK_F8: case SDLK_F9: case SDLK_F10: - GBAThreadTryPause(context); + GBAThreadInterrupt(context); GBASaveState(context->gba, event->keysym.sym - SDLK_F1); GBAThreadContinue(context); break; @@ -153,7 +153,7 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents case SDLK_F8: case SDLK_F9: case SDLK_F10: - GBAThreadTryPause(context); + GBAThreadInterrupt(context); GBALoadState(context->gba, event->keysym.sym - SDLK_F1); GBAThreadContinue(context); break;