diff --git a/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeMemoryMappedViewHandle.cs b/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeMemoryMappedViewHandle.cs index b7cf6b04c7209..73f12afc504a0 100644 --- a/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeMemoryMappedViewHandle.cs +++ b/mcs/class/System.Core/Microsoft.Win32.SafeHandles/SafeMemoryMappedViewHandle.cs @@ -37,14 +37,17 @@ namespace Microsoft.Win32.SafeHandles { public sealed class SafeMemoryMappedViewHandle : SafeBuffer { - internal SafeMemoryMappedViewHandle (IntPtr handle, long size) : base (true) { - this.handle = handle; + IntPtr mmap_handle; + + internal SafeMemoryMappedViewHandle (IntPtr mmap_handle, IntPtr base_address, long size) : base (true) { + this.mmap_handle = mmap_handle; + this.handle = base_address; Initialize ((ulong)size); } protected override bool ReleaseHandle () { if (this.handle != (IntPtr) (-1)) - return MemoryMapImpl.Unmap (this.handle, ByteLength); + return MemoryMapImpl.Unmap (this.mmap_handle); throw new NotImplementedException (); } } diff --git a/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedFile.cs b/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedFile.cs index 7fa4586a44b9e..feaaa5ab98493 100644 --- a/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedFile.cs +++ b/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedFile.cs @@ -32,464 +32,84 @@ using System.Collections.Generic; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; - - -#if !MOBILE -using Mono.Unix.Native; -using Mono.Unix; -#else using System.Runtime.CompilerServices; -#endif + namespace System.IO.MemoryMappedFiles { - internal static partial class MemoryMapImpl { - static Exception ArgumentCapacity () - { - return new ArgumentException ("A positive capacity must be specified for a Memory Mapped File backed by an empty file."); - } - - static Exception CapacitySmallerThanSize () - { - return new ArgumentOutOfRangeException ("The capacity may not be smaller than the file size."); - } - } - - -#if !MOBILE - partial class MemoryMapImpl { - // - // Turns the FileMode into the first half of open(2) flags - // - static OpenFlags ToUnixMode (FileMode mode) - { - switch (mode){ - case FileMode.CreateNew: - return OpenFlags.O_CREAT | OpenFlags.O_EXCL; - - case FileMode.Create: - return OpenFlags.O_CREAT | OpenFlags.O_TRUNC; - - case FileMode.OpenOrCreate: - return OpenFlags.O_CREAT; - - case FileMode.Truncate: - return OpenFlags.O_TRUNC; - - case FileMode.Append: - return OpenFlags.O_APPEND; - default: - case FileMode.Open: - return 0; - } - } - - // - // Turns the MemoryMappedFileAccess into the second half of open(2) flags - // - static OpenFlags ToUnixMode (MemoryMappedFileAccess access) - { - switch (access){ - case MemoryMappedFileAccess.CopyOnWrite: - case MemoryMappedFileAccess.ReadWriteExecute: - case MemoryMappedFileAccess.ReadWrite: - return OpenFlags.O_RDWR; - - case MemoryMappedFileAccess.Write: - return OpenFlags.O_WRONLY; - - case MemoryMappedFileAccess.ReadExecute: - case MemoryMappedFileAccess.Read: - default: - return OpenFlags.O_RDONLY; - } - } - - static MmapProts ToUnixProts (MemoryMappedFileAccess access) - { - switch (access){ - case MemoryMappedFileAccess.ReadWrite: - return MmapProts.PROT_WRITE | MmapProts.PROT_READ; - - case MemoryMappedFileAccess.Write: - return MmapProts.PROT_WRITE; - - case MemoryMappedFileAccess.CopyOnWrite: - return MmapProts.PROT_WRITE | MmapProts.PROT_READ; - - case MemoryMappedFileAccess.ReadExecute: - return MmapProts.PROT_EXEC; - - case MemoryMappedFileAccess.ReadWriteExecute: - return MmapProts.PROT_WRITE | MmapProts.PROT_READ | MmapProts.PROT_EXEC; - - case MemoryMappedFileAccess.Read: - default: - return MmapProts.PROT_READ; - } - } - - internal static int Open (string path, FileMode mode, ref long capacity, MemoryMappedFileAccess access) - { - if (MonoUtil.IsUnix){ - Stat buf; - - int result = Syscall.stat (path, out buf); - - if (mode == FileMode.Truncate || mode == FileMode.Append || mode == FileMode.Open){ - if (result == -1) - UnixMarshal.ThrowExceptionForLastError (); - } - if (mode == FileMode.CreateNew && result == 0) - throw new IOException ("The file already exists"); - - if (result == 0){ - if (capacity == 0) { - // Special files such as FIFOs, sockets, and devices can - // have a size of 0. Specifying a capacity for these - // also makes little sense, so don't do the check if the - // file is one of these. - if (buf.st_size == 0 && - (buf.st_mode & (FilePermissions.S_IFCHR | - FilePermissions.S_IFBLK | - FilePermissions.S_IFIFO | - FilePermissions.S_IFSOCK)) == 0) { - throw ArgumentCapacity (); - } - - capacity = buf.st_size; - } else if (capacity < buf.st_size) { - throw CapacitySmallerThanSize (); - } - } else { - if (mode == FileMode.CreateNew){ - if (capacity == 0) - throw ArgumentCapacity (); - } - } - - int fd = Syscall.open (path, ToUnixMode (mode) | ToUnixMode (access), FilePermissions.DEFFILEMODE); - - if (fd == -1) - UnixMarshal.ThrowExceptionForLastError (); - return fd; - } - - throw new NotImplementedException (); - } - - internal static void CloseFD (int fd) { - Syscall.close (fd); - } - - internal static void Flush (int fd) { - if (MonoUtil.IsUnix) - Syscall.fsync (fd); - else - throw new NotImplementedException ("Not implemented on Windows"); - - } - - static int pagesize; - - internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff) - { - if (!MonoUtil.IsUnix) - throw new NotImplementedException ("Not implemented on windows."); - - if (pagesize == 0) - pagesize = Syscall.getpagesize (); - - Stat buf; - Syscall.fstat (file_handle, out buf); - long fsize = buf.st_size; - - if (size == 0 || size > fsize) - size = fsize; - - // Align offset - long real_offset = offset & ~(pagesize - 1); - - offset_diff = (int)(offset - real_offset); - - // FIXME: Need to determine the unix fd for the file, Handle is only - // equal to it by accident - // - // The new API no longer uses FileStream everywhere, but exposes instead - // the filename (with one exception), we could move this API to use - // file descriptors instead of the FileStream plus its Handle. - // - map_addr = Syscall.mmap (IntPtr.Zero, (ulong) size, - ToUnixProts (access), - access == MemoryMappedFileAccess.CopyOnWrite ? MmapFlags.MAP_PRIVATE : MmapFlags.MAP_SHARED, - file_handle, real_offset); - - if (map_addr == (IntPtr)(-1)) - throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")"); - } - - internal static bool Unmap (IntPtr map_addr, ulong map_size) - { - if (!MonoUtil.IsUnix) - return false; - return Syscall.munmap (map_addr, map_size) == 0; - } - - static void ConfigureUnixFD (IntPtr handle, HandleInheritability h) - { - // TODO: Mono.Posix is lacking O_CLOEXEC definitions for fcntl. - } - - - [DllImport("kernel32", SetLastError = true)] - static extern bool SetHandleInformation (IntPtr hObject, int dwMask, int dwFlags); - static void ConfigureWindowsFD (IntPtr handle, HandleInheritability h) - { - SetHandleInformation (handle, 1 /* FLAG_INHERIT */, h == HandleInheritability.None ? 0 : 1); - } - - internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability) - { - if (MonoUtil.IsUnix) - ConfigureUnixFD (handle, inheritability); - else - ConfigureWindowsFD (handle, inheritability); - } - - } -#else - partial class MemoryMapImpl { - [DllImport ("libc")] - static extern int fsync (int fd); - - [DllImport ("libc")] - static extern int close (int fd); - - [DllImport ("libc")] - static extern int fcntl (int fd, int cmd, int arg0); - - //XXX check if android off_t is 64bits or not. on iOS / darwin it is. - [DllImport ("libc")] - static extern IntPtr mmap (IntPtr addr, IntPtr len, int prot, int flags, int fd, long offset); - - [DllImport ("libc")] - static extern int munmap (IntPtr addr, IntPtr size); - - [DllImport ("libc", SetLastError=true)] - static extern int open (string path, int flags, int access); - -#if MONODROID - [DllImport ("__Internal")] - static extern int monodroid_getpagesize (); - - static int getpagesize () - { - return monodroid_getpagesize (); - } -#else - [DllImport ("libc")] - static extern int getpagesize (); -#endif - + internal static class MemoryMapImpl { [MethodImplAttribute (MethodImplOptions.InternalCall)] - static extern long mono_filesize_from_path (string str); + static extern IntPtr OpenFileInternal (string path, FileMode mode, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, out int error); [MethodImplAttribute (MethodImplOptions.InternalCall)] - static extern long mono_filesize_from_fd (int fd); - - //Values valid on iOS/OSX and android ndk r6 - const int F_GETFD = 1; - const int F_SETFD = 2; - const int FD_CLOEXEC = 1; - const int DEFFILEMODE = 0x666; - - const int O_RDONLY = 0x0; - const int O_WRONLY = 0x1; - const int O_RDWR = 0x2; + static extern IntPtr OpenHandleInternal (IntPtr handle, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, out int error); - const int PROT_READ = 0x1; - const int PROT_WRITE = 0x2; - const int PROT_EXEC = 0x4; - - const int MAP_PRIVATE = 0x2; - const int MAP_SHARED = 0x1; - - const int EINVAL = 22; - -#if MONODROID - const int O_CREAT = 0x040; - const int O_TRUNC = 0x080; - const int O_EXCL = 0x200; - - const int ENAMETOOLONG = 63; -#else - /* MONOTOUCH - usr/include/sys/fcntl.h */ - const int O_CREAT = 0x0200; - const int O_TRUNC = 0x0400; - const int O_EXCL = 0x0800; - - // usr/include/sys/errno.h - const int ENAMETOOLONG = 63; -#endif + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void CloseMapping (IntPtr handle); - static int ToUnixMode (FileMode mode) - { - switch (mode) { - case FileMode.CreateNew: - return O_CREAT | O_EXCL; - - case FileMode.Create: - return O_CREAT | O_TRUNC; - - case FileMode.OpenOrCreate: - return O_CREAT; - - case FileMode.Truncate: - return O_TRUNC; - default: - case FileMode.Open: - return 0; - } - } + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Flush (IntPtr file_handle); - // - // Turns the MemoryMappedFileAccess into the second half of open(2) flags - // - static int ToUnixMode (MemoryMappedFileAccess access) - { - switch (access) { - case MemoryMappedFileAccess.CopyOnWrite: - case MemoryMappedFileAccess.ReadWriteExecute: - case MemoryMappedFileAccess.ReadWrite: - return O_RDWR; - - case MemoryMappedFileAccess.Write: - return O_WRONLY; + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void ConfigureHandleInheritability (IntPtr handle, HandleInheritability inheritability); - case MemoryMappedFileAccess.ReadExecute: - case MemoryMappedFileAccess.Read: - default: - return O_RDONLY; - } - } + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static bool Unmap (IntPtr mmap_handle); - static int ToUnixProts (MemoryMappedFileAccess access) - { - switch (access){ - case MemoryMappedFileAccess.ReadWrite: - return PROT_WRITE | PROT_READ; - - case MemoryMappedFileAccess.Write: - return PROT_WRITE; - - case MemoryMappedFileAccess.CopyOnWrite: - return PROT_WRITE | PROT_READ; - - case MemoryMappedFileAccess.ReadExecute: - return PROT_EXEC; - - case MemoryMappedFileAccess.ReadWriteExecute: - return PROT_WRITE | PROT_READ | PROT_EXEC; - - case MemoryMappedFileAccess.Read: + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern static int MapInternal (IntPtr handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr mmap_handle, out IntPtr base_address); + + internal static void Map (IntPtr handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr mmap_handle, out IntPtr base_address) + { + int error = MapInternal (handle, offset, ref size, access, out mmap_handle, out base_address); + if (error != 0) + throw CreateException (error, ""); + } + + static Exception CreateException (int error, string path) { + switch (error){ + case 1: + return new ArgumentException ("A positive capacity must be specified for a Memory Mapped File backed by an empty file."); + case 2: + return new ArgumentOutOfRangeException ("The capacity may not be smaller than the file size."); + case 3: + return new FileNotFoundException (path); + case 4: + return new IOException ("The file already exists"); + case 5: + return new PathTooLongException (); + case 6: + return new IOException ("Could not open file"); + case 7: + return new ArgumentException ("Capacity must be bigger than zero for non-file mappings"); + case 8: + return new ArgumentException ("Invalid FileMode value."); + case 9: + return new IOException ("Could not map file"); default: - return PROT_READ; + return new IOException ("Failed with unknown error code " + error); } } - static void ThrowErrorFromErrno (int errno) + internal static IntPtr OpenFile (string path, FileMode mode, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options) { - switch (errno) { - case EINVAL: throw new ArgumentException (); - case ENAMETOOLONG: throw new PathTooLongException (); - default: throw new IOException ("Failed with errno " + errno); - } - } - - internal static int Open (string path, FileMode mode, ref long capacity, MemoryMappedFileAccess access) - { - long file_size = mono_filesize_from_path (path); - - Console.WriteLine ("{0} is {1} big", path, file_size); - if (mode == FileMode.Truncate || mode == FileMode.Append || mode == FileMode.Open){ - if (file_size < 0) - throw new FileNotFoundException (path); - if (capacity == 0) - capacity = file_size; - if (capacity < file_size) - throw CapacitySmallerThanSize (); - } else { - if (mode == FileMode.CreateNew){ - if (file_size >= 0) - throw new IOException ("The file already exists"); - if (capacity == 0) - throw ArgumentCapacity (); - } - } - - int fd = open (path, ToUnixMode (mode) | ToUnixMode (access), DEFFILEMODE); - - if (fd == -1) - ThrowErrorFromErrno (Marshal.GetLastWin32Error ()); - return fd; - } - - internal static void CloseFD (int fd) - { - close (fd); - } - - internal static void Flush (int fd) - { - fsync (fd); - } - - internal static bool Unmap (IntPtr map_addr, ulong map_size) - { - return munmap (map_addr, (IntPtr)map_size) == 0; - } - - static int pagesize; - - internal static unsafe void Map (int file_handle, long offset, ref long size, MemoryMappedFileAccess access, out IntPtr map_addr, out int offset_diff) - { - if (pagesize == 0) - pagesize = getpagesize (); - - long fsize = mono_filesize_from_fd (file_handle); - if (fsize < 0) - throw new FileNotFoundException (); - - if (size == 0 || size > fsize) - size = fsize; - - // Align offset - long real_offset = offset & ~(pagesize - 1); - - offset_diff = (int)(offset - real_offset); - - map_addr = mmap (IntPtr.Zero, (IntPtr) size, - ToUnixProts (access), - access == MemoryMappedFileAccess.CopyOnWrite ? MAP_PRIVATE : MAP_SHARED, - file_handle, real_offset); - - if (map_addr == (IntPtr)(-1)) - throw new IOException ("mmap failed for fd#" + file_handle + "(" + offset + ", " + size + ")"); + int error = 0; + IntPtr res = OpenFileInternal (path, mode, mapName, out capacity, access, options, out error); + if (error != 0) + throw CreateException (error, path); + return res; } - internal static void ConfigureFD (IntPtr handle, HandleInheritability inheritability) + internal static IntPtr OpenHandle (IntPtr handle, string mapName, out long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options) { - int fd = (int)handle; - int flags = fcntl (fd, F_GETFD, 0); - if (inheritability == HandleInheritability.None) - flags &= ~FD_CLOEXEC; - else - flags |= FD_CLOEXEC; - fcntl (fd, F_SETFD, flags); + int error = 0; + IntPtr res = OpenHandleInternal (handle, mapName, out capacity, access, options, out error); + if (error != 0) + throw CreateException (error, ""); + return res; } - } -#endif + public class MemoryMappedFile : IDisposable { MemoryMappedFileAccess fileAccess; @@ -504,7 +124,7 @@ public class MemoryMappedFile : IDisposable { // FileStream stream; bool keepOpen; - int unix_fd; + IntPtr handle; public static MemoryMappedFile CreateFromFile (string path) { @@ -513,7 +133,21 @@ public static MemoryMappedFile CreateFromFile (string path) public static MemoryMappedFile CreateFromFile (string path, FileMode mode) { - return CreateFromFile (path, mode, null, 0, MemoryMappedFileAccess.ReadWrite); + long capacity = 0; + if (path == null) + throw new ArgumentNullException ("path"); + if (path.Length == 0) + throw new ArgumentException ("path"); + if (mode == FileMode.Append) + throw new ArgumentException ("mode"); + + IntPtr handle = MemoryMapImpl.OpenFile (path, mode, null, out capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages); + + return new MemoryMappedFile () { + handle = handle, + fileAccess = MemoryMappedFileAccess.ReadWrite, + fileCapacity = capacity + }; } public static MemoryMappedFile CreateFromFile (string path, FileMode mode, string mapName) @@ -539,26 +173,21 @@ public static MemoryMappedFile CreateFromFile (string path, FileMode mode, strin if (capacity < 0) throw new ArgumentOutOfRangeException ("capacity"); - int fd = MemoryMapImpl.Open (path, mode, ref capacity, access); + IntPtr handle = MemoryMapImpl.OpenFile (path, mode, mapName, out capacity, access, MemoryMappedFileOptions.DelayAllocatePages); return new MemoryMappedFile () { - unix_fd = fd, + handle = handle, fileAccess = access, name = mapName, fileCapacity = capacity }; } -#if MOBILE - public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access, - HandleInheritability inheritability, - bool leaveOpen) -#else + [MonoLimitation ("memoryMappedFileSecurity is currently ignored")] public static MemoryMappedFile CreateFromFile (FileStream fileStream, string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability, bool leaveOpen) -#endif { if (fileStream == null) throw new ArgumentNullException ("fileStream"); @@ -567,86 +196,92 @@ public static MemoryMappedFile CreateFromFile (string path, FileMode mode, strin if ((!MonoUtil.IsUnix && capacity == 0 && fileStream.Length == 0) || (capacity > fileStream.Length)) throw new ArgumentException ("capacity"); - MemoryMapImpl.ConfigureFD (fileStream.Handle, inheritability); + IntPtr handle = MemoryMapImpl.OpenHandle (fileStream.Handle, mapName, out capacity, access, MemoryMappedFileOptions.DelayAllocatePages); + + MemoryMapImpl.ConfigureHandleInheritability (handle, inheritability); return new MemoryMappedFile () { - stream = fileStream, + handle = handle, fileAccess = access, name = mapName, fileCapacity = capacity, + + stream = fileStream, keepOpen = leaveOpen }; } - [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")] + + static MemoryMappedFile CoreShmCreate (string mapName, long capacity, MemoryMappedFileAccess access, + MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, + HandleInheritability inheritability, FileMode mode) + { + if (mapName != null && mapName.Length == 0) + throw new ArgumentException ("mapName"); + if (capacity < 0) + throw new ArgumentOutOfRangeException ("capacity"); + + IntPtr handle = MemoryMapImpl.OpenFile (null, mode, mapName, out capacity, access, options); + + return new MemoryMappedFile () { + handle = handle, + fileAccess = access, + name = mapName, + fileCapacity = capacity + }; + } + + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile CreateNew (string mapName, long capacity) { -#if MOBILE - return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, 0); -#else - return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, null, 0); -#endif + return CreateNew (mapName, capacity, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.DelayAllocatePages, null, HandleInheritability.None); } - [MonoLimitation ("CreateNew requires that mapName be a file name on Unix")] + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access) { -#if MOBILE - return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, 0); -#else - return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, 0); -#endif + return CreateNew (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, HandleInheritability.None); } -#if MOBILE - public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access, - MemoryMappedFileOptions options, - HandleInheritability handleInheritability) -#else - [MonoLimitation ("CreateNew requires that mapName be a file name on Unix; options and memoryMappedFileSecurity are ignored")] + [MonoLimitation ("Named mappings scope is process local; options and memoryMappedFileSecurity are ignored")] public static MemoryMappedFile CreateNew (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability) -#endif { - return CreateFromFile (mapName, FileMode.CreateNew, mapName, capacity, access); + return CoreShmCreate (mapName, capacity, access, options, memoryMappedFileSecurity, inheritability, FileMode.CreateNew); } - [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")] + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile CreateOrOpen (string mapName, long capacity) { return CreateOrOpen (mapName, capacity, MemoryMappedFileAccess.ReadWrite); } - [MonoLimitation ("CreateOrOpen requires that mapName be a file name on Unix")] + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access) { - return CreateFromFile (mapName, FileMode.OpenOrCreate, mapName, capacity, access); + return CreateOrOpen (mapName, capacity, access, MemoryMappedFileOptions.DelayAllocatePages, null, HandleInheritability.None); } - [MonoTODO] -#if MOBILE - public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, HandleInheritability inheritability) -#else + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile CreateOrOpen (string mapName, long capacity, MemoryMappedFileAccess access, MemoryMappedFileOptions options, MemoryMappedFileSecurity memoryMappedFileSecurity, HandleInheritability inheritability) -#endif { - throw new NotImplementedException (); + return CoreShmCreate (mapName, capacity, access, options, memoryMappedFileSecurity, inheritability, FileMode.OpenOrCreate); } - [MonoTODO] + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile OpenExisting (string mapName) { throw new NotImplementedException (); } - [MonoTODO] + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights) { throw new NotImplementedException (); } - [MonoTODO] + [MonoLimitation ("Named mappings scope is process local")] public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRights desiredAccessRights, HandleInheritability inheritability) { throw new NotImplementedException (); @@ -654,7 +289,7 @@ public static MemoryMappedFile OpenExisting (string mapName, MemoryMappedFileRig public MemoryMappedViewStream CreateViewStream () { - return CreateViewStream (0, 0); + return CreateViewStream (0, 0);//FIXME this is wrong } public MemoryMappedViewStream CreateViewStream (long offset, long size) @@ -664,7 +299,7 @@ public MemoryMappedViewStream CreateViewStream (long offset, long size) public MemoryMappedViewStream CreateViewStream (long offset, long size, MemoryMappedFileAccess access) { - return new MemoryMappedViewStream (stream != null ? (int)stream.Handle : unix_fd, offset, size, access); + return new MemoryMappedViewStream (handle, offset, size, access); } public MemoryMappedViewAccessor CreateViewAccessor () @@ -679,9 +314,7 @@ public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size) public MemoryMappedViewAccessor CreateViewAccessor (long offset, long size, MemoryMappedFileAccess access) { - int file_handle = stream != null ? (int) stream.Handle : unix_fd; - - return new MemoryMappedViewAccessor (file_handle, offset, size, access); + return new MemoryMappedViewAccessor (handle, offset, size, access); } MemoryMappedFile () @@ -699,17 +332,15 @@ protected virtual void Dispose (bool disposing) if (stream != null){ if (keepOpen == false) stream.Close (); - unix_fd = -1; stream = null; } - if (unix_fd != -1) { - MemoryMapImpl.CloseFD (unix_fd); - unix_fd = -1; + if (handle != IntPtr.Zero) { + MemoryMapImpl.CloseMapping (handle); + handle = IntPtr.Zero; } } } -#if !MOBILE [MonoTODO] public MemoryMappedFileSecurity GetAccessControl () { @@ -721,7 +352,6 @@ public void SetAccessControl (MemoryMappedFileSecurity memoryMappedFileSecurity) { throw new NotImplementedException (); } -#endif [MonoTODO] public SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle { diff --git a/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cs b/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cs index 0535337210d42..c66acdb55c6cd 100644 --- a/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cs +++ b/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewAccessor.cs @@ -36,14 +36,12 @@ namespace System.IO.MemoryMappedFiles { public sealed class MemoryMappedViewAccessor : UnmanagedMemoryAccessor, IDisposable { - int file_handle; - IntPtr mmap_addr; - SafeMemoryMappedViewHandle handle; + IntPtr mmap_handle; + SafeMemoryMappedViewHandle safe_handle; - internal MemoryMappedViewAccessor (int file_handle, long offset, long size, MemoryMappedFileAccess access) + internal MemoryMappedViewAccessor (IntPtr handle, long offset, long size, MemoryMappedFileAccess access) { - this.file_handle = file_handle; - Create (offset, size, access); + Create (handle, offset, size, access); } static FileAccess ToFileAccess (MemoryMappedFileAccess access) @@ -64,19 +62,19 @@ static FileAccess ToFileAccess (MemoryMappedFileAccess access) } } - unsafe void Create (long offset, long size, MemoryMappedFileAccess access) + unsafe void Create (IntPtr handle, long offset, long size, MemoryMappedFileAccess access) { - int offset_diff; + IntPtr base_address; - MemoryMapImpl.Map (file_handle, offset, ref size, access, out mmap_addr, out offset_diff); + MemoryMapImpl.Map (handle, offset, ref size, access, out mmap_handle, out base_address); + safe_handle = new SafeMemoryMappedViewHandle (mmap_handle, base_address, size); - handle = new SafeMemoryMappedViewHandle ((IntPtr)((long)mmap_addr + offset_diff), size); - Initialize (handle, 0, size, ToFileAccess (access)); + Initialize (safe_handle, 0, size, ToFileAccess (access)); } public SafeMemoryMappedViewHandle SafeMemoryMappedViewHandle { get { - return handle; + return safe_handle; } } @@ -91,7 +89,7 @@ protected override void Dispose (bool disposing) public void Flush () { - MemoryMapImpl.Flush (file_handle); + MemoryMapImpl.Flush (mmap_handle); } } } diff --git a/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cs b/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cs index 0f6aa75dc4203..651e2d0d26244 100644 --- a/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cs +++ b/mcs/class/System.Core/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cs @@ -35,15 +35,12 @@ namespace System.IO.MemoryMappedFiles { public sealed class MemoryMappedViewStream : UnmanagedMemoryStream { - IntPtr mmap_addr; - ulong mmap_size; + IntPtr mmap_handle; object monitor; - int fd; - internal MemoryMappedViewStream (int fd, long offset, long size, MemoryMappedFileAccess access) { - this.fd = fd; + internal MemoryMappedViewStream (IntPtr handle, long offset, long size, MemoryMappedFileAccess access) { monitor = new Object (); - CreateStream (fd, offset, size, access); + CreateStream (handle, offset, size, access); } public SafeMemoryMappedViewHandle SafeMemoryMappedViewHandle { @@ -52,13 +49,13 @@ public sealed class MemoryMappedViewStream : UnmanagedMemoryStream { } } - unsafe void CreateStream (int fd, long offset, long size, MemoryMappedFileAccess access) + unsafe void CreateStream (IntPtr handle, long offset, long size, MemoryMappedFileAccess access) { - int offset_diff; - mmap_size = (ulong) size; - MemoryMapImpl.Map (fd, offset, ref size, access, out mmap_addr, out offset_diff); - FileAccess faccess; + IntPtr base_address; + + MemoryMapImpl.Map (handle, offset, ref size, access, out mmap_handle, out base_address); + FileAccess faccess; switch (access) { case MemoryMappedFileAccess.ReadWrite: faccess = FileAccess.ReadWrite; @@ -72,23 +69,23 @@ unsafe void CreateStream (int fd, long offset, long size, MemoryMappedFileAccess default: throw new NotImplementedException ("access mode " + access + " not supported."); } - Initialize ((byte*)mmap_addr + offset_diff, size, size, faccess); + Initialize ((byte*)base_address, size, size, faccess); } protected override void Dispose (bool disposing) { base.Dispose (disposing); lock (monitor) { - if (mmap_addr != (IntPtr)(-1)) { - MemoryMapImpl.Unmap (mmap_addr, mmap_size); - mmap_addr = (IntPtr)(-1); + if (mmap_handle != (IntPtr)(-1)) { + MemoryMapImpl.Unmap (mmap_handle); + mmap_handle = (IntPtr)(-1); } } } public override void Flush () { - MemoryMapImpl.Flush (fd); + MemoryMapImpl.Flush (mmap_handle); } } } diff --git a/mono/metadata/Makefile.am.in b/mono/metadata/Makefile.am.in index fa6228326346f..d3c19c25ba56e 100644 --- a/mono/metadata/Makefile.am.in +++ b/mono/metadata/Makefile.am.in @@ -191,7 +191,11 @@ common_sources = \ verify.c \ verify-internals.h \ wrapper-types.h \ - reflection-internals.h + reflection-internals.h \ + file-mmap-posix.c \ + file-mmap-windows.c \ + file-mmap.h + # These source files have compile time dependencies on GC code gc_dependent_sources = \ diff --git a/mono/metadata/file-mmap-posix.c b/mono/metadata/file-mmap-posix.c new file mode 100644 index 0000000000000..afd97b22ed560 --- /dev/null +++ b/mono/metadata/file-mmap-posix.c @@ -0,0 +1,514 @@ +/* + * file-mmap-posix.c: File mmap internal calls + * + * Author: + * Rodrigo Kumpera + * + * Copyright 2014 Xamarin Inc (http://www.xamarin.com) + */ + +#include + +#ifndef TARGET_WIN32 + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_MMAN_H +#include +#endif + +#include + + +#include +#include +#include +#include +#include +#include + +enum { + MMAP_KIND_FILE = 1, + MMAP_KIND_MEMORY = 2 +}; + +typedef struct { + int kind; + int ref_count; + gint64 capacity; + char *name; +} Handle; + +typedef struct { + Handle handle; + int fd; +} FileHandle; + +typedef struct { + Handle handle; + void *address; + size_t length; +} MemoryHandle; + +typedef struct { + void *address; + void *free_handle; + int kind; + size_t length; +} MmapHandle; + +enum { + BAD_CAPACITY_FOR_FILE_BACKED = 1, + CAPACITY_SMALLER_THAN_FILE_SIZE, + FILE_NOT_FOUND, + FILE_ALREADY_EXISTS, + PATH_TOO_LONG, + COULD_NOT_OPEN, + CAPACITY_MUST_BE_POSITIVE, + INVALID_FILE_MODE, + COULD_NOT_MAP_MEMORY +}; + +enum { + FILE_MODE_CREATE_NEW = 1, + FILE_MODE_CREATE = 2, + FILE_MODE_OPEN = 3, + FILE_MODE_OPEN_OR_CREATE = 4, + FILE_MODE_TRUNCATE = 5, + FILE_MODE_APPEND = 6, +}; + +enum { + MMAP_FILE_ACCESS_READ_WRITE = 0, + MMAP_FILE_ACCESS_READ = 1, + MMAP_FILE_ACCESS_WRITE = 2, + MMAP_FILE_ACCESS_COPY_ON_WRITE = 3, + MMAP_FILE_ACCESS_READ_EXECUTE = 4, + MMAP_FILE_ACCESS_READ_WRITE_EXECUTE = 5, +}; + + +static int mmap_init_state; +static mono_mutex_t named_regions_mutex; +static GHashTable *named_regions; + + +static gint64 +align_up_to_page_size (gint64 size) +{ + gint64 page_size = mono_pagesize (); + return (size + page_size - 1) & ~(page_size - 1); +} + +static gint64 +align_down_to_page_size (gint64 size) +{ + gint64 page_size = mono_pagesize (); + return size & ~(page_size - 1); +} + +static void +file_mmap_init (void) +{ +retry: + switch (mmap_init_state) { + case 0: + if (InterlockedCompareExchange (&mmap_init_state, 1, 0) != 0) + goto retry; + named_regions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); + mono_mutex_init (&named_regions_mutex); + + mono_atomic_store_release (&mmap_init_state, 2); + break; + + case 1: + do { + g_usleep (1000); /* Been init'd by other threads, this is very rare. */ + } while (mmap_init_state != 2); + break; + case 2: + break; + default: + g_error ("Invalid init state %d", mmap_init_state); + } +} + +static void +named_regions_lock (void) +{ + file_mmap_init (); + mono_mutex_lock (&named_regions_mutex); +} + +static void +named_regions_unlock (void) +{ + mono_mutex_unlock (&named_regions_mutex); +} + + +static int +file_mode_to_unix (int mode) +{ + switch (mode) { + case FILE_MODE_CREATE_NEW: + return O_CREAT | O_EXCL; + case FILE_MODE_CREATE: + return O_CREAT | O_TRUNC; + case FILE_MODE_OPEN: + return 0; + case FILE_MODE_OPEN_OR_CREATE: + return O_CREAT; + case FILE_MODE_TRUNCATE: + return O_TRUNC; + case FILE_MODE_APPEND: + return O_APPEND; + default: + g_error ("unknown FileMode %d", mode); + } +} + +static int +access_mode_to_unix (int access) +{ + switch (access) { + case MMAP_FILE_ACCESS_READ_WRITE: + case MMAP_FILE_ACCESS_COPY_ON_WRITE: + case MMAP_FILE_ACCESS_READ_WRITE_EXECUTE: + return O_RDWR; + case MMAP_FILE_ACCESS_READ: + case MMAP_FILE_ACCESS_READ_EXECUTE: + return O_RDONLY; + case MMAP_FILE_ACCESS_WRITE: + return O_WRONLY; + default: + g_error ("unknown MemoryMappedFileAccess %d", access); + } +} + +static int +acess_to_mmap_flags (int access) +{ + switch (access) { + case MMAP_FILE_ACCESS_READ_WRITE: + return MONO_MMAP_WRITE | MONO_MMAP_READ | MONO_MMAP_PRIVATE; + + case MMAP_FILE_ACCESS_WRITE: + return MONO_MMAP_WRITE | MONO_MMAP_PRIVATE; + + case MMAP_FILE_ACCESS_COPY_ON_WRITE: + return MONO_MMAP_WRITE | MONO_MMAP_READ; + + case MMAP_FILE_ACCESS_READ_EXECUTE: + return MONO_MMAP_EXEC | MONO_MMAP_PRIVATE | MONO_MMAP_SHARED; + + case MMAP_FILE_ACCESS_READ_WRITE_EXECUTE: + return MONO_MMAP_WRITE | MONO_MMAP_READ | MONO_MMAP_EXEC | MONO_MMAP_PRIVATE; + + case MMAP_FILE_ACCESS_READ: + return MONO_MMAP_READ | MONO_MMAP_PRIVATE; + default: + g_error ("unknown MemoryMappedFileAccess %d", access); + } +} + +/* +XXX implement options +*/ +static void* +open_file_map (MonoString *path, int input_fd, int mode, gint64 *capacity, int access, int options, int *error) +{ + struct stat buf; + char *c_path = path ? mono_string_to_utf8 (path) : NULL; + FileHandle *handle = NULL; + int result, fd; + + if (path) + result = stat (c_path, &buf); + else + result = fstat (input_fd, &buf); + + if (mode == FILE_MODE_TRUNCATE || mode == FILE_MODE_APPEND || mode == FILE_MODE_OPEN) { + if (result == -1) { //XXX translate errno? + *error = FILE_NOT_FOUND; + goto done; + } + } + + if (mode == FILE_MODE_CREATE_NEW && result == 0) { + *error = FILE_ALREADY_EXISTS; + goto done; + } + + if (result == 0) { + if (*capacity == 0) { + /** + * Special files such as FIFOs, sockets, and devices can have a size of 0. Specifying a capacity for these + * also makes little sense, so don't do the check if th file is one of these. + */ + if (buf.st_size == 0 && (buf.st_mode & (S_IFCHR | S_IFBLK | S_IFIFO | S_IFSOCK)) == 0) { + *error = CAPACITY_SMALLER_THAN_FILE_SIZE; + goto done; + } + *capacity = buf.st_size; + } else if (*capacity < buf.st_size) { + *error = CAPACITY_SMALLER_THAN_FILE_SIZE; + goto done; + } + } else { + if (mode == FILE_MODE_CREATE_NEW && *capacity == 0) { + *error = CAPACITY_SMALLER_THAN_FILE_SIZE; + goto done; + } + } + + if (path) //FIXME use io portability? + fd = open (c_path, file_mode_to_unix (mode) | access_mode_to_unix (access), DEFFILEMODE); + else + fd = dup (input_fd); + + if (fd == -1) { //XXX translate errno? + *error = COULD_NOT_OPEN; + goto done; + } + + *capacity = align_up_to_page_size ((size_t)*capacity); + + if (*capacity > buf.st_size) + ftruncate (fd, (off_t)*capacity); + + handle = g_new0 (FileHandle, 1); + handle->handle.kind = MMAP_KIND_FILE; + handle->handle.ref_count = 1; + handle->handle.capacity = *capacity; + handle->fd = fd; + +done: + g_free (c_path); + return (void*)handle; +} + +static void* +open_memory_map (MonoString *mapName, int mode, gint64 *capacity, int access, int options, int *error) +{ + char *c_mapName; + MemoryHandle *handle; + if (*capacity <= 1) { + *error = CAPACITY_MUST_BE_POSITIVE; + return NULL; + } + + if (!(mode == FILE_MODE_CREATE_NEW || mode == FILE_MODE_OPEN_OR_CREATE || mode == FILE_MODE_OPEN)) { + *error = INVALID_FILE_MODE; + return NULL; + } + + c_mapName = mono_string_to_utf8 (mapName); + + named_regions_lock (); + handle = (MemoryHandle*)g_hash_table_lookup (named_regions, c_mapName); + if (handle) { + if (mode == FILE_MODE_CREATE_NEW) + *error = FILE_ALREADY_EXISTS; + + handle->handle.ref_count++; + //XXX should we ftruncate if the file is smaller than capacity? + } else { + if (mode == FILE_MODE_OPEN) + *error = FILE_NOT_FOUND; + + *capacity = align_up_to_page_size (*capacity); + + handle = g_new0 (MemoryHandle, 1); + handle->handle.kind = MMAP_KIND_MEMORY; + handle->handle.ref_count = 1; + handle->handle.capacity = *capacity; + handle->handle.name = g_strdup (c_mapName); + + //FIXME compute RWX from access + handle->address = mono_valloc (NULL, (size_t)*capacity, MONO_MMAP_READ | MONO_MMAP_WRITE | MONO_MMAP_PRIVATE | MONO_MMAP_ANON); + handle->length = (size_t)*capacity; + g_hash_table_insert (named_regions, handle->handle.name, handle); + } + + named_regions_unlock (); + + g_free (c_mapName); + return handle; +} + + +void * +mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error) +{ + g_assert (path || mapName); + + if (!mapName) + return open_file_map (path, -1, mode, capacity, access, options, error); + + if (path) { + FileHandle *file_handle; + char *c_mapName = mono_string_to_utf8 (mapName); + + named_regions_lock (); + file_handle = (FileHandle*)g_hash_table_lookup (named_regions, c_mapName); + if (file_handle) { + *error = FILE_ALREADY_EXISTS; + file_handle = NULL; + } else { + file_handle = open_file_map (path, -1, mode, capacity, access, options, error); + if (file_handle) { + file_handle->handle.name = g_strdup (c_mapName); + g_hash_table_insert (named_regions, file_handle->handle.name, file_handle); + } + } + named_regions_unlock (); + + g_free (c_mapName); + return file_handle; + } + + return open_memory_map (mapName, mode, capacity, access, options, error); +} + +void * +mono_mmap_open_handle (void *handle, MonoString *mapName, gint64 *capacity, int access, int options, int *error) +{ + FileHandle *file_handle; + char *c_mapName = mono_string_to_utf8 (mapName); + + named_regions_lock (); + file_handle = (FileHandle*)g_hash_table_lookup (named_regions, c_mapName); + if (file_handle) { + *error = FILE_ALREADY_EXISTS; + file_handle = NULL; + } else { + //XXX we're exploiting wapi HANDLE == FD equivalence. THIS IS FRAGILE, create a _wapi_handle_to_fd call + file_handle = open_file_map (NULL, GPOINTER_TO_INT (handle), FILE_MODE_OPEN, capacity, access, options, error); + file_handle->handle.name = g_strdup (c_mapName); + g_hash_table_insert (named_regions, file_handle->handle.name, file_handle); + } + named_regions_unlock (); + + g_free (c_mapName); + return file_handle; +} + +void +mono_mmap_close (void *mmap_handle) +{ + Handle *handle = mmap_handle; + + named_regions_lock (); + --handle->ref_count; + if (handle->ref_count == 0) { + if (handle->name) + g_hash_table_remove (named_regions, handle->name); + + g_free (handle->name); + if (handle->kind == MMAP_KIND_MEMORY) + mono_vfree (((MemoryHandle*)handle)->address, ((MemoryHandle*)handle)->length); + else + close (((FileHandle*)handle)->fd); + g_free (handle); + } + named_regions_unlock (); +} + +void +mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability) +{ + FileHandle *h = mmap_handle; + int fd, flags; + + if (h->handle.kind != MMAP_KIND_FILE) + return; + + fd = h->fd; + flags = fcntl (fd, F_GETFD, 0); + if (inheritability) + flags &= ~FD_CLOEXEC; + else + flags |= FD_CLOEXEC; + fcntl (fd, F_SETFD, flags); +} + +void +mono_mmap_flush (void *mmap_handle) +{ + MmapHandle *h = mmap_handle; + + if (h) + msync (h->address, h->length, MS_SYNC); +} + +int +mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address) +{ + gint64 mmap_offset = 0; + Handle *h = handle; + MmapHandle res = { 0 }; + if (h->kind == MMAP_KIND_FILE) { + FileHandle *fh = (FileHandle*)h; + size_t eff_size = *size; + struct stat buf = { 0 }; + fstat (fh->fd, &buf); //FIXME error handling + + if (eff_size == 0 || eff_size > buf.st_size) + eff_size = buf.st_size; + *size = eff_size; + + mmap_offset = align_down_to_page_size (offset); + eff_size += (offset - mmap_offset); + //FIXME translate some interesting errno values + res.address = mono_file_map ((size_t)eff_size, acess_to_mmap_flags (access), fh->fd, mmap_offset, &res.free_handle); + res.length = eff_size; + res.kind = MMAP_KIND_FILE; + + } else { + MemoryHandle *mh = (MemoryHandle*)h; + size_t eff_size = *size; + + if (!eff_size) + eff_size = *size = mh->length; + mmap_offset = (size_t)mmap_offset; + res.address = (char*)mh->address + offset; + res.length = (size_t)size; + res.kind = MMAP_KIND_MEMORY; + } + + if (res.address) { + *mmap_handle = g_memdup (&res, sizeof (MmapHandle)); + *base_address = (char*)res.address + (offset - mmap_offset); + return 0; + } + + *mmap_handle = NULL; + *base_address = NULL; + return COULD_NOT_MAP_MEMORY; +} + +gboolean +mono_mmap_unmap (void *mmap_handle) +{ + int res = 0; + MmapHandle *h = mmap_handle; + + if (h->kind == MMAP_KIND_FILE) + res = mono_file_unmap (h->address, h->free_handle); + + g_free (h); + return res == 0; +} + +#endif diff --git a/mono/metadata/file-mmap-windows.c b/mono/metadata/file-mmap-windows.c new file mode 100644 index 0000000000000..78203ad47a81c --- /dev/null +++ b/mono/metadata/file-mmap-windows.c @@ -0,0 +1,70 @@ +/* + * file-mmap-posix.c: File mmap internal calls + * + * Author: + * Rodrigo Kumpera + * + * Copyright 2014 Xamarin Inc (http://www.xamarin.com) + */ + +#include + +#ifdef TARGET_WIN32 + +#include +#include +#include + + +#include +#include + +void * +mono_mmap_open_file (MonoString *path, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error) +{ + g_error ("No windows backend"); + return NULL; +} + +void * +mono_mmap_open_handle (void *handle, MonoString *mapName, gint64 *capacity, int access, int options, int *error) +{ + g_error ("No windows backend"); + return NULL; +} + +void +mono_mmap_close (void *mmap_handle) +{ + g_error ("No windows backend"); +} + +void +mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability) +{ + g_error ("No windows backend"); +} + +void +mono_mmap_flush (void *mmap_handle) +{ + g_error ("No windows backend"); +} + + + +int +mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address) +{ + g_error ("No windows backend"); + return 0; +} + +gboolean +mono_mmap_unmap (void *mmap_handle) +{ + g_error ("No windows backend"); + return TRUE; +} + +#endif diff --git a/mono/metadata/file-mmap.h b/mono/metadata/file-mmap.h new file mode 100644 index 0000000000000..1d750167254b4 --- /dev/null +++ b/mono/metadata/file-mmap.h @@ -0,0 +1,34 @@ +/* + * file-mmap.h: Managed mmap wrappers. + * + * Authors: + * Rodrigo Kumpera + * + * Copyright 2014 Xamarin Inc (http://www.xamarin.com) + */ + +#ifndef _MONO_METADATA_FILE_MMAP_H_ +#define _MONO_METADATA_FILE_MMAP_H_ + +#include +#include + +#include +#include +#include + +extern void mono_mmap_close (void *mmap_handle) MONO_INTERNAL; + +extern void mono_mmap_configure_inheritability (void *mmap_handle, gboolean inheritability) MONO_INTERNAL; + +extern void mono_mmap_flush (void *mmap_handle) MONO_INTERNAL; + +extern void *mono_mmap_open_file (MonoString *string, int mode, MonoString *mapName, gint64 *capacity, int access, int options, int *error) MONO_INTERNAL; + +extern void *mono_mmap_open_handle (void *handle, MonoString *mapName, gint64 *capacity, int access, int options, int *error) MONO_INTERNAL; + +extern int mono_mmap_map (void *handle, gint64 offset, gint64 *size, int access, void **mmap_handle, void **base_address) MONO_INTERNAL; + +extern gboolean mono_mmap_unmap (void *base_address) MONO_INTERNAL; + +#endif /* _MONO_METADATA_FILE_MMAP_H_ */ diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 0582798fc799f..028319dcfe03e 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -315,12 +315,14 @@ ICALL(INOW_1, "AddWatch", ves_icall_System_IO_InotifyWatcher_AddWatch) ICALL(INOW_2, "GetInotifyInstance", ves_icall_System_IO_InotifyWatcher_GetInotifyInstance) ICALL(INOW_3, "RemoveWatch", ves_icall_System_IO_InotifyWatcher_RemoveWatch) -#if defined (TARGET_IOS) || defined (TARGET_ANDROID) ICALL_TYPE(MMAPIMPL, "System.IO.MemoryMappedFiles.MemoryMapImpl", MMAPIMPL_1) -ICALL(MMAPIMPL_1, "mono_filesize_from_fd", mono_filesize_from_fd) -ICALL(MMAPIMPL_2, "mono_filesize_from_path", mono_filesize_from_path) -#endif - +ICALL(MMAPIMPL_1, "CloseMapping", mono_mmap_close) +ICALL(MMAPIMPL_2, "ConfigureHandleInheritability", mono_mmap_configure_inheritability) +ICALL(MMAPIMPL_3, "Flush", mono_mmap_flush) +ICALL(MMAPIMPL_4, "MapInternal", mono_mmap_map) +ICALL(MMAPIMPL_5, "OpenFileInternal", mono_mmap_open_file) +ICALL(MMAPIMPL_6, "OpenHandleInternal", mono_mmap_open_handle) +ICALL(MMAPIMPL_7, "Unmap", mono_mmap_unmap) ICALL_TYPE(MONOIO, "System.IO.MonoIO", MONOIO_1) ICALL(MONOIO_1, "Close(intptr,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Close) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index f861ff581f9dc..f711003792d87 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include