MemoryManagerUnixHelper.cs
1 using System; 2 using System.Runtime.InteropServices; 3 using System.Runtime.Versioning; 4 5 namespace Ryujinx.Memory 6 { 7 [SupportedOSPlatform("linux")] 8 [SupportedOSPlatform("macos")] 9 public static partial class MemoryManagerUnixHelper 10 { 11 [Flags] 12 public enum MmapProts : uint 13 { 14 PROT_NONE = 0, 15 PROT_READ = 1, 16 PROT_WRITE = 2, 17 PROT_EXEC = 4, 18 } 19 20 [Flags] 21 public enum MmapFlags : uint 22 { 23 MAP_SHARED = 1, 24 MAP_PRIVATE = 2, 25 MAP_ANONYMOUS = 4, 26 MAP_NORESERVE = 8, 27 MAP_FIXED = 16, 28 MAP_UNLOCKED = 32, 29 MAP_JIT_DARWIN = 0x800, 30 } 31 32 [Flags] 33 public enum OpenFlags : uint 34 { 35 O_RDONLY = 0, 36 O_WRONLY = 1, 37 O_RDWR = 2, 38 O_CREAT = 4, 39 O_EXCL = 8, 40 O_NOCTTY = 16, 41 O_TRUNC = 32, 42 O_APPEND = 64, 43 O_NONBLOCK = 128, 44 O_SYNC = 256, 45 } 46 47 public const IntPtr MAP_FAILED = -1; 48 49 private const int MAP_ANONYMOUS_LINUX_GENERIC = 0x20; 50 private const int MAP_NORESERVE_LINUX_GENERIC = 0x4000; 51 private const int MAP_UNLOCKED_LINUX_GENERIC = 0x80000; 52 53 private const int MAP_NORESERVE_DARWIN = 0x40; 54 private const int MAP_ANONYMOUS_DARWIN = 0x1000; 55 56 public const int MADV_DONTNEED = 4; 57 public const int MADV_REMOVE = 9; 58 59 [LibraryImport("libc", EntryPoint = "mmap", SetLastError = true)] 60 private static partial IntPtr Internal_mmap(IntPtr address, ulong length, MmapProts prot, int flags, int fd, long offset); 61 62 [LibraryImport("libc", SetLastError = true)] 63 public static partial int mprotect(IntPtr address, ulong length, MmapProts prot); 64 65 [LibraryImport("libc", SetLastError = true)] 66 public static partial int munmap(IntPtr address, ulong length); 67 68 [LibraryImport("libc", SetLastError = true)] 69 public static partial IntPtr mremap(IntPtr old_address, ulong old_size, ulong new_size, int flags, IntPtr new_address); 70 71 [LibraryImport("libc", SetLastError = true)] 72 public static partial int madvise(IntPtr address, ulong size, int advice); 73 74 [LibraryImport("libc", SetLastError = true)] 75 public static partial int mkstemp(IntPtr template); 76 77 [LibraryImport("libc", SetLastError = true)] 78 public static partial int unlink(IntPtr pathname); 79 80 [LibraryImport("libc", SetLastError = true)] 81 public static partial int ftruncate(int fildes, IntPtr length); 82 83 [LibraryImport("libc", SetLastError = true)] 84 public static partial int close(int fd); 85 86 [LibraryImport("libc", SetLastError = true)] 87 public static partial int shm_open(IntPtr name, int oflag, uint mode); 88 89 [LibraryImport("libc", SetLastError = true)] 90 public static partial int shm_unlink(IntPtr name); 91 92 private static int MmapFlagsToSystemFlags(MmapFlags flags) 93 { 94 int result = 0; 95 96 if (flags.HasFlag(MmapFlags.MAP_SHARED)) 97 { 98 result |= (int)MmapFlags.MAP_SHARED; 99 } 100 101 if (flags.HasFlag(MmapFlags.MAP_PRIVATE)) 102 { 103 result |= (int)MmapFlags.MAP_PRIVATE; 104 } 105 106 if (flags.HasFlag(MmapFlags.MAP_FIXED)) 107 { 108 result |= (int)MmapFlags.MAP_FIXED; 109 } 110 111 if (flags.HasFlag(MmapFlags.MAP_ANONYMOUS)) 112 { 113 if (OperatingSystem.IsLinux()) 114 { 115 result |= MAP_ANONYMOUS_LINUX_GENERIC; 116 } 117 else if (OperatingSystem.IsMacOS()) 118 { 119 result |= MAP_ANONYMOUS_DARWIN; 120 } 121 else 122 { 123 throw new NotImplementedException(); 124 } 125 } 126 127 if (flags.HasFlag(MmapFlags.MAP_NORESERVE)) 128 { 129 if (OperatingSystem.IsLinux()) 130 { 131 result |= MAP_NORESERVE_LINUX_GENERIC; 132 } 133 else if (OperatingSystem.IsMacOS()) 134 { 135 result |= MAP_NORESERVE_DARWIN; 136 } 137 else 138 { 139 throw new NotImplementedException(); 140 } 141 } 142 143 if (flags.HasFlag(MmapFlags.MAP_UNLOCKED)) 144 { 145 if (OperatingSystem.IsLinux()) 146 { 147 result |= MAP_UNLOCKED_LINUX_GENERIC; 148 } 149 else if (OperatingSystem.IsMacOS()) 150 { 151 // FIXME: Doesn't exist on Darwin 152 } 153 else 154 { 155 throw new NotImplementedException(); 156 } 157 } 158 159 if (flags.HasFlag(MmapFlags.MAP_JIT_DARWIN) && OperatingSystem.IsMacOSVersionAtLeast(10, 14)) 160 { 161 result |= (int)MmapFlags.MAP_JIT_DARWIN; 162 } 163 164 return result; 165 } 166 167 public static IntPtr Mmap(IntPtr address, ulong length, MmapProts prot, MmapFlags flags, int fd, long offset) 168 { 169 return Internal_mmap(address, length, prot, MmapFlagsToSystemFlags(flags), fd, offset); 170 } 171 } 172 }