MemoryManagerUnixHelper.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace Ryujinx.Memory
  4. {
  5. public static class MemoryManagerUnixHelper
  6. {
  7. [Flags]
  8. public enum MmapProts : uint
  9. {
  10. PROT_NONE = 0,
  11. PROT_READ = 1,
  12. PROT_WRITE = 2,
  13. PROT_EXEC = 4
  14. }
  15. [Flags]
  16. public enum MmapFlags : uint
  17. {
  18. MAP_SHARED = 1,
  19. MAP_PRIVATE = 2,
  20. MAP_ANONYMOUS = 4,
  21. MAP_NORESERVE = 8,
  22. MAP_UNLOCKED = 16
  23. }
  24. private const int MAP_ANONYMOUS_LINUX_GENERIC = 0x20;
  25. private const int MAP_NORESERVE_LINUX_GENERIC = 0x4000;
  26. private const int MAP_UNLOCKED_LINUX_GENERIC = 0x80000;
  27. private const int MAP_NORESERVE_DARWIN = 0x40;
  28. private const int MAP_JIT_DARWIN = 0x800;
  29. private const int MAP_ANONYMOUS_DARWIN = 0x1000;
  30. public const int MADV_DONTNEED = 4;
  31. public const int MADV_REMOVE = 9;
  32. [DllImport("libc", EntryPoint = "mmap", SetLastError = true)]
  33. private static extern IntPtr Internal_mmap(IntPtr address, ulong length, MmapProts prot, int flags, int fd, long offset);
  34. [DllImport("libc", SetLastError = true)]
  35. public static extern int mprotect(IntPtr address, ulong length, MmapProts prot);
  36. [DllImport("libc", SetLastError = true)]
  37. public static extern int munmap(IntPtr address, ulong length);
  38. [DllImport("libc", SetLastError = true)]
  39. public static extern IntPtr mremap(IntPtr old_address, ulong old_size, ulong new_size, int flags, IntPtr new_address);
  40. [DllImport("libc", SetLastError = true)]
  41. public static extern int madvise(IntPtr address, ulong size, int advice);
  42. private static int MmapFlagsToSystemFlags(MmapFlags flags)
  43. {
  44. int result = 0;
  45. if (flags.HasFlag(MmapFlags.MAP_SHARED))
  46. {
  47. result |= (int)MmapFlags.MAP_SHARED;
  48. }
  49. if (flags.HasFlag(MmapFlags.MAP_PRIVATE))
  50. {
  51. result |= (int)MmapFlags.MAP_PRIVATE;
  52. }
  53. if (flags.HasFlag(MmapFlags.MAP_ANONYMOUS))
  54. {
  55. if (OperatingSystem.IsLinux())
  56. {
  57. result |= MAP_ANONYMOUS_LINUX_GENERIC;
  58. }
  59. else if (OperatingSystem.IsMacOS())
  60. {
  61. result |= MAP_ANONYMOUS_DARWIN;
  62. }
  63. else
  64. {
  65. throw new NotImplementedException();
  66. }
  67. }
  68. if (flags.HasFlag(MmapFlags.MAP_NORESERVE))
  69. {
  70. if (OperatingSystem.IsLinux())
  71. {
  72. result |= MAP_NORESERVE_LINUX_GENERIC;
  73. }
  74. else if (OperatingSystem.IsMacOS())
  75. {
  76. result |= MAP_NORESERVE_DARWIN;
  77. }
  78. else
  79. {
  80. throw new NotImplementedException();
  81. }
  82. }
  83. if (flags.HasFlag(MmapFlags.MAP_UNLOCKED))
  84. {
  85. if (OperatingSystem.IsLinux())
  86. {
  87. result |= MAP_UNLOCKED_LINUX_GENERIC;
  88. }
  89. else if (OperatingSystem.IsMacOS())
  90. {
  91. // FIXME: Doesn't exist on Darwin
  92. }
  93. else
  94. {
  95. throw new NotImplementedException();
  96. }
  97. }
  98. if (OperatingSystem.IsMacOSVersionAtLeast(10, 14))
  99. {
  100. result |= MAP_JIT_DARWIN;
  101. }
  102. return result;
  103. }
  104. public static IntPtr mmap(IntPtr address, ulong length, MmapProts prot, MmapFlags flags, int fd, long offset)
  105. {
  106. return Internal_mmap(address, length, prot, MmapFlagsToSystemFlags(flags), fd, offset);
  107. }
  108. }
  109. }