-
-
Notifications
You must be signed in to change notification settings - Fork 913
Debugger: Make debugger aware of thread status when using threads #3603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -5,6 +5,10 @@ | |||||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||||||
| #include <mgba/debugger/debugger.h> | ||||||
|
|
||||||
| #ifndef DISABLE_THREADING | ||||||
| #include <mgba/core/thread.h> | ||||||
| #endif | ||||||
|
|
||||||
| #include <mgba/core/core.h> | ||||||
|
|
||||||
| #include <mgba/internal/debugger/cli-debugger.h> | ||||||
|
|
@@ -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; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought 0 was the prefered C sintax and NULL for C++? |
||||||
| } | ||||||
| } | ||||||
| #endif | ||||||
|
|
||||||
| void mDebuggerAttachModule(struct mDebugger* debugger, struct mDebuggerModule* module) { | ||||||
| module->p = debugger; | ||||||
| *mDebuggerModuleListAppend(&debugger->modules) = module; | ||||||
|
|
@@ -127,45 +145,105 @@ 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) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Almost all of these checks can be put outside of the switch statement by just doing an unlock before and lock afterwards. The only exceptions are the early exit if the thread is paused, which doesn't really seem like it belongs in this function anyway (are there any other callsites that can't do the check itself?), and the two cases at the end, which you can do an early check for before unlocking. By doing the checks external to the switch statement, you can reduce duplication of code and massively reduce the diff size at the same time. |
||||||
| 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) { | ||||||
| debugger->state = DEBUGGER_RUNNING; | ||||||
| } | ||||||
| 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; | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave the name
timeoutMsin the signature. I remove parameter names that are obvious, buttimeoutMsincludes the unit, which justint32_tdoesn't.