aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Memory/MemoryManagementUnix.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Memory/MemoryManagementUnix.cs')
-rw-r--r--Ryujinx.Memory/MemoryManagementUnix.cs197
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