diff options
Diffstat (limited to 'Ryujinx.Cpu/MemoryEhMeilleure.cs')
-rw-r--r-- | Ryujinx.Cpu/MemoryEhMeilleure.cs | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/Ryujinx.Cpu/MemoryEhMeilleure.cs b/Ryujinx.Cpu/MemoryEhMeilleure.cs index a8229581..806ef811 100644 --- a/Ryujinx.Cpu/MemoryEhMeilleure.cs +++ b/Ryujinx.Cpu/MemoryEhMeilleure.cs @@ -6,36 +6,57 @@ using System.Runtime.InteropServices; namespace Ryujinx.Cpu { - class MemoryEhMeilleure : IDisposable + public class MemoryEhMeilleure : IDisposable { private delegate bool TrackingEventDelegate(ulong address, ulong size, bool write, bool precise = false); - private readonly MemoryBlock _addressSpace; private readonly MemoryTracking _tracking; private readonly TrackingEventDelegate _trackingEvent; private readonly ulong _baseAddress; + private readonly ulong _mirrorAddress; - public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryTracking tracking) + public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking) { - _addressSpace = addressSpace; _tracking = tracking; - _baseAddress = (ulong)_addressSpace.Pointer; + _baseAddress = (ulong)addressSpace.Pointer; ulong endAddress = _baseAddress + addressSpace.Size; - _trackingEvent = new TrackingEventDelegate(tracking.VirtualMemoryEventEh); + _trackingEvent = new TrackingEventDelegate(tracking.VirtualMemoryEvent); bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent)); if (!added) { throw new InvalidOperationException("Number of allowed tracked regions exceeded."); } + + if (OperatingSystem.IsWindows()) + { + // Add a tracking event with no signal handler for the mirror on Windows. + // The native handler has its own code to check for the partial overlap race when regions are protected by accident, + // and when there is no signal handler present. + + _mirrorAddress = (ulong)addressSpaceMirror.Pointer; + ulong endAddressMirror = _mirrorAddress + addressSpace.Size; + + bool addedMirror = NativeSignalHandler.AddTrackedRegion((nuint)_mirrorAddress, (nuint)endAddressMirror, IntPtr.Zero); + + if (!addedMirror) + { + throw new InvalidOperationException("Number of allowed tracked regions exceeded."); + } + } } public void Dispose() { NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress); + + if (_mirrorAddress != 0) + { + NativeSignalHandler.RemoveTrackedRegion((nuint)_mirrorAddress); + } } } } |