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);
}
}
}
}