diff --git a/include/mgba/debugger/debugger.h b/include/mgba/debugger/debugger.h index d66ea824b38..baef1d502d9 100644 --- a/include/mgba/debugger/debugger.h +++ b/include/mgba/debugger/debugger.h @@ -212,10 +212,13 @@ struct mDebuggerPlatform { void (*nextInstructionInfo)(struct mDebuggerPlatform* d, struct mDebuggerInstructionInfo* info); }; +struct mCoreThreadInternal; + struct mDebugger { struct mCPUComponent d; struct mDebuggerPlatform* platform; enum mDebuggerState state; + struct mCoreThreadInternal* threadImpl; struct mCore* core; struct mScriptBridge* bridge; struct mStackTrace stackTrace; @@ -245,9 +248,13 @@ void mDebuggerInit(struct mDebugger*); void mDebuggerDeinit(struct mDebugger*); void mDebuggerAttach(struct mDebugger*, struct mCore*); +#ifndef DISABLE_THREADING +void mDebuggerSetThread(struct mDebugger*, struct mCoreThreadInternal*); +void mDebuggerUnsetThread(struct mDebugger*); +#endif void mDebuggerAttachModule(struct mDebugger*, struct mDebuggerModule*); void mDebuggerDetachModule(struct mDebugger*, struct mDebuggerModule*); -void mDebuggerRunTimeout(struct mDebugger* debugger, int32_t timeoutMs); +void mDebuggerRunTimeout(struct mDebugger*, int32_t); void mDebuggerRun(struct mDebugger*); void mDebuggerRunFrame(struct mDebugger*); void mDebuggerEnter(struct mDebugger*, enum mDebuggerEntryReason, struct mDebuggerEntryInfo*); diff --git a/src/core/thread.c b/src/core/thread.c index 92d13412092..23c6263926d 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -285,9 +285,10 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { #ifdef ENABLE_DEBUGGERS struct mDebugger* debugger = core->debugger; if (debugger) { - MutexUnlock(&impl->stateMutex); + if (!debugger->threadImpl) { + mDebuggerSetThread(core->debugger, impl); + } mDebuggerRun(debugger); - MutexLock(&impl->stateMutex); if (debugger->state == DEBUGGER_SHUTDOWN) { impl->state = mTHREAD_EXITING; } @@ -385,6 +386,12 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { impl->state = mTHREAD_SHUTDOWN; } ConditionWake(&threadContext->impl->stateOffThreadCond); + +#ifdef ENABLE_DEBUGGERS + if (core->debugger && core->debugger->threadImpl) { + mDebuggerUnsetThread(core->debugger); + } +#endif MutexUnlock(&impl->stateMutex); if (core->opts.rewindEnable) { diff --git a/src/debugger/debugger.c b/src/debugger/debugger.c index 995a280991d..d5dfe3ac3fd 100644 --- a/src/debugger/debugger.c +++ b/src/debugger/debugger.c @@ -5,6 +5,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include +#ifndef DISABLE_THREADING +#include +#endif + #include #include @@ -97,6 +101,20 @@ void mDebuggerAttach(struct mDebugger* debugger, struct mCore* core) { core->attachDebugger(core, debugger); } +#ifndef DISABLE_THREADING +void mDebuggerSetThread(struct mDebugger* debugger, struct mCoreThreadInternal* thread) { + if (!debugger->threadImpl) { + debugger->threadImpl = thread; + } +} + +void mDebuggerUnsetThread(struct mDebugger* debugger) { + if (debugger->threadImpl) { + debugger->threadImpl = 0; + } +} +#endif + void mDebuggerAttachModule(struct mDebugger* debugger, struct mDebuggerModule* module) { module->p = debugger; *mDebuggerModuleListAppend(&debugger->modules) = module; @@ -127,37 +145,97 @@ void mDebuggerRunTimeout(struct mDebugger* debugger, int32_t timeoutMs) { size_t i; size_t anyPaused = 0; +#ifndef DISABLE_THREADING + struct mCoreThreadInternal* impl = debugger->threadImpl; +#endif + switch (debugger->state) { case DEBUGGER_RUNNING: - if (!debugger->platform->hasBreakpoints(debugger->platform)) { - debugger->core->runLoop(debugger->core); - } else { - debugger->core->step(debugger->core); - debugger->platform->checkBreakpoints(debugger->platform); + bool hasBreakpoints = debugger->platform->hasBreakpoints(debugger->platform); +#ifndef DISABLE_THREADING + if (impl) { + if (impl->state == mTHREAD_RUNNING) { + if (!hasBreakpoints) { + MutexUnlock(&impl->stateMutex); + debugger->core->runLoop(debugger->core); + MutexLock(&impl->stateMutex); + } else { + MutexUnlock(&impl->stateMutex); + debugger->core->step(debugger->core); + debugger->platform->checkBreakpoints(debugger->platform); + MutexLock(&impl->stateMutex); + } + } + } else +#endif + { + if (!hasBreakpoints) { + debugger->core->runLoop(debugger->core); + } else { + debugger->core->step(debugger->core); + debugger->platform->checkBreakpoints(debugger->platform); + } } break; case DEBUGGER_CALLBACK: - debugger->core->step(debugger->core); - debugger->platform->checkBreakpoints(debugger->platform); - for (i = 0; i < mDebuggerModuleListSize(&debugger->modules); ++i) { - struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); - if (module->needsCallback) { - module->custom(module); +#ifndef DISABLE_THREADING + if (impl) { + MutexUnlock(&impl->stateMutex); + debugger->core->step(debugger->core); + debugger->platform->checkBreakpoints(debugger->platform); + for (i = 0; i < mDebuggerModuleListSize(&debugger->modules); ++i) { + struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); + if (module->needsCallback) { + module->custom(module); + } + } + MutexLock(&impl->stateMutex); + } else +#endif + { + debugger->core->step(debugger->core); + debugger->platform->checkBreakpoints(debugger->platform); + for (i = 0; i < mDebuggerModuleListSize(&debugger->modules); ++i) { + struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); + if (module->needsCallback) { + module->custom(module); + } } } break; case DEBUGGER_PAUSED: - for (i = 0; i < mDebuggerModuleListSize(&debugger->modules); ++i) { - struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); - if (module->isPaused) { - if (module->paused) { - module->paused(module, timeoutMs); +#ifndef DISABLE_THREADING + if (impl) { + MutexUnlock(&impl->stateMutex); + for (i = 0; i < mDebuggerModuleListSize(&debugger->modules); ++i) { + struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); + if (module->isPaused) { + if (module->paused) { + module->paused(module, timeoutMs); + } + if (module->isPaused) { + ++anyPaused; + } + } else if (module->needsCallback) { + module->custom(module); } + } + MutexLock(&impl->stateMutex); + } else +#endif + { + for (i = 0; i < mDebuggerModuleListSize(&debugger->modules); ++i) { + struct mDebuggerModule* module = *mDebuggerModuleListGetPointer(&debugger->modules, i); if (module->isPaused) { - ++anyPaused; + if (module->paused) { + module->paused(module, timeoutMs); + } + if (module->isPaused) { + ++anyPaused; + } + } else if (module->needsCallback) { + module->custom(module); } - } else if (module->needsCallback) { - module->custom(module); } } if (debugger->state == DEBUGGER_PAUSED && !anyPaused) { @@ -165,7 +243,7 @@ void mDebuggerRunTimeout(struct mDebugger* debugger, int32_t timeoutMs) { } break; case DEBUGGER_CREATED: - mLOG(DEBUGGER, ERROR, "Attempted to run debugger before initializtion"); + mLOG(DEBUGGER, ERROR, "Attempted to run debugger before initialization"); return; case DEBUGGER_SHUTDOWN: return;