mirror of https://github.com/mgba-emu/mgba.git
GBA Thread: Make GBAThreadInterrupt and -Continue check for the thread status, resolving several deadlocks
This commit is contained in:
parent
6e62ba8bb2
commit
d83520c5a2
|
@ -426,10 +426,14 @@ void GBAThreadJoin(struct GBAThread* threadContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GBAThreadIsActive(struct GBAThread* threadContext) {
|
||||||
|
return threadContext->state >= THREAD_RUNNING && threadContext->state < THREAD_EXITING;
|
||||||
|
}
|
||||||
|
|
||||||
void GBAThreadInterrupt(struct GBAThread* threadContext) {
|
void GBAThreadInterrupt(struct GBAThread* threadContext) {
|
||||||
MutexLock(&threadContext->stateMutex);
|
MutexLock(&threadContext->stateMutex);
|
||||||
++threadContext->interruptDepth;
|
++threadContext->interruptDepth;
|
||||||
if (threadContext->interruptDepth > 1) {
|
if (threadContext->interruptDepth > 1 || !GBAThreadIsActive(threadContext)) {
|
||||||
MutexUnlock(&threadContext->stateMutex);
|
MutexUnlock(&threadContext->stateMutex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -447,7 +451,7 @@ void GBAThreadInterrupt(struct GBAThread* threadContext) {
|
||||||
void GBAThreadContinue(struct GBAThread* threadContext) {
|
void GBAThreadContinue(struct GBAThread* threadContext) {
|
||||||
MutexLock(&threadContext->stateMutex);
|
MutexLock(&threadContext->stateMutex);
|
||||||
--threadContext->interruptDepth;
|
--threadContext->interruptDepth;
|
||||||
if (threadContext->interruptDepth < 1) {
|
if (threadContext->interruptDepth < 1 && GBAThreadIsActive(threadContext)) {
|
||||||
threadContext->state = threadContext->savedState;
|
threadContext->state = threadContext->savedState;
|
||||||
ConditionWake(&threadContext->stateCond);
|
ConditionWake(&threadContext->stateCond);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ void GBAThreadEnd(struct GBAThread* threadContext);
|
||||||
void GBAThreadReset(struct GBAThread* threadContext);
|
void GBAThreadReset(struct GBAThread* threadContext);
|
||||||
void GBAThreadJoin(struct GBAThread* threadContext);
|
void GBAThreadJoin(struct GBAThread* threadContext);
|
||||||
|
|
||||||
|
bool GBAThreadIsActive(struct GBAThread* threadContext);
|
||||||
void GBAThreadInterrupt(struct GBAThread* threadContext);
|
void GBAThreadInterrupt(struct GBAThread* threadContext);
|
||||||
void GBAThreadContinue(struct GBAThread* threadContext);
|
void GBAThreadContinue(struct GBAThread* threadContext);
|
||||||
|
|
||||||
|
|
|
@ -52,13 +52,17 @@ void Display::startDrawing(const uint32_t* buffer, GBAThread* thread) {
|
||||||
|
|
||||||
void Display::stopDrawing() {
|
void Display::stopDrawing() {
|
||||||
if (m_drawThread) {
|
if (m_drawThread) {
|
||||||
GBAThreadInterrupt(m_context);
|
if (GBAThreadIsActive(m_context)) {
|
||||||
GBASyncSuspendDrawing(&m_context->sync);
|
GBAThreadInterrupt(m_context);
|
||||||
|
GBASyncSuspendDrawing(&m_context->sync);
|
||||||
|
}
|
||||||
QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection);
|
QMetaObject::invokeMethod(m_painter, "stop", Qt::BlockingQueuedConnection);
|
||||||
m_drawThread->exit();
|
m_drawThread->exit();
|
||||||
m_drawThread = nullptr;
|
m_drawThread = nullptr;
|
||||||
GBASyncResumeDrawing(&m_context->sync);
|
if (GBAThreadIsActive(m_context)) {
|
||||||
GBAThreadContinue(m_context);
|
GBASyncResumeDrawing(&m_context->sync);
|
||||||
|
GBAThreadContinue(m_context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,13 +250,9 @@ void GameController::setAudioBufferSamples(int samples) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::setFPSTarget(float fps) {
|
void GameController::setFPSTarget(float fps) {
|
||||||
if (m_gameOpen) {
|
GBAThreadInterrupt(&m_threadContext);
|
||||||
GBAThreadInterrupt(&m_threadContext);
|
m_threadContext.fpsTarget = fps;
|
||||||
m_threadContext.fpsTarget = fps;
|
GBAThreadContinue(&m_threadContext);
|
||||||
GBAThreadContinue(&m_threadContext);
|
|
||||||
} else {
|
|
||||||
m_threadContext.fpsTarget = fps;
|
|
||||||
}
|
|
||||||
QMetaObject::invokeMethod(m_audioProcessor, "inputParametersChanged");
|
QMetaObject::invokeMethod(m_audioProcessor, "inputParametersChanged");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,23 +311,15 @@ void GameController::setTurbo(bool set, bool forced) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::setAVStream(GBAAVStream* stream) {
|
void GameController::setAVStream(GBAAVStream* stream) {
|
||||||
if (m_gameOpen) {
|
GBAThreadInterrupt(&m_threadContext);
|
||||||
GBAThreadInterrupt(&m_threadContext);
|
m_threadContext.stream = stream;
|
||||||
m_threadContext.stream = stream;
|
GBAThreadContinue(&m_threadContext);
|
||||||
GBAThreadContinue(&m_threadContext);
|
|
||||||
} else {
|
|
||||||
m_threadContext.stream = stream;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::clearAVStream() {
|
void GameController::clearAVStream() {
|
||||||
if (m_gameOpen) {
|
GBAThreadInterrupt(&m_threadContext);
|
||||||
GBAThreadInterrupt(&m_threadContext);
|
m_threadContext.stream = nullptr;
|
||||||
m_threadContext.stream = nullptr;
|
GBAThreadContinue(&m_threadContext);
|
||||||
GBAThreadContinue(&m_threadContext);
|
|
||||||
} else {
|
|
||||||
m_threadContext.stream = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameController::updateKeys() {
|
void GameController::updateKeys() {
|
||||||
|
|
Loading…
Reference in New Issue