From 22704a85cfe913e06acc349e0a3fdfd7dc433dda Mon Sep 17 00:00:00 2001 From: jfrijters Date: Mon, 11 Apr 2005 08:05:42 +0000 Subject: [PATCH] *** empty log message *** --- .../java/nio/channels/FileChannelImpl.java | 26 +++-- classpath/map.xml | 11 ++ native/os.c | 18 ++- runtime/classpath.cs | 109 ++++++++++++++++++ 4 files changed, 155 insertions(+), 9 deletions(-) diff --git a/classpath/gnu/java/nio/channels/FileChannelImpl.java b/classpath/gnu/java/nio/channels/FileChannelImpl.java index 4e9f98d3..ce16b321 100644 --- a/classpath/gnu/java/nio/channels/FileChannelImpl.java +++ b/classpath/gnu/java/nio/channels/FileChannelImpl.java @@ -55,7 +55,7 @@ import java.nio.channels.WritableByteChannel; import cli.System.Console; import cli.System.IO.*; -import ikvm.lang.CIL; +import gnu.classpath.RawData; /** * This file is not user visible ! @@ -138,7 +138,7 @@ public final class FileChannelImpl extends FileChannel if(false) throw new cli.System.UnauthorizedAccessException(); if(false) throw new cli.System.ArgumentException(); if(false) throw new cli.System.NotSupportedException(); - return new cli.System.IO.FileStream(demanglePath(path), FileMode.wrap(fileMode), FileAccess.wrap(fileAccess), FileShare.wrap(FileShare.ReadWrite), 1, false); + return new FileStream(demanglePath(path), FileMode.wrap(fileMode), FileAccess.wrap(fileAccess), FileShare.wrap(FileShare.ReadWrite), 1, false); } catch(cli.System.Security.SecurityException x1) { @@ -514,12 +514,22 @@ public final class FileChannelImpl extends FileChannel return result; } - public MappedByteBuffer mapImpl (char mode, long position, int size) throws IOException + private MappedByteBuffer mapImpl (char mode, long position, int size) throws IOException { - // TODO - throw new IOException("not implemented"); + if (! (stream instanceof FileStream)) + throw new IllegalArgumentException("only file streams can be mapped"); + + RawData address = mapViewOfFile((FileStream)stream, mode != 'r', mode == 'c', position, size); + if (address == null) + throw new IOException("file mapping failed"); + return createMappedByteBufferImpl(address, size, mode == 'r'); } + private static native RawData mapViewOfFile(FileStream stream, boolean writeable, boolean copy_on_write, long position, int size); + + // implementation in map.xml to bypass Java access checking + private static native MappedByteBuffer createMappedByteBufferImpl(RawData address, int size, boolean readonly); + public MappedByteBuffer map (FileChannel.MapMode mode, long position, long size) throws IOException @@ -566,16 +576,16 @@ public final class FileChannelImpl extends FileChannel throw new IOException(x.getMessage()); } - if (stream instanceof cli.System.IO.FileStream) + if (stream instanceof FileStream) { - if(!flush(((cli.System.IO.FileStream)stream))) + if(!flush(((FileStream)stream))) { throw new IOException(); } } } - private static native boolean flush(cli.System.IO.FileStream fs); + private static native boolean flush(FileStream fs); // like transferTo, but with a count of less than 2Gbytes private int smallTransferTo (long position, int count, diff --git a/classpath/map.xml b/classpath/map.xml index 4a6ab580..892212df 100644 --- a/classpath/map.xml +++ b/classpath/map.xml @@ -929,6 +929,17 @@ + + + + + + + + + + + diff --git a/native/os.c b/native/os.c index 9098d269..cc90658c 100644 --- a/native/os.c +++ b/native/os.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 Jeroen Frijters + Copyright (C) 2004, 2005 Jeroen Frijters This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -57,6 +57,7 @@ } #else #include + #include #include "jni.h" JNIEXPORT void* JNICALL ikvm_LoadLibrary(char* psz) @@ -80,4 +81,19 @@ else return NULL; } + + JNIEXPORT void* JNICALL ikvm_mmap(int fd, jboolean writeable, jboolean copy_on_write, jlong position, jint size) + { + return mmap(0, size, writeable ? PROT_WRITE | PROT_READ : PROT_READ, copy_on_write ? MAP_PRIVATE : MAP_SHARED, fd, position); + } + + JNIEXPORT int JNICALL ikvm_munmap(void* address, jint size) + { + return munmap(address, size); + } + + JNIEXPORT int JNICALL ikvm_msync(void* address, jint size) + { + return msync(address, size, MS_SYNC); + } #endif diff --git a/runtime/classpath.cs b/runtime/classpath.cs index f712ad8e..d2f6e45c 100644 --- a/runtime/classpath.cs +++ b/runtime/classpath.cs @@ -34,6 +34,7 @@ using IKVM.Runtime; using IKVM.Internal; using NetSystem = System; +using RawData = gnu.classpath.RawData; namespace IKVM.NativeCode.java { @@ -1256,6 +1257,7 @@ namespace IKVM.NativeCode.gnu.java.nio.channels { public class FileChannelImpl { + internal static readonly bool runningOnWindows; private static readonly MethodInfo mono_1_0_Flush; private static readonly MethodInfo mono_1_1_Flush; @@ -1264,9 +1266,11 @@ namespace IKVM.NativeCode.gnu.java.nio.channels try { FlushFileBuffers(new IntPtr(-1)); + runningOnWindows = true; } catch(TypeLoadException) { + runningOnWindows = false; // If we end up here, we're not running on Windows, so we'll try two Mono specific methods. // TODO convert this to Mono.Unix Type t = Type.GetType("Mono.Posix.Syscall, Mono.Posix"); @@ -1324,6 +1328,111 @@ namespace IKVM.NativeCode.gnu.java.nio.channels [DllImport("kernel32")] private extern static bool FlushFileBuffers(IntPtr handle); + + public static RawData mapViewOfFile(FileStream fs, bool writeable, bool copy_on_write, long position, int size) + { + try + { + if(runningOnWindows) + { + const uint PAGE_READONLY = 2; + const uint PAGE_READWRITE = 4; + const uint PAGE_WRITECOPY = 8; + IntPtr hFileMapping = CreateFileMapping(fs.Handle, IntPtr.Zero, + copy_on_write ? PAGE_WRITECOPY : (writeable ? PAGE_READWRITE : PAGE_READONLY), + 0, (uint)size, null); + if(hFileMapping == IntPtr.Zero) + { + return null; + } + const uint FILE_MAP_WRITE = 2; + const uint FILE_MAP_READ = 4; + const uint FILE_MAP_COPY = 1; + IntPtr p = MapViewOfFile(hFileMapping, + copy_on_write ? FILE_MAP_COPY : (writeable ? FILE_MAP_WRITE : FILE_MAP_READ), + (uint)(position >> 32), (uint)position, (uint)size); + CloseHandle(hFileMapping); + if(p == IntPtr.Zero) + { + return null; + } + return new RawData(p); + } + else + { + return new RawData(ikvm_mmap(fs.Handle, writeable, copy_on_write, position, size)); + } + } + finally + { + GC.KeepAlive(fs); + } + } + + [DllImport("ikvm-native")] + private extern static IntPtr ikvm_mmap(IntPtr handle, bool writeable, bool copy_on_write, long position, int size); + + [DllImport("kernel32")] + private extern static bool CloseHandle(IntPtr handle); + + [DllImport("kernel32")] + private extern static IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName); + + [DllImport("kernel32")] + private extern static IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap); + } +} + +namespace IKVM.NativeCode.java.nio +{ + public class MappedByteBufferImpl + { + public static void unmapImpl(object thiz) + { + IntPtr address = JVM.Library.getDirectBufferAddress(thiz); + if(gnu.java.nio.channels.FileChannelImpl.runningOnWindows) + { + UnmapViewOfFile(address); + } + else + { + ikvm_munmap(address, JVM.Library.getDirectBufferCapacity(thiz)); + } + } + + [DllImport("ikvm-native")] + private extern static int ikvm_munmap(IntPtr address, int size); + + [DllImport("ikvm-native")] + private extern static int ikvm_msync(IntPtr address, int size); + + [DllImport("kernel32")] + private extern static bool UnmapViewOfFile(IntPtr lpBaseAddress); + + [DllImport("kernel32")] + private extern static bool FlushViewOfFile(IntPtr lpBaseAddress, uint dwNumberOfBytesToFlush); + + public static bool isLoadedImpl(object thiz) + { + return false; + } + + public static void loadImpl(object thiz) + { + } + + public static void forceImpl(object thiz) + { + IntPtr address = JVM.Library.getDirectBufferAddress(thiz); + if(gnu.java.nio.channels.FileChannelImpl.runningOnWindows) + { + FlushViewOfFile(address, 0); + } + else + { + ikvm_msync(address, JVM.Library.getDirectBufferCapacity(thiz)); + } + } } }