all repos — mgba @ d83520c5a246b8096ceb02ce001f4ee7291bba9f

mGBA Game Boy Advance Emulator

GBA Thread: Make GBAThreadInterrupt and -Continue check for the thread status, resolving several deadlocks
Jeffrey Pfau jeffrey@endrift.com
Sun, 09 Nov 2014 20:31:24 -0800
commit

d83520c5a246b8096ceb02ce001f4ee7291bba9f

parent

6e62ba8bb260ab39ff31dbdf5e0e000c72ffaba2

M src/gba/gba-thread.csrc/gba/gba-thread.c

@@ -426,10 +426,14 @@ threadContext->stateDir = 0;

} } +bool GBAThreadIsActive(struct GBAThread* threadContext) { + return threadContext->state >= THREAD_RUNNING && threadContext->state < THREAD_EXITING; +} + void GBAThreadInterrupt(struct GBAThread* threadContext) { MutexLock(&threadContext->stateMutex); ++threadContext->interruptDepth; - if (threadContext->interruptDepth > 1) { + if (threadContext->interruptDepth > 1 || !GBAThreadIsActive(threadContext)) { MutexUnlock(&threadContext->stateMutex); return; }

@@ -447,7 +451,7 @@

void GBAThreadContinue(struct GBAThread* threadContext) { MutexLock(&threadContext->stateMutex); --threadContext->interruptDepth; - if (threadContext->interruptDepth < 1) { + if (threadContext->interruptDepth < 1 && GBAThreadIsActive(threadContext)) { threadContext->state = threadContext->savedState; ConditionWake(&threadContext->stateCond); }
M src/gba/gba-thread.hsrc/gba/gba-thread.h

@@ -104,6 +104,7 @@ void GBAThreadEnd(struct GBAThread* threadContext);

void GBAThreadReset(struct GBAThread* threadContext); void GBAThreadJoin(struct GBAThread* threadContext); +bool GBAThreadIsActive(struct GBAThread* threadContext); void GBAThreadInterrupt(struct GBAThread* threadContext); void GBAThreadContinue(struct GBAThread* threadContext);
M src/platform/qt/Display.cppsrc/platform/qt/Display.cpp

@@ -52,13 +52,17 @@ }

void Display::stopDrawing() { if (m_drawThread) { - GBAThreadInterrupt(m_context); - GBASyncSuspendDrawing(&m_context->sync); + if (GBAThreadIsActive(m_context)) { + GBAThreadInterrupt(m_context); + GBASyncSuspendDrawing(&m_context->sync); + } QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection); m_drawThread->exit(); m_drawThread = nullptr; - GBASyncResumeDrawing(&m_context->sync); - GBAThreadContinue(m_context); + if (GBAThreadIsActive(m_context)) { + GBASyncResumeDrawing(&m_context->sync); + GBAThreadContinue(m_context); + } } }
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -250,13 +250,9 @@ QMetaObject::invokeMethod(m_audioProcessor, "setBufferSamples", Q_ARG(int, samples));

} void GameController::setFPSTarget(float fps) { - if (m_gameOpen) { - GBAThreadInterrupt(&m_threadContext); - m_threadContext.fpsTarget = fps; - GBAThreadContinue(&m_threadContext); - } else { - m_threadContext.fpsTarget = fps; - } + GBAThreadInterrupt(&m_threadContext); + m_threadContext.fpsTarget = fps; + GBAThreadContinue(&m_threadContext); QMetaObject::invokeMethod(m_audioProcessor, "inputParametersChanged"); }

@@ -315,23 +311,15 @@ }

} void GameController::setAVStream(GBAAVStream* stream) { - if (m_gameOpen) { - GBAThreadInterrupt(&m_threadContext); - m_threadContext.stream = stream; - GBAThreadContinue(&m_threadContext); - } else { - m_threadContext.stream = stream; - } + GBAThreadInterrupt(&m_threadContext); + m_threadContext.stream = stream; + GBAThreadContinue(&m_threadContext); } void GameController::clearAVStream() { - if (m_gameOpen) { - GBAThreadInterrupt(&m_threadContext); - m_threadContext.stream = nullptr; - GBAThreadContinue(&m_threadContext); - } else { - m_threadContext.stream = nullptr; - } + GBAThreadInterrupt(&m_threadContext); + m_threadContext.stream = nullptr; + GBAThreadContinue(&m_threadContext); } void GameController::updateKeys() {