/ src / Ryujinx.Memory / MemoryManagerUnixHelper.cs
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  }