MemoryEhMeilleure.cs 3.0 KB

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