Debugger: Fixed some deadlocks when pausing/resetting/changing game, fixed breakpoints not being remembered after a reset

This commit is contained in:
Souryo 2016-06-04 08:55:52 -04:00
parent 33c201984c
commit e210d267d8
7 changed files with 56 additions and 26 deletions

View file

@ -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));

View file

@ -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();

View file

@ -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();
}

View file

@ -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();

View file

@ -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];

View file

@ -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;
}
}

View file

@ -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()