diff options
Diffstat (limited to 'Ryujinx.Memory/Tracking/MultiRegionHandle.cs')
-rw-r--r-- | Ryujinx.Memory/Tracking/MultiRegionHandle.cs | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/Ryujinx.Memory/Tracking/MultiRegionHandle.cs b/Ryujinx.Memory/Tracking/MultiRegionHandle.cs index 45138ff3..6cbea7f3 100644 --- a/Ryujinx.Memory/Tracking/MultiRegionHandle.cs +++ b/Ryujinx.Memory/Tracking/MultiRegionHandle.cs @@ -25,6 +25,7 @@ namespace Ryujinx.Memory.Tracking private int _sequenceNumber; private BitMap _sequenceNumberBitmap; + private BitMap _dirtyCheckedBitmap; private int _uncheckedHandles; public bool Dirty { get; private set; } = true; @@ -36,6 +37,7 @@ namespace Ryujinx.Memory.Tracking _dirtyBitmap = new ConcurrentBitmap(_handles.Length, true); _sequenceNumberBitmap = new BitMap(_handles.Length); + _dirtyCheckedBitmap = new BitMap(_handles.Length); int i = 0; @@ -246,16 +248,18 @@ namespace Ryujinx.Memory.Tracking } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ParseDirtyBits(long dirtyBits, long mask, int index, long[] seqMasks, ref int baseBit, ref int prevHandle, ref ulong rgStart, ref ulong rgSize, Action<ulong, ulong> modifiedAction) + private void ParseDirtyBits(long dirtyBits, long mask, int index, long[] seqMasks, long[] checkMasks, ref int baseBit, ref int prevHandle, ref ulong rgStart, ref ulong rgSize, Action<ulong, ulong> modifiedAction) { long seqMask = mask & ~seqMasks[index]; + long checkMask = (~dirtyBits) & seqMask; dirtyBits &= seqMask; while (dirtyBits != 0) { int bit = BitOperations.TrailingZeroCount(dirtyBits); + long bitValue = 1L << bit; - dirtyBits &= ~(1L << bit); + dirtyBits &= ~bitValue; int handleIndex = baseBit + bit; @@ -273,11 +277,14 @@ namespace Ryujinx.Memory.Tracking } rgSize += handle.Size; - handle.Reprotect(); + handle.Reprotect(false, (checkMasks[index] & bitValue) == 0); + + checkMasks[index] &= ~bitValue; prevHandle = handleIndex; } + checkMasks[index] |= checkMask; seqMasks[index] |= mask; _uncheckedHandles -= BitOperations.PopCount((ulong)seqMask); @@ -328,6 +335,7 @@ namespace Ryujinx.Memory.Tracking ulong rgSize = 0; long[] seqMasks = _sequenceNumberBitmap.Masks; + long[] checkedMasks = _dirtyCheckedBitmap.Masks; long[] masks = _dirtyBitmap.Masks; int startIndex = startHandle >> ConcurrentBitmap.IntShift; @@ -345,20 +353,20 @@ namespace Ryujinx.Memory.Tracking if (startIndex == endIndex) { - ParseDirtyBits(startValue, startMask & endMask, startIndex, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); + ParseDirtyBits(startValue, startMask & endMask, startIndex, seqMasks, checkedMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); } else { - ParseDirtyBits(startValue, startMask, startIndex, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); + ParseDirtyBits(startValue, startMask, startIndex, seqMasks, checkedMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); for (int i = startIndex + 1; i < endIndex; i++) { - ParseDirtyBits(Volatile.Read(ref masks[i]), -1L, i, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); + ParseDirtyBits(Volatile.Read(ref masks[i]), -1L, i, seqMasks, checkedMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); } long endValue = Volatile.Read(ref masks[endIndex]); - ParseDirtyBits(endValue, endMask, endIndex, seqMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); + ParseDirtyBits(endValue, endMask, endIndex, seqMasks, checkedMasks, ref baseBit, ref prevHandle, ref rgStart, ref rgSize, modifiedAction); } if (rgSize != 0) |