diff options
Diffstat (limited to 'Ryujinx.Memory/Tracking/RegionHandle.cs')
-rw-r--r-- | Ryujinx.Memory/Tracking/RegionHandle.cs | 84 |
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; } |