aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Memory/Tracking/PhysicalRegion.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Memory/Tracking/PhysicalRegion.cs')
-rw-r--r--Ryujinx.Memory/Tracking/PhysicalRegion.cs97
1 files changed, 97 insertions, 0 deletions
diff --git a/Ryujinx.Memory/Tracking/PhysicalRegion.cs b/Ryujinx.Memory/Tracking/PhysicalRegion.cs
new file mode 100644
index 00000000..683186b1
--- /dev/null
+++ b/Ryujinx.Memory/Tracking/PhysicalRegion.cs
@@ -0,0 +1,97 @@
+using Ryujinx.Memory.Range;
+using System.Collections.Generic;
+
+namespace Ryujinx.Memory.Tracking
+{
+ /// <summary>
+ /// A region of physical memory.
+ /// </summary>
+ class PhysicalRegion : AbstractRegion
+ {
+ public List<VirtualRegion> VirtualParents = new List<VirtualRegion>();
+ public MemoryPermission Protection { get; private set; }
+ public MemoryTracking Tracking;
+
+ public PhysicalRegion(MemoryTracking tracking, ulong address, ulong size) : base(address, size)
+ {
+ Tracking = tracking;
+ Protection = MemoryPermission.ReadAndWrite;
+ }
+
+ public override void Signal(ulong address, ulong size, bool write)
+ {
+ Protection = MemoryPermission.ReadAndWrite;
+ Tracking.ProtectPhysicalRegion(this, MemoryPermission.ReadAndWrite); // Remove our protection immedately.
+ foreach (var parent in VirtualParents)
+ {
+ parent.Signal(address, size, write);
+ }
+ }
+
+ /// <summary>
+ /// Update the protection of this region, based on our parent's requested protection.
+ /// </summary>
+ public void UpdateProtection()
+ {
+ // Re-evaluate protection, and commit to the block.
+
+ lock (Tracking.TrackingLock)
+ {
+ MemoryPermission result = MemoryPermission.ReadAndWrite;
+ foreach (var parent in VirtualParents)
+ {
+ result &= parent.GetRequiredPermission();
+ if (result == 0) break;
+ }
+
+ if (Protection != result)
+ {
+ Protection = result;
+ Tracking.ProtectPhysicalRegion(this, result);
+ }
+ }
+ }
+
+ public override INonOverlappingRange Split(ulong splitAddress)
+ {
+ PhysicalRegion newRegion = new PhysicalRegion(Tracking, splitAddress, EndAddress - splitAddress);
+ Size = splitAddress - Address;
+
+ // The new region inherits all of our parents.
+ newRegion.VirtualParents = new List<VirtualRegion>(VirtualParents);
+ foreach (var parent in VirtualParents)
+ {
+ parent.AddChild(newRegion);
+ }
+
+ return newRegion;
+ }
+
+ /// <summary>
+ /// Remove a parent virtual region from this physical region. Assumes that the tracking lock has been obtained.
+ /// </summary>
+ /// <param name="region">Region to remove</param>
+ /// <returns>True if there are no more parents and we should be removed, false otherwise.</returns>
+ public bool RemoveParent(VirtualRegion region)
+ {
+ VirtualParents.Remove(region);
+ UpdateProtection();
+ if (VirtualParents.Count == 0)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Deletes this physical region if there are no more virtual parents.
+ /// </summary>
+ public void TryDelete()
+ {
+ if (VirtualParents.Count == 0)
+ {
+ Tracking.RemovePhysical(this);
+ }
+ }
+ }
+}