ryujinx/src/Ryujinx.Memory/Tracking/VirtualRegion.cs
TSRBerry 0a75b73fa4
[Ryujinx.Memory] Address dotnet-format issues (#5386)
* dotnet format style --severity info

Some changes were manually reverted.

* dotnet format analyzers --serverity info

Some changes have been minimally adapted.

* Silence dotnet format IDE0059 warnings

* Address or silence dotnet format IDE1006 warnings

* Address dotnet format CA1816 warnings

* Address or silence dotnet format CA1069 warnings

* Address remaining dotnet format analyzer warnings

* Address review comments

* Address most dotnet format whitespace warnings

* Apply dotnet format whitespace formatting

A few of them have been manually reverted and the corresponding warning was silenced

* Format if-blocks correctly

* Another rebase, another dotnet format run

* Run dotnet format after rebase and remove unused usings

- analyzers
- style
- whitespace

* Add comments to disabled warnings

* Simplify properties and array initialization, Use const when possible, Remove trailing commas

* Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas"

This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e.

* dotnet format whitespace after rebase

* Address review feedback

* Assign Decommit to ReplacePlaceholder

* Run final dotnet format pass

* Organize imports again

* Add trailing commas

* Add missing newline
2023-06-28 18:34:00 +02:00

147 lines
4.7 KiB
C#

using Ryujinx.Memory.Range;
using System.Collections.Generic;
namespace Ryujinx.Memory.Tracking
{
/// <summary>
/// A region of virtual memory.
/// </summary>
class VirtualRegion : AbstractRegion
{
public List<RegionHandle> Handles = new();
private readonly MemoryTracking _tracking;
private MemoryPermission _lastPermission;
public VirtualRegion(MemoryTracking tracking, ulong address, ulong size, MemoryPermission lastPermission = MemoryPermission.Invalid) : base(address, size)
{
_lastPermission = lastPermission;
_tracking = tracking;
}
/// <inheritdoc/>
public override void Signal(ulong address, ulong size, bool write, int? exemptId)
{
IList<RegionHandle> handles = Handles;
for (int i = 0; i < handles.Count; i++)
{
if (exemptId == null || handles[i].Id != exemptId.Value)
{
handles[i].Signal(address, size, write, ref handles);
}
}
UpdateProtection();
}
/// <inheritdoc/>
public override void SignalPrecise(ulong address, ulong size, bool write, int? exemptId)
{
IList<RegionHandle> handles = Handles;
bool allPrecise = true;
for (int i = 0; i < handles.Count; i++)
{
if (exemptId == null || handles[i].Id != exemptId.Value)
{
allPrecise &= handles[i].SignalPrecise(address, size, write, ref handles);
}
}
// Only update protection if a regular signal handler was called.
// This allows precise actions to skip reprotection costs if they want (they can still do it manually).
if (!allPrecise)
{
UpdateProtection();
}
}
/// <summary>
/// Signal that this region has been mapped or unmapped.
/// </summary>
/// <param name="mapped">True if the region has been mapped, false if unmapped</param>
public void SignalMappingChanged(bool mapped)
{
_lastPermission = MemoryPermission.Invalid;
foreach (RegionHandle handle in Handles)
{
handle.SignalMappingChanged(mapped);
}
}
/// <summary>
/// Gets the strictest permission that the child handles demand. Assumes that the tracking lock has been obtained.
/// </summary>
/// <returns>Protection level that this region demands</returns>
public MemoryPermission GetRequiredPermission()
{
// Start with Read/Write, each handle can strip off permissions as necessary.
// Assumes the tracking lock has already been obtained.
MemoryPermission result = MemoryPermission.ReadAndWrite;
foreach (var handle in Handles)
{
result &= handle.RequiredPermission;
if (result == 0)
{
return result;
}
}
return result;
}
/// <summary>
/// Updates the protection for this virtual region.
/// </summary>
public bool UpdateProtection()
{
MemoryPermission permission = GetRequiredPermission();
if (_lastPermission != permission)
{
_tracking.ProtectVirtualRegion(this, permission);
_lastPermission = permission;
return true;
}
return false;
}
/// <summary>
/// Removes a handle from this virtual region. If there are no handles left, this virtual region is removed.
/// </summary>
/// <param name="handle">Handle to remove</param>
public void RemoveHandle(RegionHandle handle)
{
lock (_tracking.TrackingLock)
{
Handles.Remove(handle);
UpdateProtection();
if (Handles.Count == 0)
{
_tracking.RemoveVirtual(this);
}
}
}
public override INonOverlappingRange Split(ulong splitAddress)
{
VirtualRegion newRegion = new(_tracking, splitAddress, EndAddress - splitAddress, _lastPermission);
Size = splitAddress - Address;
// The new region inherits all of our parents.
newRegion.Handles = new List<RegionHandle>(Handles);
foreach (var parent in Handles)
{
parent.AddChild(newRegion);
}
return newRegion;
}
}
}