| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- using Ryujinx.Common;
- using Ryujinx.Cpu.Signal;
- using Ryujinx.Memory;
- using Ryujinx.Memory.Tracking;
- using System;
- using System.Runtime.InteropServices;
- namespace Ryujinx.Cpu
- {
- public class MemoryEhMeilleure : IDisposable
- {
- public delegate ulong TrackingEventDelegate(ulong address, ulong size, bool write);
- private readonly MemoryTracking _tracking;
- private readonly TrackingEventDelegate _trackingEvent;
- private readonly ulong _pageSize;
- private readonly ulong _baseAddress;
- private readonly ulong _mirrorAddress;
- public MemoryEhMeilleure(MemoryBlock addressSpace, MemoryBlock addressSpaceMirror, MemoryTracking tracking, TrackingEventDelegate trackingEvent = null)
- {
- _baseAddress = (ulong)addressSpace.Pointer;
- ulong endAddress = _baseAddress + addressSpace.Size;
- _tracking = tracking;
- _trackingEvent = trackingEvent ?? VirtualMemoryEvent;
- _pageSize = MemoryBlock.GetPageSize();
- 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() && addressSpaceMirror != null)
- {
- // 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.");
- }
- }
- }
- private ulong VirtualMemoryEvent(ulong address, ulong size, bool write)
- {
- ulong pageSize = _pageSize;
- ulong addressAligned = BitUtils.AlignDown(address, pageSize);
- ulong endAddressAligned = BitUtils.AlignUp(address + size, pageSize);
- ulong sizeAligned = endAddressAligned - addressAligned;
- if (_tracking.VirtualMemoryEvent(addressAligned, sizeAligned, write))
- {
- return _baseAddress + address;
- }
- return 0;
- }
- public void Dispose()
- {
- GC.SuppressFinalize(this);
- NativeSignalHandler.RemoveTrackedRegion((nuint)_baseAddress);
- if (_mirrorAddress != 0)
- {
- NativeSignalHandler.RemoveTrackedRegion((nuint)_mirrorAddress);
- }
- }
- }
- }
|