diff options
| author | gdk <gab.dark.100@gmail.com> | 2022-06-23 13:52:45 -0300 |
|---|---|---|
| committer | Mary-nyan <thog@protonmail.com> | 2022-09-10 16:23:49 +0200 |
| commit | 96d4ad952c60e99c1d814ad7680106a5eabcb0d8 (patch) | |
| tree | 8a988cd7014c6e6131bae4a2ae7a93dbcd532754 | |
| parent | 6a07f80b766a6894ef6699acbafc719c9a7d7bd8 (diff) | |
Fix reprotection regression
| -rw-r--r-- | Ryujinx.Memory/WindowsShared/PlaceholderManager.cs | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs b/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs index 6db8d7df..f1752229 100644 --- a/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs +++ b/Ryujinx.Memory/WindowsShared/PlaceholderManager.cs @@ -69,6 +69,11 @@ namespace Ryujinx.Memory.WindowsShared { _mappings.Add(new RangeNode<ulong>(address, address + size, ulong.MaxValue)); } + + lock (_protections) + { + _protections.Add(new RangeNode<MemoryPermission>(address, size, MemoryPermission.None)); + } } /// <summary> @@ -104,14 +109,6 @@ namespace Ryujinx.Memory.WindowsShared } } - if (count > 1) - { - CheckFreeResult(WindowsApi.VirtualFree( - (IntPtr)address, - (IntPtr)size, - AllocationType.Release | AllocationType.CoalescePlaceholders)); - } - RemoveProtection(address, size); } @@ -130,7 +127,7 @@ namespace Ryujinx.Memory.WindowsShared try { - UnmapViewInternal(sharedMemory, location, size, owner); + UnmapViewInternal(sharedMemory, location, size, owner, updateProtection: false); MapViewInternal(sharedMemory, srcOffset, location, size); } finally @@ -166,6 +163,8 @@ namespace Ryujinx.Memory.WindowsShared { throw new WindowsApiException("MapViewOfFile3"); } + + UpdateProtection((ulong)location, (ulong)size, MemoryPermission.ReadAndWrite); } /// <summary> @@ -189,7 +188,6 @@ namespace Ryujinx.Memory.WindowsShared var overlap = overlaps[0]; - // Tree operations might modify the node start/end values, so save a copy before we modify the tree. ulong overlapStart = overlap.Start; ulong overlapEnd = overlap.End; ulong overlapValue = overlap.Value; @@ -254,7 +252,7 @@ namespace Ryujinx.Memory.WindowsShared try { - UnmapViewInternal(sharedMemory, location, size, owner); + UnmapViewInternal(sharedMemory, location, size, owner, updateProtection: true); } finally { @@ -273,8 +271,9 @@ namespace Ryujinx.Memory.WindowsShared /// <param name="location">Address to unmap</param> /// <param name="size">Size of the region to unmap in bytes</param> /// <param name="owner">Memory block that owns the mapping</param> + /// <param name="updateProtection">Indicates if the memory protections should be updated after the unmap</param> /// <exception cref="WindowsApiException">Thrown when the Windows API returns an error unmapping or remapping the memory</exception> - private void UnmapViewInternal(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner) + private void UnmapViewInternal(IntPtr sharedMemory, IntPtr location, IntPtr size, MemoryBlock owner, bool updateProtection) { ulong startAddress = (ulong)location; ulong unmapSize = (ulong)size; @@ -294,7 +293,6 @@ namespace Ryujinx.Memory.WindowsShared if (IsMapped(overlap.Value)) { - // Tree operations might modify the node start/end values, so save a copy before we modify the tree. ulong overlapStart = overlap.Start; ulong overlapEnd = overlap.End; ulong overlapValue = overlap.Value; @@ -360,7 +358,11 @@ namespace Ryujinx.Memory.WindowsShared } CoalesceForUnmap(startAddress, unmapSize, owner); - RemoveProtection(startAddress, unmapSize); + + if (updateProtection) + { + UpdateProtection(startAddress, unmapSize, MemoryPermission.None); + } } /// <summary> @@ -512,19 +514,10 @@ namespace Ryujinx.Memory.WindowsShared success = false; } - - // We only keep track of "non-standard" protections, - // that is, everything that is not just RW (which is the default when views are mapped). - if (permission == MemoryPermission.ReadAndWrite) - { - RemoveProtection(mappedAddress, mappedSize); - } - else - { - AddProtection(mappedAddress, mappedSize, permission); - } } + UpdateProtection(reprotectAddress, reprotectSize, permission); + return success; } @@ -573,7 +566,7 @@ namespace Ryujinx.Memory.WindowsShared /// <param name="address">Address of the protected region</param> /// <param name="size">Size of the protected region in bytes</param> /// <param name="permission">Memory permissions of the region</param> - private void AddProtection(ulong address, ulong size, MemoryPermission permission) + private void UpdateProtection(ulong address, ulong size, MemoryPermission permission) { ulong endAddress = address + size; var overlaps = new RangeNode<MemoryPermission>[InitialOverlapsSize]; @@ -693,6 +686,12 @@ namespace Ryujinx.Memory.WindowsShared { var protection = overlaps[index]; + // If protection is R/W we don't need to reprotect as views are initially mapped as R/W. + if (protection.Value == MemoryPermission.ReadAndWrite) + { + continue; + } + ulong protAddress = protection.Start; ulong protEndAddress = protection.End; |
