Debugger refactor
This commit is contained in:
parent
81c399ec3e
commit
65d7a16a87
12 changed files with 115 additions and 114 deletions
|
@ -2,6 +2,8 @@ using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using ExecutionContext = ARMeilleure.State.ExecutionContext;
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
|
@ -175,7 +177,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
ExecutionContext context = GetContext();
|
ExecutionContext context = GetContext();
|
||||||
|
|
||||||
if (context.DebugStopped == 1)
|
if (Optimizations.EnableDebugging && context.Interrupted)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace ARMeilleure.State
|
||||||
|
|
||||||
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
||||||
|
|
||||||
private bool _interrupted;
|
internal bool Interrupted { get; private set; }
|
||||||
|
|
||||||
private readonly ICounter _counter;
|
private readonly ICounter _counter;
|
||||||
|
|
||||||
|
@ -103,9 +103,9 @@ namespace ARMeilleure.State
|
||||||
|
|
||||||
internal int ShouldStep;
|
internal int ShouldStep;
|
||||||
internal int DebugStopped;
|
internal int DebugStopped;
|
||||||
|
|
||||||
// This is only valid while debugging is enabled.
|
public ulong DebugPc; // This is only valid while debugging is enabled.
|
||||||
public ulong DebugPc;
|
public Barrier StepBarrier = new Barrier(2);
|
||||||
|
|
||||||
public ExecutionContext(
|
public ExecutionContext(
|
||||||
IJitMemoryAllocator allocator,
|
IJitMemoryAllocator allocator,
|
||||||
|
@ -141,9 +141,9 @@ namespace ARMeilleure.State
|
||||||
|
|
||||||
internal void CheckInterrupt()
|
internal void CheckInterrupt()
|
||||||
{
|
{
|
||||||
if (_interrupted)
|
if (Interrupted)
|
||||||
{
|
{
|
||||||
_interrupted = false;
|
Interrupted = false;
|
||||||
|
|
||||||
_interruptCallback?.Invoke(this);
|
_interruptCallback?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
@ -153,31 +153,13 @@ namespace ARMeilleure.State
|
||||||
|
|
||||||
public void RequestInterrupt()
|
public void RequestInterrupt()
|
||||||
{
|
{
|
||||||
_interrupted = true;
|
Interrupted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DebugStop()
|
public void RequestDebugStep()
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref DebugStopped, 1, 0) == 0)
|
Interlocked.Exchange(ref ShouldStep, 1);
|
||||||
{
|
RequestInterrupt();
|
||||||
RequestInterrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DebugStep()
|
|
||||||
{
|
|
||||||
if (DebugStopped != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ShouldStep = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DebugContinue()
|
|
||||||
{
|
|
||||||
Interlocked.CompareExchange(ref DebugStopped, 0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void OnBreak(ulong address, int imm)
|
internal void OnBreak(ulong address, int imm)
|
||||||
|
|
|
@ -145,17 +145,17 @@ namespace ARMeilleure.Translation
|
||||||
context.DebugPc = address;
|
context.DebugPc = address;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
context.DebugPc = ExecuteSingle(context, context.DebugPc);
|
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
|
||||||
|
|
||||||
while (context.DebugStopped == 1)
|
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref context.ShouldStep, 0, 1) == 1)
|
context.DebugPc = Step(context, context.DebugPc);
|
||||||
{
|
context.StepBarrier.SignalAndWait();
|
||||||
context.DebugPc = Step(context, context.DebugPc);
|
context.StepBarrier.SignalAndWait();
|
||||||
context.RequestInterrupt();
|
|
||||||
}
|
|
||||||
context.CheckInterrupt();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.DebugPc = ExecuteSingle(context, context.DebugPc);
|
||||||
|
}
|
||||||
|
context.CheckInterrupt();
|
||||||
}
|
}
|
||||||
while (context.Running && context.DebugPc != 0);
|
while (context.Running && context.DebugPc != 0);
|
||||||
}
|
}
|
||||||
|
|
10
src/Ryujinx.Cpu/AppleHv/Arm/ExceptionLevel.cs
Normal file
10
src/Ryujinx.Cpu/AppleHv/Arm/ExceptionLevel.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Ryujinx.Cpu.AppleHv.Arm
|
||||||
|
{
|
||||||
|
enum ExceptionLevel: uint
|
||||||
|
{
|
||||||
|
PstateMask = 0xfffffff0,
|
||||||
|
EL1h = 0b0101,
|
||||||
|
El1t = 0b0100,
|
||||||
|
EL0 = 0b0000,
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,18 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
class HvExecutionContext : IExecutionContext
|
class HvExecutionContext : IExecutionContext
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ulong Pc => _impl.ElrEl1;
|
public ulong Pc
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
||||||
|
if (currentEl == (uint)ExceptionLevel.EL1h)
|
||||||
|
{
|
||||||
|
return _impl.ElrEl1;
|
||||||
|
}
|
||||||
|
return _impl.Pc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public long TpidrEl0
|
public long TpidrEl0
|
||||||
|
@ -71,7 +82,6 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
private readonly IHvExecutionContext _shadowContext;
|
private readonly IHvExecutionContext _shadowContext;
|
||||||
private IHvExecutionContext _impl;
|
private IHvExecutionContext _impl;
|
||||||
private int _shouldStep;
|
private int _shouldStep;
|
||||||
private int _debugStopped;
|
|
||||||
|
|
||||||
private readonly ExceptionCallbacks _exceptionCallbacks;
|
private readonly ExceptionCallbacks _exceptionCallbacks;
|
||||||
|
|
||||||
|
@ -83,6 +93,7 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
_shadowContext = new HvExecutionContextShadow();
|
_shadowContext = new HvExecutionContextShadow();
|
||||||
_impl = _shadowContext;
|
_impl = _shadowContext;
|
||||||
_exceptionCallbacks = exceptionCallbacks;
|
_exceptionCallbacks = exceptionCallbacks;
|
||||||
|
StepBarrier = new(2);
|
||||||
Running = true;
|
Running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,39 +144,31 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void DebugStop()
|
public void RequestDebugStep()
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref _debugStopped, 1, 0) == 0)
|
Interlocked.Exchange(ref _shouldStep, 1);
|
||||||
{
|
|
||||||
RequestInterrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool DebugStep()
|
|
||||||
{
|
|
||||||
if (_debugStopped != 1)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_shouldStep = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void DebugContinue()
|
|
||||||
{
|
|
||||||
Interlocked.CompareExchange(ref _debugStopped, 0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ulong DebugPc
|
public ulong DebugPc
|
||||||
{
|
{
|
||||||
get => _impl.ElrEl1;
|
get => Pc;
|
||||||
set => _impl.ElrEl1 = value;
|
set
|
||||||
|
{
|
||||||
|
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
||||||
|
if (currentEl == (uint)ExceptionLevel.EL1h)
|
||||||
|
{
|
||||||
|
_impl.ElrEl1 = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_impl.Pc = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Barrier StepBarrier { get; private set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void StopRunning()
|
public void StopRunning()
|
||||||
{
|
{
|
||||||
|
@ -183,13 +186,17 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
if (Interlocked.CompareExchange(ref _shouldStep, 0, 1) == 1)
|
if (Interlocked.CompareExchange(ref _shouldStep, 0, 1) == 1)
|
||||||
{
|
{
|
||||||
uint currentEl = Pstate & ~(0xfffffff0);
|
uint currentEl = Pstate & ~((uint)ExceptionLevel.PstateMask);
|
||||||
if (currentEl == 0b0101)
|
if (currentEl == (uint)ExceptionLevel.EL1h)
|
||||||
{
|
{
|
||||||
HvApi.hv_vcpu_get_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
|
HvApi.hv_vcpu_get_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, out ulong spsr).ThrowOnError();
|
||||||
spsr |= (1 << 21);
|
spsr |= (1 << 21);
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, spsr);
|
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.SPSR_EL1, spsr);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Pstate |= (1 << 21);
|
||||||
|
}
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.MDSCR_EL1, 1);
|
HvApi.hv_vcpu_set_sys_reg(vcpu.Handle, HvSysReg.MDSCR_EL1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +213,6 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
{
|
{
|
||||||
throw new Exception($"Unhandled exception from guest kernel with ESR 0x{hvEsr:X} ({hvEc}).");
|
throw new Exception($"Unhandled exception from guest kernel with ESR 0x{hvEsr:X} ({hvEc}).");
|
||||||
}
|
}
|
||||||
|
|
||||||
address = SynchronousException(memoryManager, ref vcpu);
|
address = SynchronousException(memoryManager, ref vcpu);
|
||||||
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
HvApi.hv_vcpu_set_reg(vcpu.Handle, HvReg.PC, address).ThrowOnError();
|
||||||
}
|
}
|
||||||
|
@ -266,13 +272,14 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, spsr).ThrowOnError();
|
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.SPSR_EL1, spsr).ThrowOnError();
|
||||||
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.MDSCR_EL1, 0);
|
HvApi.hv_vcpu_set_sys_reg(vcpuHandle, HvSysReg.MDSCR_EL1, 0);
|
||||||
ReturnToPool(vcpu);
|
ReturnToPool(vcpu);
|
||||||
|
StepBarrier.SignalAndWait();
|
||||||
|
StepBarrier.SignalAndWait();
|
||||||
InterruptHandler();
|
InterruptHandler();
|
||||||
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
||||||
break;
|
break;
|
||||||
case ExceptionClass.BrkAarch64:
|
case ExceptionClass.BrkAarch64:
|
||||||
ReturnToPool(vcpu);
|
ReturnToPool(vcpu);
|
||||||
BreakHandler(elr, (ushort)esr);
|
BreakHandler(elr, (ushort)esr);
|
||||||
InterruptHandler();
|
|
||||||
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
vcpu = RentFromPool(memoryManager.AddressSpace, vcpu);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -138,6 +138,7 @@ namespace Ryujinx.Cpu.AppleHv
|
||||||
|
|
||||||
private readonly ulong _vcpu;
|
private readonly ulong _vcpu;
|
||||||
private int _interruptRequested;
|
private int _interruptRequested;
|
||||||
|
private int _breakRequested;
|
||||||
|
|
||||||
public HvExecutionContextVcpu(ulong vcpu)
|
public HvExecutionContextVcpu(ulong vcpu)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu
|
namespace Ryujinx.Cpu
|
||||||
{
|
{
|
||||||
|
@ -115,10 +116,9 @@ namespace Ryujinx.Cpu
|
||||||
void StopRunning();
|
void StopRunning();
|
||||||
|
|
||||||
// TODO: comments
|
// TODO: comments
|
||||||
void DebugStop();
|
void RequestDebugStep();
|
||||||
bool DebugStep();
|
|
||||||
void DebugContinue();
|
|
||||||
|
|
||||||
ulong DebugPc { get; set; }
|
ulong DebugPc { get; set; }
|
||||||
|
Barrier StepBarrier { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using System.Threading;
|
||||||
|
using ExecutionContext = ARMeilleure.State.ExecutionContext;
|
||||||
|
|
||||||
namespace Ryujinx.Cpu.Jit
|
namespace Ryujinx.Cpu.Jit
|
||||||
{
|
{
|
||||||
|
@ -117,13 +119,7 @@ namespace Ryujinx.Cpu.Jit
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void DebugStop() => _impl.DebugStop();
|
public void RequestDebugStep() => _impl.RequestDebugStep();
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public bool DebugStep() => _impl.DebugStep();
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void DebugContinue() => _impl.DebugContinue();
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public ulong DebugPc
|
public ulong DebugPc
|
||||||
|
@ -132,6 +128,9 @@ namespace Ryujinx.Cpu.Jit
|
||||||
set => _impl.DebugPc = value;
|
set => _impl.DebugPc = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public Barrier StepBarrier => _impl.StepBarrier;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void StopRunning()
|
public void StopRunning()
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace Ryujinx.HLE.Debugger
|
||||||
private IVirtualMemoryManager GetMemory() => Device.System.DebugGetApplicationProcess().CpuMemory;
|
private IVirtualMemoryManager GetMemory() => Device.System.DebugGetApplicationProcess().CpuMemory;
|
||||||
private void InvalidateCacheRegion(ulong address, ulong size) =>
|
private void InvalidateCacheRegion(ulong address, ulong size) =>
|
||||||
Device.System.DebugGetApplicationProcess().InvalidateCacheRegion(address, size);
|
Device.System.DebugGetApplicationProcess().InvalidateCacheRegion(address, size);
|
||||||
|
private KernelContext KernelContext => Device.System.KernelContext;
|
||||||
|
|
||||||
const int GdbRegisterCount = 68;
|
const int GdbRegisterCount = 68;
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ namespace Ryujinx.HLE.Debugger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GdbReadRegister(Ryujinx.Cpu.IExecutionContext state, int gdbRegId)
|
private string GdbReadRegister(IExecutionContext state, int gdbRegId)
|
||||||
{
|
{
|
||||||
switch (gdbRegId)
|
switch (gdbRegId)
|
||||||
{
|
{
|
||||||
|
@ -724,13 +725,32 @@ namespace Ryujinx.HLE.Debugger
|
||||||
|
|
||||||
public void ThreadBreak(IExecutionContext ctx, ulong address, int imm)
|
public void ThreadBreak(IExecutionContext ctx, ulong address, int imm)
|
||||||
{
|
{
|
||||||
KThread thread = GetThread(ctx.ThreadUid);
|
|
||||||
|
|
||||||
thread.DebugStop();
|
|
||||||
|
|
||||||
Logger.Notice.Print(LogClass.GdbStub, $"Break hit on thread {ctx.ThreadUid} at pc {address:x016}");
|
Logger.Notice.Print(LogClass.GdbStub, $"Break hit on thread {ctx.ThreadUid} at pc {address:x016}");
|
||||||
|
|
||||||
Messages.Add(new ThreadBreakMessage(ctx, address, imm));
|
Messages.Add(new ThreadBreakMessage(ctx, address, imm));
|
||||||
|
|
||||||
|
KThread currentThread = GetThread(ctx.ThreadUid);
|
||||||
|
|
||||||
|
if (currentThread.Context.Running &&
|
||||||
|
currentThread.Owner != null &&
|
||||||
|
currentThread.GetUserDisableCount() != 0 &&
|
||||||
|
currentThread.Owner.PinnedThreads[currentThread.CurrentCore] == null)
|
||||||
|
{
|
||||||
|
KernelContext.CriticalSection.Enter();
|
||||||
|
|
||||||
|
currentThread.Owner.PinThread(currentThread);
|
||||||
|
|
||||||
|
currentThread.SetUserInterruptFlag();
|
||||||
|
|
||||||
|
KernelContext.CriticalSection.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentThread.IsSchedulable)
|
||||||
|
{
|
||||||
|
KernelContext.Schedulers[currentThread.CurrentCore].Schedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentThread.HandlePostSyscall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -749,14 +749,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
KThread currentThread = KernelStatic.GetCurrentThread();
|
KThread currentThread = KernelStatic.GetCurrentThread();
|
||||||
|
|
||||||
if (currentThread.GetDebugState() != DebugState.Running)
|
|
||||||
{
|
|
||||||
KernelContext.CriticalSection.Enter();
|
|
||||||
currentThread.Suspend(ThreadSchedState.ThreadPauseFlag);
|
|
||||||
currentThread.DebugHalt.Set();
|
|
||||||
KernelContext.CriticalSection.Leave();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentThread.Context.Running &&
|
if (currentThread.Context.Running &&
|
||||||
currentThread.Owner != null &&
|
currentThread.Owner != null &&
|
||||||
currentThread.GetUserDisableCount() != 0 &&
|
currentThread.GetUserDisableCount() != 0 &&
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using Ryujinx.Cpu;
|
using Ryujinx.Cpu;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel.Process
|
namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
private readonly ulong[] _x = new ulong[32];
|
private readonly ulong[] _x = new ulong[32];
|
||||||
|
|
||||||
public ulong DebugPc { get; set; }
|
public ulong DebugPc { get; set; }
|
||||||
|
public Barrier StepBarrier { get; }
|
||||||
|
|
||||||
public ulong GetX(int index) => _x[index];
|
public ulong GetX(int index) => _x[index];
|
||||||
public void SetX(int index, ulong value) => _x[index] = value;
|
public void SetX(int index, ulong value) => _x[index] = value;
|
||||||
|
@ -35,16 +37,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DebugStop()
|
public void RequestDebugStep()
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DebugStep()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DebugContinue()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1443,15 +1443,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
lock (_activityOperationLock)
|
lock (_activityOperationLock)
|
||||||
{
|
{
|
||||||
if (_debugState != (int)DebugState.Stopped
|
if (_debugState != (int)DebugState.Stopped
|
||||||
|| (_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) == 0
|
|| (_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) == 0)
|
||||||
|| !Context.DebugStep())
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugHalt.Reset();
|
Context.RequestDebugStep();
|
||||||
Resume(ThreadSchedState.ThreadPauseFlag);
|
Resume(ThreadSchedState.ThreadPauseFlag);
|
||||||
DebugHalt.WaitOne();
|
Context.StepBarrier.SignalAndWait();
|
||||||
|
Suspend(ThreadSchedState.ThreadPauseFlag);
|
||||||
|
Context.StepBarrier.SignalAndWait();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1467,12 +1468,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) == 0)
|
Suspend(ThreadSchedState.ThreadPauseFlag);
|
||||||
{
|
Context.RequestInterrupt();
|
||||||
Suspend(ThreadSchedState.ThreadPauseFlag);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context.DebugStop();
|
|
||||||
DebugHalt.WaitOne();
|
DebugHalt.WaitOne();
|
||||||
|
|
||||||
_debugState = (int)DebugState.Stopped;
|
_debugState = (int)DebugState.Stopped;
|
||||||
|
@ -1489,8 +1486,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context.DebugContinue();
|
|
||||||
|
|
||||||
if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) != 0)
|
if ((_forcePauseFlags & ThreadSchedState.ThreadPauseFlag) != 0)
|
||||||
{
|
{
|
||||||
Resume(ThreadSchedState.ThreadPauseFlag);
|
Resume(ThreadSchedState.ThreadPauseFlag);
|
||||||
|
|
Loading…
Reference in a new issue