Query multiple pages at once with GetWriteWatch (#222)
* Query multiple pages at once with GetWriteWatch * Allow multiple buffer types to share the same page, aways use the physical address as cache key * Remove a variable that is no longer needed
This commit is contained in:
parent
a47b96571e
commit
0daf70a1d9
2 changed files with 58 additions and 29 deletions
|
@ -33,19 +33,25 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
private byte* RamPtr;
|
private byte* RamPtr;
|
||||||
|
|
||||||
|
private int HostPageSize;
|
||||||
|
|
||||||
public AMemory()
|
public AMemory()
|
||||||
{
|
{
|
||||||
Manager = new AMemoryMgr();
|
Manager = new AMemoryMgr();
|
||||||
|
|
||||||
Monitors = new Dictionary<int, ArmMonitor>();
|
Monitors = new Dictionary<int, ArmMonitor>();
|
||||||
|
|
||||||
|
IntPtr Size = (IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize;
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
Ram = AMemoryWin32.Allocate((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
|
Ram = AMemoryWin32.Allocate(Size);
|
||||||
|
|
||||||
|
HostPageSize = AMemoryWin32.GetPageSize(Ram, Size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
|
Ram = Marshal.AllocHGlobal(Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
RamPtr = (byte*)Ram;
|
RamPtr = (byte*)Ram;
|
||||||
|
@ -149,49 +155,53 @@ namespace ChocolArm64.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetHostPageSize()
|
public int GetHostPageSize()
|
||||||
|
{
|
||||||
|
return HostPageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool[] IsRegionModified(long Position, long Size)
|
||||||
{
|
{
|
||||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
return AMemoryMgr.PageSize;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
IntPtr MemAddress = new IntPtr(RamPtr);
|
|
||||||
IntPtr MemSize = new IntPtr(AMemoryMgr.RamSize);
|
|
||||||
|
|
||||||
long PageSize = AMemoryWin32.IsRegionModified(MemAddress, MemSize, Reset: false);
|
|
||||||
|
|
||||||
if (PageSize < 1)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return PageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRegionModified(long Position, long Size)
|
|
||||||
{
|
|
||||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long EndPos = Position + Size;
|
long EndPos = Position + Size;
|
||||||
|
|
||||||
if ((ulong)EndPos < (ulong)Position)
|
if ((ulong)EndPos < (ulong)Position)
|
||||||
{
|
{
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ulong)EndPos > AMemoryMgr.RamSize)
|
if ((ulong)EndPos > AMemoryMgr.RamSize)
|
||||||
{
|
{
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr MemAddress = new IntPtr(RamPtr + Position);
|
IntPtr MemAddress = new IntPtr(RamPtr + Position);
|
||||||
IntPtr MemSize = new IntPtr(Size);
|
IntPtr MemSize = new IntPtr(Size);
|
||||||
|
|
||||||
return AMemoryWin32.IsRegionModified(MemAddress, MemSize, Reset: true) != 0;
|
int HostPageMask = HostPageSize - 1;
|
||||||
|
|
||||||
|
Position &= ~HostPageMask;
|
||||||
|
|
||||||
|
Size = EndPos - Position;
|
||||||
|
|
||||||
|
IntPtr[] Addresses = new IntPtr[(Size + HostPageMask) / HostPageSize];
|
||||||
|
|
||||||
|
AMemoryWin32.IsRegionModified(MemAddress, MemSize, Addresses, out int Count);
|
||||||
|
|
||||||
|
bool[] Modified = new bool[Addresses.Length];
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Count; Index++)
|
||||||
|
{
|
||||||
|
long VA = Addresses[Index].ToInt64() - Ram.ToInt64();
|
||||||
|
|
||||||
|
Modified[(VA - Position) / HostPageSize] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sbyte ReadSByte(long Position)
|
public sbyte ReadSByte(long Position)
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace ChocolArm64.Memory
|
||||||
VirtualFree(Address, IntPtr.Zero, MEM_RELEASE);
|
VirtualFree(Address, IntPtr.Zero, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe static long IsRegionModified(IntPtr Address, IntPtr Size, bool Reset)
|
public unsafe static int GetPageSize(IntPtr Address, IntPtr Size)
|
||||||
{
|
{
|
||||||
IntPtr[] Addresses = new IntPtr[1];
|
IntPtr[] Addresses = new IntPtr[1];
|
||||||
|
|
||||||
|
@ -57,17 +57,36 @@ namespace ChocolArm64.Memory
|
||||||
|
|
||||||
long Granularity;
|
long Granularity;
|
||||||
|
|
||||||
int Flags = Reset ? WRITE_WATCH_FLAG_RESET : 0;
|
|
||||||
|
|
||||||
GetWriteWatch(
|
GetWriteWatch(
|
||||||
Flags,
|
0,
|
||||||
Address,
|
Address,
|
||||||
Size,
|
Size,
|
||||||
Addresses,
|
Addresses,
|
||||||
&Count,
|
&Count,
|
||||||
&Granularity);
|
&Granularity);
|
||||||
|
|
||||||
return Count != 0 ? Granularity : 0;
|
return (int)Granularity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe static void IsRegionModified(
|
||||||
|
IntPtr Address,
|
||||||
|
IntPtr Size,
|
||||||
|
IntPtr[] Addresses,
|
||||||
|
out int AddrCount)
|
||||||
|
{
|
||||||
|
long Count = Addresses.Length;
|
||||||
|
|
||||||
|
long Granularity;
|
||||||
|
|
||||||
|
GetWriteWatch(
|
||||||
|
WRITE_WATCH_FLAG_RESET,
|
||||||
|
Address,
|
||||||
|
Size,
|
||||||
|
Addresses,
|
||||||
|
&Count,
|
||||||
|
&Granularity);
|
||||||
|
|
||||||
|
AddrCount = (int)Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue