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.cs84
1 files changed, 77 insertions, 7 deletions
diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs
index 14c6de2c..363bedef 100644
--- a/Ryujinx.Memory/Tracking/RegionHandle.cs
+++ b/Ryujinx.Memory/Tracking/RegionHandle.cs
@@ -1,5 +1,4 @@
-using Ryujinx.Memory.Range;
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -10,7 +9,7 @@ namespace Ryujinx.Memory.Tracking
/// A tracking handle for a given region of virtual memory. The Dirty flag is updated whenever any changes are made,
/// and an action can be performed when the region is read to or written from.
/// </summary>
- public class RegionHandle : IRegionHandle, IRange
+ public class RegionHandle : IRegionHandle
{
/// <summary>
/// If more than this number of checks have been performed on a dirty flag since its last reprotect,
@@ -23,7 +22,20 @@ namespace Ryujinx.Memory.Tracking
/// </summary>
private static int VolatileThreshold = 5;
- public bool Dirty { get; private set; }
+ public bool Dirty
+ {
+ get
+ {
+ return Bitmap.IsSet(DirtyBit);
+ }
+ protected set
+ {
+ Bitmap.Set(DirtyBit, value);
+ }
+ }
+
+ internal int SequenceNumber { get; set; }
+
public bool Unmapped { get; private set; }
public ulong Address { get; }
@@ -31,7 +43,6 @@ namespace Ryujinx.Memory.Tracking
public ulong EndAddress { get; }
internal IMultiRegionHandle Parent { get; set; }
- internal int SequenceNumber { get; set; }
private event Action _onDirty;
@@ -68,6 +79,39 @@ namespace Ryujinx.Memory.Tracking
internal RegionSignal PreAction => _preAction;
+ internal ConcurrentBitmap Bitmap;
+ internal int DirtyBit;
+
+ /// <summary>
+ /// Create a new bitmap backed region handle. The handle is registered with the given tracking object,
+ /// and will be notified of any changes to the specified region.
+ /// </summary>
+ /// <param name="tracking">Tracking object for the target memory block</param>
+ /// <param name="address">Virtual address of the region to track</param>
+ /// <param name="size">Size of the region to track</param>
+ /// <param name="bitmap">The bitmap the dirty flag for this handle is stored in</param>
+ /// <param name="bit">The bit index representing the dirty flag for this handle</param>
+ /// <param name="mapped">True if the region handle starts mapped</param>
+ internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, ConcurrentBitmap bitmap, int bit, bool mapped = true)
+ {
+ Bitmap = bitmap;
+ DirtyBit = bit;
+
+ Dirty = mapped;
+
+ Unmapped = !mapped;
+ Address = address;
+ Size = size;
+ EndAddress = address + size;
+
+ _tracking = tracking;
+ _regions = tracking.GetVirtualRegionsForHandle(address, size);
+ foreach (var region in _regions)
+ {
+ region.Handles.Add(this);
+ }
+ }
+
/// <summary>
/// Create a new region handle. The handle is registered with the given tracking object,
/// and will be notified of any changes to the specified region.
@@ -78,7 +122,8 @@ namespace Ryujinx.Memory.Tracking
/// <param name="mapped">True if the region handle starts mapped</param>
internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, bool mapped = true)
{
- Dirty = mapped;
+ Bitmap = new ConcurrentBitmap(1, mapped);
+
Unmapped = !mapped;
Address = address;
Size = size;
@@ -93,6 +138,29 @@ namespace Ryujinx.Memory.Tracking
}
/// <summary>
+ /// Replace the bitmap and bit index used to track dirty state.
+ /// </summary>
+ /// <remarks>
+ /// The tracking lock should be held when this is called, to ensure neither bitmap is modified.
+ /// </remarks>
+ /// <param name="bitmap">The bitmap the dirty flag for this handle is stored in</param>
+ /// <param name="bit">The bit index representing the dirty flag for this handle</param>
+ internal void ReplaceBitmap(ConcurrentBitmap bitmap, int bit)
+ {
+ // Assumes the tracking lock is held, so nothing else can signal right now.
+
+ var oldBitmap = Bitmap;
+ var oldBit = DirtyBit;
+
+ bitmap.Set(bit, Dirty);
+
+ Bitmap = bitmap;
+ DirtyBit = bit;
+
+ Dirty |= oldBitmap.IsSet(oldBit);
+ }
+
+ /// <summary>
/// Clear the volatile state of this handle.
/// </summary>
private void ClearVolatile()
@@ -108,7 +176,7 @@ namespace Ryujinx.Memory.Tracking
public bool DirtyOrVolatile()
{
_checkCount++;
- return Dirty || _volatile;
+ return _volatile || Dirty;
}
/// <summary>
@@ -195,6 +263,8 @@ namespace Ryujinx.Memory.Tracking
/// </summary>
public void ForceDirty()
{
+ _checkCount++;
+
Dirty = true;
}