diff options
Diffstat (limited to 'Ryujinx.Memory/MemoryManagementUnix.cs')
-rw-r--r-- | Ryujinx.Memory/MemoryManagementUnix.cs | 197 |
1 files changed, 53 insertions, 144 deletions
diff --git a/Ryujinx.Memory/MemoryManagementUnix.cs b/Ryujinx.Memory/MemoryManagementUnix.cs index 9e3ec48a..db7539f0 100644 --- a/Ryujinx.Memory/MemoryManagementUnix.cs +++ b/Ryujinx.Memory/MemoryManagementUnix.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Runtime.Versioning; +using System.Text; using static Ryujinx.Memory.MemoryManagerUnixHelper; @@ -12,15 +11,6 @@ namespace Ryujinx.Memory [SupportedOSPlatform("macos")] static class MemoryManagementUnix { - private struct UnixSharedMemory - { - public IntPtr Pointer; - public ulong Size; - public IntPtr SourcePointer; - } - - private static readonly List<UnixSharedMemory> _sharedMemory = new List<UnixSharedMemory>(); - private static readonly ConcurrentDictionary<IntPtr, ulong> _sharedMemorySource = new ConcurrentDictionary<IntPtr, ulong>(); private static readonly ConcurrentDictionary<IntPtr, ulong> _allocations = new ConcurrentDictionary<IntPtr, ulong>(); public static IntPtr Allocate(ulong size) @@ -69,40 +59,15 @@ namespace Ryujinx.Memory public static bool Commit(IntPtr address, ulong size) { - bool success = mprotect(address, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE) == 0; - - if (success) - { - foreach (var shared in _sharedMemory) - { - if ((ulong)address + size > (ulong)shared.SourcePointer && (ulong)address < (ulong)shared.SourcePointer + shared.Size) - { - ulong sharedAddress = ((ulong)address - (ulong)shared.SourcePointer) + (ulong)shared.Pointer; - - if (mprotect((IntPtr)sharedAddress, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE) != 0) - { - return false; - } - } - } - } - - return success; + return mprotect(address, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE) == 0; } public static bool Decommit(IntPtr address, ulong size) { - bool isShared; - - lock (_sharedMemory) - { - isShared = _sharedMemory.Exists(x => (ulong)address >= (ulong)x.Pointer && (ulong)address + size <= (ulong)x.Pointer + x.Size); - } - // Must be writable for madvise to work properly. mprotect(address, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE); - madvise(address, size, isShared ? MADV_REMOVE : MADV_DONTNEED); + madvise(address, size, MADV_REMOVE); return mprotect(address, size, MmapProts.PROT_NONE) == 0; } @@ -136,139 +101,83 @@ namespace Ryujinx.Memory return false; } - public static IntPtr Remap(IntPtr target, IntPtr source, ulong size) + public static bool Unmap(IntPtr address, ulong size) { - int flags = 1; - - if (target != IntPtr.Zero) - { - flags |= 2; - } - - IntPtr result = mremap(source, 0, size, flags, target); - - if (result == IntPtr.Zero) - { - throw new InvalidOperationException(); - } - - return result; + return munmap(address, size) == 0; } - public static IntPtr CreateSharedMemory(ulong size, bool reserve) + public unsafe static IntPtr CreateSharedMemory(ulong size, bool reserve) { - IntPtr result = AllocateInternal( - size, - reserve ? MmapProts.PROT_NONE : MmapProts.PROT_READ | MmapProts.PROT_WRITE, - true); + int fd; - if (result == IntPtr.Zero) + if (OperatingSystem.IsMacOS()) { - throw new OutOfMemoryException(); - } - - _sharedMemorySource[result] = (ulong)size; + byte[] memName = Encoding.ASCII.GetBytes("Ryujinx-XXXXXX"); - return result; - } - - public static void DestroySharedMemory(IntPtr handle) - { - lock (_sharedMemory) - { - foreach (var memory in _sharedMemory) + fixed (byte* pMemName = memName) { - if (memory.SourcePointer == handle) + fd = shm_open((IntPtr)pMemName, 0x2 | 0x200 | 0x800 | 0x400, 384); // O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0600 + if (fd == -1) { - throw new InvalidOperationException("Shared memory cannot be destroyed unless fully unmapped."); + throw new OutOfMemoryException(); + } + + if (shm_unlink((IntPtr)pMemName) != 0) + { + throw new OutOfMemoryException(); } } } - - _sharedMemorySource.Remove(handle, out ulong _); - } - - public static IntPtr MapSharedMemory(IntPtr handle) - { - // Try find the handle for this shared memory. If it is mapped, then we want to map - // it a second time in another location. - // If it is not mapped, then its handle is the mapping. - - ulong size = _sharedMemorySource[handle]; - - if (size == 0) + else { - throw new InvalidOperationException("Shared memory cannot be mapped after its source is unmapped."); - } + byte[] fileName = Encoding.ASCII.GetBytes("/dev/shm/Ryujinx-XXXXXX"); - lock (_sharedMemory) - { - foreach (var memory in _sharedMemory) + fixed (byte* pFileName = fileName) { - if (memory.Pointer == handle) + fd = mkstemp((IntPtr)pFileName); + if (fd == -1) { - IntPtr result = AllocateInternal( - memory.Size, - MmapProts.PROT_NONE - ); - - if (result == IntPtr.Zero) - { - throw new OutOfMemoryException(); - } - - Remap(result, handle, memory.Size); - - _sharedMemory.Add(new UnixSharedMemory - { - Pointer = result, - Size = memory.Size, - - SourcePointer = handle - }); + throw new OutOfMemoryException(); + } - return result; + if (unlink((IntPtr)pFileName) != 0) + { + throw new OutOfMemoryException(); } } + } - _sharedMemory.Add(new UnixSharedMemory - { - Pointer = handle, - Size = size, - - SourcePointer = handle - }); + if (ftruncate(fd, (IntPtr)size) != 0) + { + throw new OutOfMemoryException(); } - return handle; + return (IntPtr)fd; } - public static void UnmapSharedMemory(IntPtr address) + public static void DestroySharedMemory(IntPtr handle) { - lock (_sharedMemory) - { - int removed = _sharedMemory.RemoveAll(memory => - { - if (memory.Pointer == address) - { - if (memory.Pointer == memory.SourcePointer) - { - // After removing the original mapping, it cannot be mapped again. - _sharedMemorySource[memory.SourcePointer] = 0; - } - - Free(address); - return true; - } + close((int)handle); + } - return false; - }); + public static IntPtr MapSharedMemory(IntPtr handle, ulong size) + { + return mmap(IntPtr.Zero, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_SHARED, (int)handle, 0); + } - if (removed == 0) - { - throw new InvalidOperationException("Shared memory mapping could not be found."); - } - } + public static void UnmapSharedMemory(IntPtr address, ulong size) + { + munmap(address, size); + } + + public static void MapView(IntPtr sharedMemory, ulong srcOffset, IntPtr location, ulong size) + { + mmap(location, size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, MmapFlags.MAP_FIXED | MmapFlags.MAP_SHARED, (int)sharedMemory, (long)srcOffset); + } + + public static void UnmapView(IntPtr location, ulong size) + { + mmap(location, size, MmapProts.PROT_NONE, MmapFlags.MAP_FIXED, -1, 0); } } }
\ No newline at end of file |