Update several methods to use GetNode directly and avoid array allocations
This commit is contained in:
parent
65f2a82b97
commit
c646638680
1 changed files with 76 additions and 53 deletions
|
@ -89,9 +89,12 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
lock (_mappings)
|
lock (_mappings)
|
||||||
{
|
{
|
||||||
RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(address, address + 1UL, default));
|
RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(address, address + 1UL, default));
|
||||||
|
RangeNode<ulong> successorNode;
|
||||||
|
|
||||||
for (; node != null; node = node.Successor)
|
for (; node != null; node = successorNode)
|
||||||
{
|
{
|
||||||
|
successorNode = node.Successor;
|
||||||
|
|
||||||
if (IsMapped(node.Value))
|
if (IsMapped(node.Value))
|
||||||
{
|
{
|
||||||
if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)node.Start, 2))
|
if (!WindowsApi.UnmapViewOfFile2(WindowsApi.CurrentProcessHandle, (IntPtr)node.Start, 2))
|
||||||
|
@ -372,25 +375,25 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
ulong blockAddress = (ulong)owner.Pointer;
|
ulong blockAddress = (ulong)owner.Pointer;
|
||||||
ulong blockEnd = blockAddress + owner.Size;
|
ulong blockEnd = blockAddress + owner.Size;
|
||||||
var overlaps = new RangeNode<ulong>[InitialOverlapsSize];
|
|
||||||
int unmappedCount = 0;
|
int unmappedCount = 0;
|
||||||
|
|
||||||
lock (_mappings)
|
lock (_mappings)
|
||||||
{
|
{
|
||||||
int count = _mappings.GetNodes(address, endAddress, ref overlaps);
|
RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(address, address + 1UL, default));
|
||||||
|
|
||||||
if (count == 0)
|
if (node == null)
|
||||||
{
|
{
|
||||||
// Nothing to coalesce if we no overlaps.
|
// Nothing to coalesce if we have no overlaps.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RangeNode<ulong> predecessor = overlaps[0].Predecessor;
|
RangeNode<ulong> predecessor = node.Predecessor;
|
||||||
RangeNode<ulong> successor = overlaps[count - 1].Successor;
|
RangeNode<ulong> successor = null;
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
for (; node != null; node = successor)
|
||||||
{
|
{
|
||||||
var overlap = overlaps[index];
|
successor = node.Successor;
|
||||||
|
var overlap = node;
|
||||||
|
|
||||||
if (!IsMapped(overlap.Value))
|
if (!IsMapped(overlap.Value))
|
||||||
{
|
{
|
||||||
|
@ -400,6 +403,11 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
_mappings.Remove(overlap);
|
_mappings.Remove(overlap);
|
||||||
unmappedCount++;
|
unmappedCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.End >= endAddress)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (predecessor != null && !IsMapped(predecessor.Value) && predecessor.Start >= blockAddress)
|
if (predecessor != null && !IsMapped(predecessor.Value) && predecessor.Start >= blockAddress)
|
||||||
|
@ -469,46 +477,50 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
ulong reprotectSize = (ulong)size;
|
ulong reprotectSize = (ulong)size;
|
||||||
ulong endAddress = reprotectAddress + reprotectSize;
|
ulong endAddress = reprotectAddress + reprotectSize;
|
||||||
|
|
||||||
var overlaps = new RangeNode<ulong>[InitialOverlapsSize];
|
bool success = true;
|
||||||
int count;
|
|
||||||
|
|
||||||
lock (_mappings)
|
lock (_mappings)
|
||||||
{
|
{
|
||||||
count = _mappings.GetNodes(reprotectAddress, endAddress, ref overlaps);
|
RangeNode<ulong> node = _mappings.GetNode(new RangeNode<ulong>(reprotectAddress, reprotectAddress + 1UL, default));
|
||||||
}
|
RangeNode<ulong> successorNode;
|
||||||
|
|
||||||
bool success = true;
|
for (; node != null; node = successorNode)
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
|
||||||
{
|
|
||||||
var overlap = overlaps[index];
|
|
||||||
|
|
||||||
ulong mappedAddress = overlap.Start;
|
|
||||||
ulong mappedSize = overlap.End - overlap.Start;
|
|
||||||
|
|
||||||
if (mappedAddress < reprotectAddress)
|
|
||||||
{
|
{
|
||||||
ulong delta = reprotectAddress - mappedAddress;
|
successorNode = node.Successor;
|
||||||
mappedAddress = reprotectAddress;
|
var overlap = node;
|
||||||
mappedSize -= delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong mappedEndAddress = mappedAddress + mappedSize;
|
ulong mappedAddress = overlap.Start;
|
||||||
|
ulong mappedSize = overlap.End - overlap.Start;
|
||||||
|
|
||||||
if (mappedEndAddress > endAddress)
|
if (mappedAddress < reprotectAddress)
|
||||||
{
|
|
||||||
ulong delta = mappedEndAddress - endAddress;
|
|
||||||
mappedSize -= delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WindowsApi.VirtualProtect((IntPtr)mappedAddress, (IntPtr)mappedSize, WindowsApi.GetProtection(permission), out _))
|
|
||||||
{
|
|
||||||
if (throwOnError)
|
|
||||||
{
|
{
|
||||||
throw new WindowsApiException("VirtualProtect");
|
ulong delta = reprotectAddress - mappedAddress;
|
||||||
|
mappedAddress = reprotectAddress;
|
||||||
|
mappedSize -= delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
success = false;
|
ulong mappedEndAddress = mappedAddress + mappedSize;
|
||||||
|
|
||||||
|
if (mappedEndAddress > endAddress)
|
||||||
|
{
|
||||||
|
ulong delta = mappedEndAddress - endAddress;
|
||||||
|
mappedSize -= delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WindowsApi.VirtualProtect((IntPtr)mappedAddress, (IntPtr)mappedSize, WindowsApi.GetProtection(permission), out _))
|
||||||
|
{
|
||||||
|
if (throwOnError)
|
||||||
|
{
|
||||||
|
throw new WindowsApiException("VirtualProtect");
|
||||||
|
}
|
||||||
|
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.End >= endAddress)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,26 +577,27 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
private void UpdateProtection(ulong address, ulong size, MemoryPermission permission)
|
private void UpdateProtection(ulong address, ulong size, MemoryPermission permission)
|
||||||
{
|
{
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
var overlaps = new RangeNode<MemoryPermission>[InitialOverlapsSize];
|
|
||||||
int count;
|
|
||||||
|
|
||||||
lock (_protections)
|
lock (_protections)
|
||||||
{
|
{
|
||||||
count = _protections.GetNodes(address, endAddress, ref overlaps);
|
RangeNode<MemoryPermission> node = _protections.GetNode(new RangeNode<MemoryPermission>(address, address + 1UL, default));
|
||||||
|
|
||||||
if (count == 1 &&
|
if (node != null &&
|
||||||
overlaps[0].Start <= address &&
|
node.Start <= address &&
|
||||||
overlaps[0].End >= endAddress &&
|
node.End >= endAddress &&
|
||||||
overlaps[0].Value == permission)
|
node.Value == permission)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RangeNode<MemoryPermission> successorNode;
|
||||||
|
|
||||||
ulong startAddress = address;
|
ulong startAddress = address;
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
for (; node != null; node = successorNode)
|
||||||
{
|
{
|
||||||
var protection = overlaps[index];
|
successorNode = node.Successor;
|
||||||
|
var protection = node;
|
||||||
|
|
||||||
ulong protAddress = protection.Start;
|
ulong protAddress = protection.Start;
|
||||||
ulong protEndAddress = protection.End;
|
ulong protEndAddress = protection.End;
|
||||||
|
@ -616,6 +629,11 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
_protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission));
|
_protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.End >= endAddress)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_protections.Add(new RangeNode<MemoryPermission>(startAddress, endAddress, permission));
|
_protections.Add(new RangeNode<MemoryPermission>(startAddress, endAddress, permission));
|
||||||
|
@ -630,16 +648,16 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
private void RemoveProtection(ulong address, ulong size)
|
private void RemoveProtection(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
var overlaps = new RangeNode<MemoryPermission>[InitialOverlapsSize];
|
|
||||||
int count;
|
|
||||||
|
|
||||||
lock (_protections)
|
lock (_protections)
|
||||||
{
|
{
|
||||||
count = _protections.GetNodes(address, endAddress, ref overlaps);
|
RangeNode<MemoryPermission> node = _protections.GetNode(new RangeNode<MemoryPermission>(address, address + 1UL, default));
|
||||||
|
RangeNode<MemoryPermission> successorNode;
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
for (; node != null; node = successorNode)
|
||||||
{
|
{
|
||||||
var protection = overlaps[index];
|
successorNode = node.Successor;
|
||||||
|
var protection = node;
|
||||||
|
|
||||||
ulong protAddress = protection.Start;
|
ulong protAddress = protection.Start;
|
||||||
ulong protEndAddress = protection.End;
|
ulong protEndAddress = protection.End;
|
||||||
|
@ -656,6 +674,11 @@ namespace Ryujinx.Memory.WindowsShared
|
||||||
{
|
{
|
||||||
_protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission));
|
_protections.Add(new RangeNode<MemoryPermission>(endAddress, protEndAddress, protPermission));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.End >= endAddress)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue