using Ryujinx.Memory.Range; using System.Collections.Generic; namespace Ryujinx.Memory.Tracking { /// /// A region of physical memory. /// class PhysicalRegion : AbstractRegion { public List VirtualParents = new List(); 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); } } /// /// Update the protection of this region, based on our parent's requested protection. /// 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(VirtualParents); foreach (var parent in VirtualParents) { parent.AddChild(newRegion); } return newRegion; } /// /// Remove a parent virtual region from this physical region. Assumes that the tracking lock has been obtained. /// /// Region to remove /// True if there are no more parents and we should be removed, false otherwise. public bool RemoveParent(VirtualRegion region) { VirtualParents.Remove(region); UpdateProtection(); if (VirtualParents.Count == 0) { return true; } return false; } /// /// Deletes this physical region if there are no more virtual parents. /// public void TryDelete() { if (VirtualParents.Count == 0) { Tracking.RemovePhysical(this); } } } }