Debugger: Fixed some deadlocks when pausing/resetting/changing game, fixed breakpoints not being remembered after a reset
This commit is contained in:
parent
33c201984c
commit
e210d267d8
7 changed files with 56 additions and 26 deletions
|
@ -66,6 +66,11 @@ void Console::Initialize(string romFilename, stringstream *filestream, string ip
|
|||
|
||||
_initialized = true;
|
||||
|
||||
if(_debugger) {
|
||||
StopDebugger();
|
||||
GetDebugger();
|
||||
}
|
||||
|
||||
ResetComponents(false);
|
||||
|
||||
VideoDecoder::GetInstance()->StartThread();
|
||||
|
@ -151,13 +156,6 @@ void Console::ResetComponents(bool softReset)
|
|||
{
|
||||
Movie::Stop();
|
||||
|
||||
if(_debugger) {
|
||||
//Reset debugger and break on first instruction
|
||||
StopDebugger();
|
||||
GetDebugger();
|
||||
_debugger->Step(1);
|
||||
}
|
||||
|
||||
_memoryManager->Reset(softReset);
|
||||
_ppu->Reset();
|
||||
_apu->Reset(softReset);
|
||||
|
@ -187,7 +185,7 @@ void Console::Pause()
|
|||
{
|
||||
if(Console::Instance->_debugger) {
|
||||
//Make sure debugger resumes if we try to pause the emu, otherwise we will get deadlocked.
|
||||
Console::Instance->_debugger->Run();
|
||||
Console::Instance->_debugger->Suspend();
|
||||
}
|
||||
Console::Instance->_pauseLock.Acquire();
|
||||
//Spin wait until emu pauses
|
||||
|
@ -198,6 +196,11 @@ void Console::Resume()
|
|||
{
|
||||
Console::Instance->_runLock.Release();
|
||||
Console::Instance->_pauseLock.Release();
|
||||
|
||||
if(Console::Instance->_debugger) {
|
||||
//Make sure debugger resumes if we try to pause the emu, otherwise we will get deadlocked.
|
||||
Console::Instance->_debugger->Resume();
|
||||
}
|
||||
}
|
||||
|
||||
void Console::Run()
|
||||
|
@ -365,7 +368,7 @@ void Console::LoadState(uint8_t *buffer, uint32_t bufferSize)
|
|||
LoadState(stream);
|
||||
}
|
||||
|
||||
std::weak_ptr<Debugger> Console::GetDebugger()
|
||||
std::shared_ptr<Debugger> Console::GetDebugger()
|
||||
{
|
||||
if(!_debugger) {
|
||||
_debugger.reset(new Debugger(Console::Instance, _cpu, _ppu, _memoryManager, _mapper));
|
||||
|
|
|
@ -53,7 +53,7 @@ class Console
|
|||
//Used to resume the emu loop after calling Pause()
|
||||
static void Resume();
|
||||
|
||||
std::weak_ptr<Debugger> GetDebugger();
|
||||
std::shared_ptr<Debugger> GetDebugger();
|
||||
void StopDebugger();
|
||||
|
||||
static NesModel GetNesModel();
|
||||
|
|
|
@ -43,16 +43,29 @@ Debugger::~Debugger()
|
|||
{
|
||||
SaveCdlFile(FolderUtilities::CombinePath(FolderUtilities::GetDebuggerFolder(), FolderUtilities::GetFilename(_romFilepath, false) + ".cdl"));
|
||||
|
||||
Run();
|
||||
_stopFlag = true;
|
||||
|
||||
Console::Pause();
|
||||
Debugger::Instance = nullptr;
|
||||
Run();
|
||||
_breakLock.Acquire();
|
||||
_breakLock.Release();
|
||||
Console::Resume();
|
||||
}
|
||||
|
||||
void Debugger::Suspend()
|
||||
{
|
||||
_suspendCount++;
|
||||
while(_executionStopped) {}
|
||||
}
|
||||
|
||||
void Debugger::Resume()
|
||||
{
|
||||
_suspendCount--;
|
||||
if(_suspendCount < 0) {
|
||||
_suspendCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::BreakIfDebugging()
|
||||
{
|
||||
if(Debugger::Instance != nullptr) {
|
||||
|
@ -92,7 +105,7 @@ void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
|||
{
|
||||
_hasBreakpoint = length > 0;
|
||||
|
||||
while(_bpUpdateNeeded) { }
|
||||
while(_updatingBreakpoints) { }
|
||||
_newBreakpoints.clear();
|
||||
_newBreakpoints.insert(_newBreakpoints.end(), breakpoints, breakpoints + length);
|
||||
_bpUpdateNeeded = true;
|
||||
|
@ -103,6 +116,7 @@ void Debugger::SetBreakpoints(Breakpoint breakpoints[], uint32_t length)
|
|||
|
||||
void Debugger::UpdateBreakpoints()
|
||||
{
|
||||
_updatingBreakpoints = true;
|
||||
if(_bpUpdateNeeded) {
|
||||
_globalBreakpoints.clear();
|
||||
_execBreakpoints.clear();
|
||||
|
@ -141,6 +155,8 @@ void Debugger::UpdateBreakpoints()
|
|||
|
||||
_bpUpdateNeeded = false;
|
||||
}
|
||||
|
||||
_updatingBreakpoints = false;
|
||||
}
|
||||
|
||||
bool Debugger::HasMatchingBreakpoint(BreakpointType type, uint32_t addr, int16_t value)
|
||||
|
@ -265,12 +281,13 @@ void Debugger::PrivateProcessRamOperation(MemoryOperationType type, uint16_t &ad
|
|||
UpdateCallstack(addr);
|
||||
ProcessStepConditions(addr);
|
||||
|
||||
breakDone = SleepUntilResume();
|
||||
|
||||
if(_traceLogger) {
|
||||
DebugState state;
|
||||
GetState(&state);
|
||||
_traceLogger->Log(state, _disassembler->GetDisassemblyInfo(absoluteAddr, absoluteRamAddr, addr));
|
||||
}
|
||||
breakDone = SleepUntilResume();
|
||||
}
|
||||
|
||||
if(!breakDone && _hasBreakpoint) {
|
||||
|
@ -309,14 +326,14 @@ bool Debugger::SleepUntilResume()
|
|||
stepCount = _stepCount.load();
|
||||
}
|
||||
|
||||
if(stepCount == 0) {
|
||||
if(stepCount == 0 && !_stopFlag && _suspendCount == 0) {
|
||||
//Break
|
||||
_breakLock.AcquireSafe();
|
||||
_executionStopped = true;
|
||||
SoundMixer::StopAudio();
|
||||
MessageManager::SendNotification(ConsoleNotificationType::CodeBreak);
|
||||
_stepOverAddr = -1;
|
||||
while(stepCount == 0) {
|
||||
while(stepCount == 0 && !_stopFlag && _suspendCount == 0) {
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(10));
|
||||
stepCount = _stepCount.load();
|
||||
}
|
||||
|
|
|
@ -44,7 +44,10 @@ private:
|
|||
shared_ptr<BaseMapper> _mapper;
|
||||
|
||||
atomic<bool> _bpUpdateNeeded;
|
||||
atomic<bool> _updatingBreakpoints;
|
||||
atomic<bool> _stopFlag;
|
||||
atomic<bool> _executionStopped;
|
||||
atomic<int32_t> _suspendCount;
|
||||
vector<Breakpoint> _newBreakpoints;
|
||||
vector<Breakpoint> _readBreakpoints;
|
||||
vector<Breakpoint> _writeBreakpoints;
|
||||
|
@ -101,6 +104,9 @@ public:
|
|||
|
||||
void GetState(DebugState *state);
|
||||
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
||||
void Step(uint32_t count = 1);
|
||||
void StepCycles(uint32_t cycleCount = 1);
|
||||
void StepOver();
|
||||
|
|
|
@ -239,7 +239,7 @@ int32_t ExpressionEvaluator::EvaluateExpression(vector<int> *outputQueue, DebugS
|
|||
int left = 0;
|
||||
int operandStack[1000];
|
||||
resultType = EvalResultType::Numeric;
|
||||
shared_ptr<Debugger> debugger = Console::GetInstance()->GetDebugger().lock();
|
||||
shared_ptr<Debugger> debugger = Console::GetInstance()->GetDebugger();
|
||||
|
||||
for(size_t i = 0, len = outputQueue->size(); i < len; i++) {
|
||||
int token = (*outputQueue)[i];
|
||||
|
|
|
@ -60,8 +60,17 @@ namespace Mesen.GUI.Debugger
|
|||
|
||||
private void _notifListener_OnNotification(InteropEmu.NotificationEventArgs e)
|
||||
{
|
||||
if(e.NotificationType == InteropEmu.ConsoleNotificationType.CodeBreak) {
|
||||
this.BeginInvoke((MethodInvoker)(() => UpdateDebugger()));
|
||||
switch(e.NotificationType) {
|
||||
case InteropEmu.ConsoleNotificationType.CodeBreak:
|
||||
this.BeginInvoke((MethodInvoker)(() => UpdateDebugger()));
|
||||
BreakpointManager.SetBreakpoints();
|
||||
break;
|
||||
|
||||
case InteropEmu.ConsoleNotificationType.GameReset:
|
||||
case InteropEmu.ConsoleNotificationType.GameLoaded:
|
||||
BreakpointManager.SetBreakpoints();
|
||||
InteropEmu.DebugStep(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,14 +3,9 @@
|
|||
#include "../Core/Debugger.h"
|
||||
#include "../Core/CodeDataLogger.h"
|
||||
|
||||
static std::weak_ptr<Debugger> _debugger;
|
||||
|
||||
shared_ptr<Debugger> GetDebugger()
|
||||
{
|
||||
if(_debugger.expired()) {
|
||||
_debugger = Console::GetInstance()->GetDebugger();
|
||||
}
|
||||
return _debugger.lock();
|
||||
return Console::GetInstance()->GetDebugger();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
|
@ -18,7 +13,7 @@ extern "C"
|
|||
//Debugger wrapper
|
||||
DllExport void __stdcall DebugInitialize()
|
||||
{
|
||||
_debugger = Console::GetInstance()->GetDebugger();
|
||||
Console::GetInstance()->GetDebugger();
|
||||
}
|
||||
|
||||
DllExport void __stdcall DebugRelease()
|
||||
|
|
Loading…
Add table
Reference in a new issue