aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Memory
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-07-08 16:55:15 -0300
committerGitHub <noreply@github.com>2018-07-08 16:55:15 -0300
commit095db47e132a475e25d128e691ebdae101611cc9 (patch)
treef10299c8168709bf8db7f2da966eb0cbe6b598a9 /ChocolArm64/Memory
parent0f8f40486d1b3215c845325744bd545149223805 (diff)
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
Diffstat (limited to 'ChocolArm64/Memory')
-rw-r--r--ChocolArm64/Memory/AMemory.cs58
-rw-r--r--ChocolArm64/Memory/AMemoryWin32.cs27
2 files changed, 57 insertions, 28 deletions
diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
index c02bf172..da5cf007 100644
--- a/ChocolArm64/Memory/AMemory.cs
+++ b/ChocolArm64/Memory/AMemory.cs
@@ -33,19 +33,25 @@ namespace ChocolArm64.Memory
private byte* RamPtr;
+ private int HostPageSize;
+
public AMemory()
{
Manager = new AMemoryMgr();
Monitors = new Dictionary<int, ArmMonitor>();
+ IntPtr Size = (IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize;
+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- Ram = AMemoryWin32.Allocate((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
+ Ram = AMemoryWin32.Allocate(Size);
+
+ HostPageSize = AMemoryWin32.GetPageSize(Ram, Size);
}
else
{
- Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize + AMemoryMgr.PageSize);
+ Ram = Marshal.AllocHGlobal(Size);
}
RamPtr = (byte*)Ram;
@@ -149,49 +155,53 @@ namespace ChocolArm64.Memory
}
}
- public long GetHostPageSize()
+ public int GetHostPageSize()
{
- if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- {
- return AMemoryMgr.PageSize;
- }
-
- 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;
+ return HostPageSize;
}
- public bool IsRegionModified(long Position, long Size)
+ public bool[] IsRegionModified(long Position, long Size)
{
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
- return true;
+ return null;
}
long EndPos = Position + Size;
if ((ulong)EndPos < (ulong)Position)
{
- return false;
+ return null;
}
if ((ulong)EndPos > AMemoryMgr.RamSize)
{
- return false;
+ return null;
}
IntPtr MemAddress = new IntPtr(RamPtr + Position);
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)
diff --git a/ChocolArm64/Memory/AMemoryWin32.cs b/ChocolArm64/Memory/AMemoryWin32.cs
index d097dc87..387ca32c 100644
--- a/ChocolArm64/Memory/AMemoryWin32.cs
+++ b/ChocolArm64/Memory/AMemoryWin32.cs
@@ -49,7 +49,7 @@ namespace ChocolArm64.Memory
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];
@@ -57,17 +57,36 @@ namespace ChocolArm64.Memory
long Granularity;
- int Flags = Reset ? WRITE_WATCH_FLAG_RESET : 0;
+ GetWriteWatch(
+ 0,
+ Address,
+ Size,
+ Addresses,
+ &Count,
+ &Granularity);
+
+ return (int)Granularity;
+ }
+
+ public unsafe static void IsRegionModified(
+ IntPtr Address,
+ IntPtr Size,
+ IntPtr[] Addresses,
+ out int AddrCount)
+ {
+ long Count = Addresses.Length;
+
+ long Granularity;
GetWriteWatch(
- Flags,
+ WRITE_WATCH_FLAG_RESET,
Address,
Size,
Addresses,
&Count,
&Granularity);
- return Count != 0 ? Granularity : 0;
+ AddrCount = (int)Count;
}
}
} \ No newline at end of file