MemoryEhMeilleure.cs
1 using Ryujinx.Common; 2 using Ryujinx.Cpu.Signal; 3 using Ryujinx.Memory; 4 using Ryujinx.Memory.Tracking; 5 using System; 6 using System.Runtime.InteropServices; 7 8 namespace Ryujinx.Cpu 9 { 10 public class MemoryEhMeilleure : IDisposable 11 { 12 public delegate ulong TrackingEventDelegate(ulong address, ulong size, bool write); 13 14 private readonly MemoryTracking _tracking; 15 private readonly TrackingEventDelegate _trackingEvent; 16 17 private readonly ulong _pageSize; 18 19 private readonly ulong _baseAddress; 20 private readonly ulong _mirrorAddress; 21 22 public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking, TrackingEventDelegate trackingEvent = null) 23 { 24 _baseAddress = (ulong)addressSpace.Pointer; 25 26 ulong endAddress = _baseAddress + addressSpace.Size; 27 28 _tracking = tracking; 29 _trackingEvent = trackingEvent ?? VirtualMemoryEvent; 30 31 _pageSize = MemoryBlock.GetPageSize(); 32 33 bool added = NativeSignalHandler.AddTrackedRegion((nuint)_baseAddress, (nuint)endAddress, Marshal.GetFunctionPointerForDelegate(_trackingEvent)); 34 35 if (!added) 36 { 37 throw new InvalidOperationException("Number of allowed tracked regions exceeded."); 38 } 39 40 if (OperatingSystem.IsWindows() && addressSpaceMirror != null) 41 { 42 // Add a tracking event with no signal handler for the mirror on Windows. 43 // The native handler has its own code to check for the partial overlap race when regions are protected by accident, 44 // and when there is no signal handler present. 45 46 _mirrorAddress = (ulong)addressSpaceMirror.Pointer; 47 ulong endAddressMirror = _mirrorAddress + addressSpace.Size; 48 49 bool addedMirror = NativeSignalHandler.AddTrackedRegion((nuint)_mirrorAddress, (nuint)endAddressMirror, IntPtr.Zero); 50 51 if (!addedMirror) 52 { 53 throw new InvalidOperationException("Number of allowed tracked regions exceeded."); 54 } 55 } 56 } 57 58 private ulong VirtualMemoryEvent(ulong address, ulong size, bool write) 59 { 60 ulong pageSize = _pageSize; 61 ulong addressAligned = BitUtils.AlignDown(address, pageSize); 62 ulong endAddressAligned = BitUtils.AlignUp(address + size, pageSize); 63 ulong sizeAligned = endAddressAligned - addressAligned; 64 65 if (_tracking.VirtualMemoryEvent(addressAligned, sizeAligned, write)) 66 { 67 return _baseAddress + address; 68 } 69 70 return 0; 71 } 72 73 public void Dispose() 74 { 75 GC.SuppressFinalize(this); 76 77 NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress); 78 79 if (_mirrorAddress != 0) 80 { 81 NativeSignalHandler.RemoveTrackedRegion((nuint)_mirrorAddress); 82 } 83 } 84 } 85 }