MemoryManagerUnixHelper.cs 5.3 KB

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