aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Memory/Tracking
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Memory/Tracking')
-rw-r--r--Ryujinx.Memory/Tracking/MemoryTracking.cs28
-rw-r--r--Ryujinx.Memory/Tracking/RegionHandle.cs24
-rw-r--r--Ryujinx.Memory/Tracking/VirtualRegion.cs6
3 files changed, 41 insertions, 17 deletions
diff --git a/Ryujinx.Memory/Tracking/MemoryTracking.cs b/Ryujinx.Memory/Tracking/MemoryTracking.cs
index aafb418d..ed3d7e38 100644
--- a/Ryujinx.Memory/Tracking/MemoryTracking.cs
+++ b/Ryujinx.Memory/Tracking/MemoryTracking.cs
@@ -1,4 +1,6 @@
-using Ryujinx.Memory.Range;
+using Ryujinx.Common.Pools;
+using Ryujinx.Memory.Range;
+using System;
using System.Collections.Generic;
namespace Ryujinx.Memory.Tracking
@@ -14,9 +16,6 @@ namespace Ryujinx.Memory.Tracking
// Only use these from within the lock.
private readonly NonOverlappingRangeList<VirtualRegion> _virtualRegions;
- // Only use these from within the lock.
- private readonly VirtualRegion[] _virtualResults = new VirtualRegion[10];
-
private readonly int _pageSize;
/// <summary>
@@ -62,12 +61,13 @@ namespace Ryujinx.Memory.Tracking
lock (TrackingLock)
{
- var results = _virtualResults;
- int count = _virtualRegions.FindOverlapsNonOverlapping(va, size, ref results);
+ ref var overlaps = ref ThreadStaticArray<VirtualRegion>.Get();
+
+ int count = _virtualRegions.FindOverlapsNonOverlapping(va, size, ref overlaps);
for (int i = 0; i < count; i++)
{
- VirtualRegion region = results[i];
+ VirtualRegion region = overlaps[i];
// If the region has been fully remapped, signal that it has been mapped again.
bool remapped = _memoryManager.IsRangeMapped(region.Address, region.Size);
@@ -94,12 +94,13 @@ namespace Ryujinx.Memory.Tracking
lock (TrackingLock)
{
- var results = _virtualResults;
- int count = _virtualRegions.FindOverlapsNonOverlapping(va, size, ref results);
+ ref var overlaps = ref ThreadStaticArray<VirtualRegion>.Get();
+
+ int count = _virtualRegions.FindOverlapsNonOverlapping(va, size, ref overlaps);
for (int i = 0; i < count; i++)
{
- VirtualRegion region = results[i];
+ VirtualRegion region = overlaps[i];
region.SignalMappingChanged(false);
}
@@ -201,8 +202,9 @@ namespace Ryujinx.Memory.Tracking
lock (TrackingLock)
{
- var results = _virtualResults;
- int count = _virtualRegions.FindOverlapsNonOverlapping(address, size, ref results);
+ ref var overlaps = ref ThreadStaticArray<VirtualRegion>.Get();
+
+ int count = _virtualRegions.FindOverlapsNonOverlapping(address, size, ref overlaps);
if (count == 0)
{
@@ -221,7 +223,7 @@ namespace Ryujinx.Memory.Tracking
for (int i = 0; i < count; i++)
{
- VirtualRegion region = results[i];
+ VirtualRegion region = overlaps[i];
region.Signal(address, size, write);
}
}
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)
{
diff --git a/Ryujinx.Memory/Tracking/VirtualRegion.cs b/Ryujinx.Memory/Tracking/VirtualRegion.cs
index e758f38e..40f56351 100644
--- a/Ryujinx.Memory/Tracking/VirtualRegion.cs
+++ b/Ryujinx.Memory/Tracking/VirtualRegion.cs
@@ -21,9 +21,11 @@ namespace Ryujinx.Memory.Tracking
public override void Signal(ulong address, ulong size, bool write)
{
- foreach (var handle in Handles)
+ IList<RegionHandle> handles = Handles;
+
+ for (int i = 0; i < handles.Count; i++)
{
- handle.Signal(address, size, write);
+ handles[i].Signal(address, size, write, ref handles);
}
UpdateProtection();