aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Memory/Tracking/RegionHandle.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Memory/Tracking/RegionHandle.cs')
-rw-r--r--Ryujinx.Memory/Tracking/RegionHandle.cs24
1 files changed, 22 insertions, 2 deletions
diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs
index 2e45ef80..2df02f1e 100644
--- a/Ryujinx.Memory/Tracking/RegionHandle.cs
+++ b/Ryujinx.Memory/Tracking/RegionHandle.cs
@@ -1,6 +1,7 @@
using Ryujinx.Memory.Range;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
namespace Ryujinx.Memory.Tracking
@@ -112,7 +113,7 @@ namespace Ryujinx.Memory.Tracking
/// Signal that a memory action occurred within this handle's virtual regions.
/// </summary>
/// <param name="write">Whether the region was written to or read</param>
- internal void Signal(ulong address, ulong size, bool write)
+ internal void Signal(ulong address, ulong size, bool write, ref IList<RegionHandle> handleIterable)
{
RegionSignal action = Interlocked.Exchange(ref _preAction, null);
@@ -124,7 +125,26 @@ namespace Ryujinx.Memory.Tracking
return;
}
- action?.Invoke(address, size);
+ if (action != null)
+ {
+ // Copy the handles list in case it changes when we're out of the lock.
+ if (handleIterable is List<RegionHandle>)
+ {
+ handleIterable = handleIterable.ToArray();
+ }
+
+ // Temporarily release the tracking lock while we're running the action.
+ Monitor.Exit(_tracking.TrackingLock);
+
+ try
+ {
+ action.Invoke(address, size);
+ }
+ finally
+ {
+ Monitor.Enter(_tracking.TrackingLock);
+ }
+ }
if (write)
{