diff options
Diffstat (limited to 'native/jni/java-nio/java_nio_MappedByteBufferImpl.c')
-rw-r--r-- | native/jni/java-nio/java_nio_MappedByteBufferImpl.c | 216 |
1 files changed, 195 insertions, 21 deletions
diff --git a/native/jni/java-nio/java_nio_MappedByteBufferImpl.c b/native/jni/java-nio/java_nio_MappedByteBufferImpl.c index a12592e42..9e23bb2ee 100644 --- a/native/jni/java-nio/java_nio_MappedByteBufferImpl.c +++ b/native/jni/java-nio/java_nio_MappedByteBufferImpl.c @@ -1,5 +1,5 @@ /* java_nio_MappedByteBufferImpl.c - Native methods for MappedByteBufferImpl - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004,2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -15,8 +15,8 @@ General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA. +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. Linking this library statically or dynamically with other modules is making a combined work based on this library. Thus, the terms and @@ -43,41 +43,215 @@ exception statement from your version. */ #include "java_nio_MappedByteBufferImpl.h" +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif /* HAVE_SYS_MMAN_H */ + #define IO_EXCEPTION "java/io/IOException" +/* FIXME these are defined in gnu_java_nio_channels_FileChannelImpl + too; should be someplace common. */ +#define ALIGN_DOWN(p,s) ((p) - ((p) % (s))) +#define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s)))) + +/** + * Returns the memory page size of this platform. + * + * \return The page size. + */ +static long +get_pagesize (void) +{ + /* FIXME can we just try HAVE_SYSCONF? */ +#if defined(HAVE_GETPAGESIZE) + return getpagesize (); +#elif defined (HAVE_SYSCONF) + return sysconf (_SC_PAGESIZE); +#endif /* HAVE_GETPAGESIZE / HAVE_SYSCONF */ +} + +/** + * Retrieve the 'address' and 'cap' (the mapped size) fields of this + * buffer. + * + * This function will align the address down to the nearest page + * boundary, and the size up to the nearest page boundary. Thus, it is + * safe to use these values in 'mman' functions. + * + * \param env The JNI environment pointer. + * \param this The MappedByteBufferImpl instance. + * \param address A pointer to where the actual pointer should be + * stored. + * \param size A pointer to where the mapped region's size should be + * stored + */ +static void +get_raw_values (JNIEnv *env, jobject this, void **address, size_t *size) +{ + const long pagesize = get_pagesize (); + jfieldID MappedByteBufferImpl_address; + jfieldID MappedByteBufferImpl_size; + jfieldID RawData_data; + jobject MappedByteBufferImpl_address_value = NULL; + + *address = NULL; + /* 'address' is declared in java.nio.Buffer */ + MappedByteBufferImpl_address + = (*env)->GetFieldID (env, (*env)->GetObjectClass (env, this), + "address", "Lgnu/classpath/RawData;"); + /* 'cap' -- likewise, the capacity */ + MappedByteBufferImpl_size + = (*env)->GetFieldID (env, (*env)->GetObjectClass (env, this), + "cap", "I"); + if (MappedByteBufferImpl_address != NULL) + { + MappedByteBufferImpl_address_value = + (*env)->GetObjectField (env, this, MappedByteBufferImpl_address); + } + if ((*env)->ExceptionOccurred (env)) + return; + if (MappedByteBufferImpl_address_value == NULL) + { + JCL_ThrowException (env, "java/lang/NullPointerException", + "mapped address is NULL"); + return; + } + +#if (SIZEOF_VOID_P == 4) + RawData_data = + (*env)->GetFieldID (env, (*env)->GetObjectClass (env, MappedByteBufferImpl_address_value), + "data", "I"); + *address = (void *) + ALIGN_DOWN ((*env)->GetIntField (env, MappedByteBufferImpl_address_value, + RawData_data), pagesize); +#elif (SIZEOF_VOID_P == 8) + RawData_data = + (*env)->GetFieldID (env, (*env)->GetObjectClass (env, MappedByteBufferImpl_address_value), + "data", "J"); + *address = (void *) + ALIGN_DOWN ((*env)->GetLongField (env, MappedByteBufferImpl_address_value, + RawData_data), pagesize); +#endif /* SIZEOF_VOID_P */ + + *size = (size_t) + ALIGN_UP ((*env)->GetIntField (env, this, MappedByteBufferImpl_size), + pagesize); +} + JNIEXPORT void JNICALL -Java_java_nio_MappedByteBufferImpl_unmapImpl (JNIEnv * env, - jclass class - __attribute__ ((__unused__))) +Java_java_nio_MappedByteBufferImpl_unmapImpl (JNIEnv *env, jobject this) { +#ifdef HAVE_MUNMAP + void *address; + size_t size; + + get_raw_values (env, this, &address, &size); + + if (address == NULL) + return; + + if (munmap (address, size) != 0) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return; + } +#else JCL_ThrowException (env, IO_EXCEPTION, - "java.nio.MappedByteBufferImpl.unmapImpl(): not implemented"); + "unmapping files not implemented"); +#endif /* HAVE_MUNMAP */ } JNIEXPORT jboolean JNICALL -Java_java_nio_MappedByteBufferImpl_isLoadedImpl (JNIEnv * env, - jclass class - __attribute__ ((__unused__))) +Java_java_nio_MappedByteBufferImpl_isLoadedImpl (JNIEnv * env, jobject this) { - JCL_ThrowException (env, IO_EXCEPTION, - "java.nio.MappedByteBufferImpl.isLoadedImpl(): not implemented"); - return 0; +#ifdef HAVE_MINCORE + void *address; + size_t size; + char *vec; + size_t count, i; + const long pagesize = get_pagesize (); + + /* + * FIXME on Darwin this does not work if the mapped region is + * exactly one page long; i.e., 'mincore' tells us it isn't loaded. + */ + get_raw_values (env, this, &address, &size); + if (address == NULL) + return JNI_FALSE; + count = (size_t) ((size + pagesize - 1) / pagesize); + vec = (char *) malloc (count * sizeof (unsigned char)); + + /* + * Darwin (and BSD?) define argument 3 of 'mincore' to be 'char *', + * while GNU libc defines it to be 'unsigned char *'. Casting the + * argument to 'void *' fixes this, but not with C++. So you might + * be SOL if you compile this with g++ (!) on GNU with -Werror. + */ +#ifdef __cplusplus + if (mincore (address, size, vec) != 0) +#else + if (mincore (address, size, (void *) vec) != 0) +#endif /* __cplusplus */ + { + free (vec); + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + return JNI_FALSE; + } + + for (i = 0; i < count; i++) + { + if ((vec[i] & 1) == 0) + return JNI_FALSE; + } + return JNI_TRUE; +#else + return JNI_FALSE; +#endif } JNIEXPORT void JNICALL -Java_java_nio_MappedByteBufferImpl_loadImpl (JNIEnv * env, - jclass clazz - __attribute__ ((__unused__))) +Java_java_nio_MappedByteBufferImpl_loadImpl (JNIEnv *env, jobject this) { +#ifdef HAVE_MADVISE + void *address; + size_t size; + + get_raw_values (env, this, &address, &size); + if (address == NULL) + return; + + madvise (address, size, MADV_WILLNEED); +#else JCL_ThrowException (env, IO_EXCEPTION, - "java.nio.MappedByteBufferImpl.loadImpl(): not implemented"); + "forcing mapped files into core not implemented"); +#endif /* HAVE_MADVISE */ } JNIEXPORT void JNICALL -Java_java_nio_MappedByteBufferImpl_forceImpl (JNIEnv * env, - jclass class - __attribute__ ((__unused__))) +Java_java_nio_MappedByteBufferImpl_forceImpl (JNIEnv *env, jobject this) { +#ifdef HAVE_MSYNC + void *address; + size_t size; + + get_raw_values (env, this, &address, &size); + + if (address == NULL) + return; + + /* FIXME: is using MS_SYNC ok? Should we use MS_INVALIDATE? */ + if (msync (address, size, MS_SYNC) != 0) + { + JCL_ThrowException (env, IO_EXCEPTION, strerror (errno)); + } +#else JCL_ThrowException (env, IO_EXCEPTION, - "java.nio.MappedByteBufferImpl.forceImpl(): not implemented"); + "forcing mapped files to disk not implemented"); +#endif /* HAVE_MSYNC */ } |