mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-25 20:28:48 +08:00
fix(memory): reserve only large regions (#608)
* fix(memory): reserve only large regions * Potential fix for pull request finding
This commit is contained in:
@@ -238,7 +238,15 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
|
|||||||
var alignedSize = (size + 0xFFF) & ~0xFFFUL;
|
var alignedSize = (size + 0xFFF) & ~0xFFFUL;
|
||||||
var protection = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
var protection = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||||
var hostProtection = executable ? HostPageProtection.ReadWriteExecute : HostPageProtection.ReadWrite;
|
var hostProtection = executable ? HostPageProtection.ReadWriteExecute : HostPageProtection.ReadWrite;
|
||||||
var result = _hostMemory.Allocate(desiredAddress, alignedSize, hostProtection);
|
|
||||||
|
// Reserve address space only for very large non-executable regions; commit is done lazily later.
|
||||||
|
var reservedOnly = !executable &&
|
||||||
|
alignedSize >= LargeDataReserveThreshold &&
|
||||||
|
alignedSize > FullCommitRegionLimit;
|
||||||
|
|
||||||
|
var result = reservedOnly
|
||||||
|
? _hostMemory.Reserve(desiredAddress, alignedSize, HostPageProtection.ReadWrite)
|
||||||
|
: _hostMemory.Allocate(desiredAddress, alignedSize, hostProtection);
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -252,6 +260,8 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var state = reservedOnly ? ReserveRegion(actualAddress, alignedSize) : "n/a";
|
||||||
|
|
||||||
_gate.EnterWriteLock();
|
_gate.EnterWriteLock();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -260,7 +270,7 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
|
|||||||
VirtualAddress = actualAddress,
|
VirtualAddress = actualAddress,
|
||||||
Size = alignedSize,
|
Size = alignedSize,
|
||||||
IsExecutable = executable,
|
IsExecutable = executable,
|
||||||
IsReservedOnly = false,
|
IsReservedOnly = reservedOnly,
|
||||||
Protection = protection
|
Protection = protection
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -269,6 +279,7 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
|
|||||||
_gate.ExitWriteLock();
|
_gate.ExitWriteLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var allocationKind = executable ? "executable memory" : "data memory";
|
var allocationKind = executable ? "executable memory" : "data memory";
|
||||||
TraceVmem($"Allocated exact {allocationKind}: 0x{actualAddress:X16} - 0x{actualAddress + alignedSize:X16} ({alignedSize} bytes)");
|
TraceVmem($"Allocated exact {allocationKind}: 0x{actualAddress:X16} - 0x{actualAddress + alignedSize:X16} ({alignedSize} bytes)");
|
||||||
return true;
|
return true;
|
||||||
@@ -361,44 +372,7 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
|
|||||||
|
|
||||||
var actualAddress = result;
|
var actualAddress = result;
|
||||||
|
|
||||||
var lazyPrimeState = "n/a";
|
var lazyPrimeState = reservedOnly ? ReserveRegion(actualAddress, alignedSize) : "n/a";
|
||||||
if (reservedOnly)
|
|
||||||
{
|
|
||||||
var primeBytes = Math.Min(alignedSize, LazyReservePrimeBytes);
|
|
||||||
if (primeBytes != 0)
|
|
||||||
{
|
|
||||||
ulong committedBytes = 0;
|
|
||||||
while (committedBytes < primeBytes)
|
|
||||||
{
|
|
||||||
var remaining = primeBytes - committedBytes;
|
|
||||||
var chunkBytes = Math.Min(remaining, LazyReservePrimeChunkBytes);
|
|
||||||
var commitAddress = actualAddress + committedBytes;
|
|
||||||
if (!_hostMemory.Commit(commitAddress, chunkBytes, HostPageProtection.ReadWrite))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
committedBytes += chunkBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (committedBytes != 0)
|
|
||||||
{
|
|
||||||
lazyPrimeState = committedBytes == primeBytes
|
|
||||||
? $"ok:{committedBytes:X}"
|
|
||||||
: $"partial:{committedBytes:X}/{primeBytes:X}";
|
|
||||||
TraceVmem($"Primed lazy region: 0x{actualAddress:X16} - 0x{actualAddress + committedBytes:X16} ({committedBytes} bytes)");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lazyPrimeState = $"fail:{primeBytes:X}";
|
|
||||||
TraceVmem($"Failed to prime lazy region at 0x{actualAddress:X16} ({primeBytes} bytes), continuing with on-demand commit");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lazyPrimeState = "skip:0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_gate.EnterWriteLock();
|
_gate.EnterWriteLock();
|
||||||
try
|
try
|
||||||
@@ -425,6 +399,41 @@ public sealed unsafe class PhysicalVirtualMemory : IVirtualMemory, IGuestMemoryA
|
|||||||
return actualAddress;
|
return actualAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string ReserveRegion(ulong actualAddress, ulong alignedSize)
|
||||||
|
{
|
||||||
|
var primeBytes = Math.Min(alignedSize, LazyReservePrimeBytes);
|
||||||
|
if (primeBytes == 0)
|
||||||
|
{
|
||||||
|
return "skip:0";
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong committedBytes = 0;
|
||||||
|
while (committedBytes < primeBytes)
|
||||||
|
{
|
||||||
|
var remaining = primeBytes - committedBytes;
|
||||||
|
var chunkBytes = Math.Min(remaining, LazyReservePrimeChunkBytes);
|
||||||
|
var commitAddress = actualAddress + committedBytes;
|
||||||
|
if (!_hostMemory.Commit(commitAddress, chunkBytes, HostPageProtection.ReadWrite))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
committedBytes += chunkBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (committedBytes != 0)
|
||||||
|
{
|
||||||
|
var state = committedBytes == primeBytes
|
||||||
|
? $"ok:{committedBytes:X}"
|
||||||
|
: $"partial:{committedBytes:X}/{primeBytes:X}";
|
||||||
|
TraceVmem($"region: 0x{actualAddress:X16} - 0x{actualAddress + committedBytes:X16} ({committedBytes} bytes)");
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceVmem($"Failed to reserve region at 0x{actualAddress:X16} ({primeBytes} bytes)!");
|
||||||
|
return $"fail:{primeBytes:X}";
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryBackFixedRange(ulong address, ulong size, bool executable)
|
public bool TryBackFixedRange(ulong address, ulong size, bool executable)
|
||||||
{
|
{
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user