|
@@ -35,6 +35,7 @@ namespace Ryujinx.Memory.Tracking
|
|
|
|
|
|
|
|
private event Action _onDirty;
|
|
private event Action _onDirty;
|
|
|
|
|
|
|
|
|
|
+ private object _preActionLock = new object();
|
|
|
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
|
private RegionSignal _preAction; // Action to perform before a read or write. This will block the memory access.
|
|
|
private readonly List<VirtualRegion> _regions;
|
|
private readonly List<VirtualRegion> _regions;
|
|
|
private readonly MemoryTracking _tracking;
|
|
private readonly MemoryTracking _tracking;
|
|
@@ -115,17 +116,16 @@ namespace Ryujinx.Memory.Tracking
|
|
|
/// <param name="write">Whether the region was written to or read</param>
|
|
/// <param name="write">Whether the region was written to or read</param>
|
|
|
internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
|
|
internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
|
|
|
{
|
|
{
|
|
|
- RegionSignal action = Interlocked.Exchange(ref _preAction, null);
|
|
|
|
|
-
|
|
|
|
|
// If this handle was already unmapped (even if just partially),
|
|
// If this handle was already unmapped (even if just partially),
|
|
|
// then we have nothing to do until it is mapped again.
|
|
// then we have nothing to do until it is mapped again.
|
|
|
// The pre-action should be still consumed to avoid flushing on remap.
|
|
// The pre-action should be still consumed to avoid flushing on remap.
|
|
|
if (Unmapped)
|
|
if (Unmapped)
|
|
|
{
|
|
{
|
|
|
|
|
+ Interlocked.Exchange(ref _preAction, null);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (action != null)
|
|
|
|
|
|
|
+ if (_preAction != null)
|
|
|
{
|
|
{
|
|
|
// Copy the handles list in case it changes when we're out of the lock.
|
|
// Copy the handles list in case it changes when we're out of the lock.
|
|
|
if (handleIterable is List<RegionHandle>)
|
|
if (handleIterable is List<RegionHandle>)
|
|
@@ -138,7 +138,12 @@ namespace Ryujinx.Memory.Tracking
|
|
|
|
|
|
|
|
try
|
|
try
|
|
|
{
|
|
{
|
|
|
- action.Invoke(address, size);
|
|
|
|
|
|
|
+ lock (_preActionLock)
|
|
|
|
|
+ {
|
|
|
|
|
+ _preAction?.Invoke(address, size);
|
|
|
|
|
+
|
|
|
|
|
+ _preAction = null;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
finally
|
|
finally
|
|
|
{
|
|
{
|
|
@@ -220,14 +225,19 @@ namespace Ryujinx.Memory.Tracking
|
|
|
{
|
|
{
|
|
|
ClearVolatile();
|
|
ClearVolatile();
|
|
|
|
|
|
|
|
- RegionSignal lastAction = Interlocked.Exchange(ref _preAction, action);
|
|
|
|
|
- if (lastAction == null && action != lastAction)
|
|
|
|
|
|
|
+ lock (_preActionLock)
|
|
|
{
|
|
{
|
|
|
- lock (_tracking.TrackingLock)
|
|
|
|
|
|
|
+ RegionSignal lastAction = _preAction;
|
|
|
|
|
+ _preAction = action;
|
|
|
|
|
+
|
|
|
|
|
+ if (lastAction == null && action != lastAction)
|
|
|
{
|
|
{
|
|
|
- foreach (VirtualRegion region in _regions)
|
|
|
|
|
|
|
+ lock (_tracking.TrackingLock)
|
|
|
{
|
|
{
|
|
|
- region.UpdateProtection();
|
|
|
|
|
|
|
+ foreach (VirtualRegion region in _regions)
|
|
|
|
|
+ {
|
|
|
|
|
+ region.UpdateProtection();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|