diff options
Diffstat (limited to 'ARMeilleure/Memory')
| -rw-r--r-- | ARMeilleure/Memory/MemoryManagement.cs | 38 | ||||
| -rw-r--r-- | ARMeilleure/Memory/MemoryManagementUnix.cs | 23 | ||||
| -rw-r--r-- | ARMeilleure/Memory/MemoryManagementWindows.cs | 23 | ||||
| -rw-r--r-- | ARMeilleure/Memory/MemoryManagerPal.cs | 2 | ||||
| -rw-r--r-- | ARMeilleure/Memory/ReservedRegion.cs | 53 |
5 files changed, 138 insertions, 1 deletions
diff --git a/ARMeilleure/Memory/MemoryManagement.cs b/ARMeilleure/Memory/MemoryManagement.cs index e299ae49..ba62f8e7 100644 --- a/ARMeilleure/Memory/MemoryManagement.cs +++ b/ARMeilleure/Memory/MemoryManagement.cs @@ -44,6 +44,25 @@ namespace ARMeilleure.Memory } } + public static bool Commit(IntPtr address, ulong size) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + IntPtr sizeNint = new IntPtr((long)size); + + return MemoryManagementWindows.Commit(address, sizeNint); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return MemoryManagementUnix.Commit(address, size); + } + else + { + throw new PlatformNotSupportedException(); + } + } + public static void Reprotect(IntPtr address, ulong size, MemoryProtection permission) { bool result; @@ -70,6 +89,25 @@ namespace ARMeilleure.Memory } } + public static IntPtr Reserve(ulong size) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + IntPtr sizeNint = new IntPtr((long)size); + + return MemoryManagementWindows.Reserve(sizeNint); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return MemoryManagementUnix.Reserve(size); + } + else + { + throw new PlatformNotSupportedException(); + } + } + public static bool Free(IntPtr address) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/ARMeilleure/Memory/MemoryManagementUnix.cs b/ARMeilleure/Memory/MemoryManagementUnix.cs index 3331fb42..e9b29608 100644 --- a/ARMeilleure/Memory/MemoryManagementUnix.cs +++ b/ARMeilleure/Memory/MemoryManagementUnix.cs @@ -30,6 +30,11 @@ namespace ARMeilleure.Memory return ptr; } + public static bool Commit(IntPtr address, ulong size) + { + return Syscall.mprotect(address, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE) == 0; + } + public static bool Reprotect(IntPtr address, ulong size, Memory.MemoryProtection protection) { MmapProts prot = GetProtection(protection); @@ -37,6 +42,24 @@ namespace ARMeilleure.Memory return Syscall.mprotect(address, size, prot) == 0; } + public static IntPtr Reserve(ulong size) + { + ulong pageSize = (ulong)Syscall.sysconf(SysconfName._SC_PAGESIZE); + + const MmapProts prot = MmapProts.PROT_NONE; + + const MmapFlags flags = MmapFlags.MAP_PRIVATE | MmapFlags.MAP_ANONYMOUS; + + IntPtr ptr = Syscall.mmap(IntPtr.Zero, size + pageSize, prot, flags, -1, 0); + + if (ptr == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + + return ptr; + } + private static MmapProts GetProtection(Memory.MemoryProtection protection) { switch (protection) diff --git a/ARMeilleure/Memory/MemoryManagementWindows.cs b/ARMeilleure/Memory/MemoryManagementWindows.cs index ae64b5c6..a9455063 100644 --- a/ARMeilleure/Memory/MemoryManagementWindows.cs +++ b/ARMeilleure/Memory/MemoryManagementWindows.cs @@ -89,6 +89,15 @@ namespace ARMeilleure.Memory return ptr; } + public static bool Commit(IntPtr location, IntPtr size) + { + const AllocationType flags = AllocationType.Commit; + + IntPtr ptr = VirtualAlloc(location, size, flags, MemoryProtection.ReadWrite); + + return ptr != IntPtr.Zero; + } + public static bool Reprotect(IntPtr address, IntPtr size, Memory.MemoryProtection protection) { MemoryProtection prot = GetProtection(protection); @@ -96,6 +105,20 @@ namespace ARMeilleure.Memory return VirtualProtect(address, size, prot, out _); } + public static IntPtr Reserve(IntPtr size) + { + const AllocationType flags = AllocationType.Reserve; + + IntPtr ptr = VirtualAlloc(IntPtr.Zero, size, flags, MemoryProtection.ReadWrite); + + if (ptr == IntPtr.Zero) + { + throw new OutOfMemoryException(); + } + + return ptr; + } + private static MemoryProtection GetProtection(Memory.MemoryProtection protection) { switch (protection) diff --git a/ARMeilleure/Memory/MemoryManagerPal.cs b/ARMeilleure/Memory/MemoryManagerPal.cs index 64191a0a..66c43642 100644 --- a/ARMeilleure/Memory/MemoryManagerPal.cs +++ b/ARMeilleure/Memory/MemoryManagerPal.cs @@ -53,7 +53,7 @@ namespace ARMeilleure.Memory Operand expected = context.LoadArgument(OperandType.V128, 1); Operand desired = context.LoadArgument(OperandType.V128, 2); - Operand result = context.CompareAndSwap128(address, expected, desired); + Operand result = context.CompareAndSwap(address, expected, desired); context.Return(result); diff --git a/ARMeilleure/Memory/ReservedRegion.cs b/ARMeilleure/Memory/ReservedRegion.cs new file mode 100644 index 00000000..521019ad --- /dev/null +++ b/ARMeilleure/Memory/ReservedRegion.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ARMeilleure.Memory +{ + class ReservedRegion + { + private const int DefaultGranularity = 65536; // Mapping granularity in Windows. + + public IntPtr Pointer { get; } + + private ulong _maxSize; + private ulong _sizeGranularity; + private ulong _currentSize; + + public ReservedRegion(ulong maxSize, ulong granularity = 0) + { + if (granularity == 0) + { + granularity = DefaultGranularity; + } + + Pointer = MemoryManagement.Reserve(maxSize); + _maxSize = maxSize; + _sizeGranularity = granularity; + _currentSize = 0; + } + + public void ExpandIfNeeded(ulong desiredSize) + { + if (desiredSize > _maxSize) + { + throw new OutOfMemoryException(); + } + + if (desiredSize > _currentSize) + { + // Lock, and then check again. We only want to commit once. + lock (this) + { + if (desiredSize >= _currentSize) + { + ulong overflowBytes = desiredSize - _currentSize; + ulong moreToCommit = (((_sizeGranularity - 1) + overflowBytes) / _sizeGranularity) * _sizeGranularity; // Round up. + MemoryManagement.Commit(new IntPtr((long)Pointer + (long)_currentSize), moreToCommit); + _currentSize += moreToCommit; + } + } + } + } + } +} |
