PhysicalRegion.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Ryujinx.Memory.Range;
  2. using System.Collections.Generic;
  3. namespace Ryujinx.Memory.Tracking
  4. {
  5. /// <summary>
  6. /// A region of physical memory.
  7. /// </summary>
  8. class PhysicalRegion : AbstractRegion
  9. {
  10. public List<VirtualRegion> VirtualParents = new List<VirtualRegion>();
  11. public MemoryPermission Protection { get; private set; }
  12. public MemoryTracking Tracking;
  13. public PhysicalRegion(MemoryTracking tracking, ulong address, ulong size) : base(address, size)
  14. {
  15. Tracking = tracking;
  16. Protection = MemoryPermission.ReadAndWrite;
  17. }
  18. public override void Signal(ulong address, ulong size, bool write)
  19. {
  20. Protection = MemoryPermission.ReadAndWrite;
  21. Tracking.ProtectPhysicalRegion(this, MemoryPermission.ReadAndWrite); // Remove our protection immedately.
  22. foreach (var parent in VirtualParents)
  23. {
  24. parent.Signal(address, size, write);
  25. }
  26. }
  27. /// <summary>
  28. /// Update the protection of this region, based on our parent's requested protection.
  29. /// </summary>
  30. public void UpdateProtection()
  31. {
  32. // Re-evaluate protection, and commit to the block.
  33. lock (Tracking.TrackingLock)
  34. {
  35. MemoryPermission result = MemoryPermission.ReadAndWrite;
  36. foreach (var parent in VirtualParents)
  37. {
  38. result &= parent.GetRequiredPermission();
  39. if (result == 0) break;
  40. }
  41. if (Protection != result)
  42. {
  43. Protection = result;
  44. Tracking.ProtectPhysicalRegion(this, result);
  45. }
  46. }
  47. }
  48. public override INonOverlappingRange Split(ulong splitAddress)
  49. {
  50. PhysicalRegion newRegion = new PhysicalRegion(Tracking, splitAddress, EndAddress - splitAddress);
  51. Size = splitAddress - Address;
  52. // The new region inherits all of our parents.
  53. newRegion.VirtualParents = new List<VirtualRegion>(VirtualParents);
  54. foreach (var parent in VirtualParents)
  55. {
  56. parent.AddChild(newRegion);
  57. }
  58. return newRegion;
  59. }
  60. /// <summary>
  61. /// Remove a parent virtual region from this physical region. Assumes that the tracking lock has been obtained.
  62. /// </summary>
  63. /// <param name="region">Region to remove</param>
  64. /// <returns>True if there are no more parents and we should be removed, false otherwise.</returns>
  65. public bool RemoveParent(VirtualRegion region)
  66. {
  67. VirtualParents.Remove(region);
  68. UpdateProtection();
  69. if (VirtualParents.Count == 0)
  70. {
  71. return true;
  72. }
  73. return false;
  74. }
  75. /// <summary>
  76. /// Deletes this physical region if there are no more virtual parents.
  77. /// </summary>
  78. public void TryDelete()
  79. {
  80. if (VirtualParents.Count == 0)
  81. {
  82. Tracking.RemovePhysical(this);
  83. }
  84. }
  85. }
  86. }