diff options
author | riperiperi <rhy3756547@hotmail.com> | 2021-08-29 20:03:41 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-29 16:03:41 -0300 |
commit | 54adc5f9fb65f4b03bc28da5899d2413a84f66c2 (patch) | |
tree | 050385859cb25e43cb9b2a0af1a7c6b4ed046b39 /Ryujinx.Memory/Tracking/RegionHandle.cs | |
parent | 76e8f9ac87c0164f4f09600dcf8b6a5b4d062bf5 (diff) |
Ensure that all threads wait for a read tracking action to complete. (#2597)
* Lock around tracking action consume + execute. Not particularly fast.
* Lock around preaction registration and use
* Create a lock object
* Nit
Diffstat (limited to 'Ryujinx.Memory/Tracking/RegionHandle.cs')
-rw-r--r-- | Ryujinx.Memory/Tracking/RegionHandle.cs | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs index 2df02f1e..40deba98 100644 --- a/Ryujinx.Memory/Tracking/RegionHandle.cs +++ b/Ryujinx.Memory/Tracking/RegionHandle.cs @@ -35,6 +35,7 @@ namespace Ryujinx.Memory.Tracking 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 readonly List<VirtualRegion> _regions; private readonly MemoryTracking _tracking; @@ -115,17 +116,16 @@ namespace Ryujinx.Memory.Tracking /// <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) { - RegionSignal action = Interlocked.Exchange(ref _preAction, null); - // If this handle was already unmapped (even if just partially), // then we have nothing to do until it is mapped again. // The pre-action should be still consumed to avoid flushing on remap. if (Unmapped) { + Interlocked.Exchange(ref _preAction, null); return; } - if (action != null) + if (_preAction != null) { // Copy the handles list in case it changes when we're out of the lock. if (handleIterable is List<RegionHandle>) @@ -138,7 +138,12 @@ namespace Ryujinx.Memory.Tracking try { - action.Invoke(address, size); + lock (_preActionLock) + { + _preAction?.Invoke(address, size); + + _preAction = null; + } } finally { @@ -220,14 +225,19 @@ namespace Ryujinx.Memory.Tracking { 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(); + } } } } |