This one contains the VMSelector code which was adopted from GCJ.
Azureus starts to work with this (and shows a couple of other bugs in Classpath ;) )
2005-03-18 Robert Schuster <[EMAIL PROTECTED]>
* native/jni/java-nio/gnu_java_nio_VMSelector.c: Implemented Java_gnu_java_nio_VMSelector_select. * configure.ac: Added check for sys/select.h and strerro_r().
cu Robert
Index: configure.ac =================================================================== RCS file: /cvsroot/classpath/classpath/configure.ac,v retrieving revision 1.76 diff -u -r1.76 configure.ac --- configure.ac 13 Mar 2005 21:22:53 -0000 1.76 +++ configure.ac 18 Mar 2005 03:02:27 -0000 @@ -145,6 +145,7 @@ AC_CHECK_HEADERS([unistd.h sys/types.h sys/config.h sys/ioctl.h asm/ioctls.h]) AC_CHECK_HEADERS([inttypes.h stdint.h utime.h sys/utime.h sys/filio.h]) AC_CHECK_HEADERS([sys/time.h]) + AC_CHECK_HEADERS([sys/select.h]) dnl Check for crt_externs.h on Darwin. AC_CHECK_HEADERS([crt_externs.h]) @@ -159,6 +160,7 @@ AC_CHECK_FUNCS([getsockname sizeof getpeername bind listen accept]) AC_CHECK_FUNCS([recvfrom send sendto setsockopt getsockopt time mktime]) AC_CHECK_FUNCS([localtime_r]) + AC_CHECK_FUNCS([strerror_r]) AC_HEADER_TIME AC_STRUCT_TM Index: native/jni/java-nio/gnu_java_nio_VMSelector.c =================================================================== RCS file: /cvsroot/classpath/classpath/native/jni/java-nio/gnu_java_nio_VMSelector.c,v retrieving revision 1.2 diff -u -r1.2 gnu_java_nio_VMSelector.c --- native/jni/java-nio/gnu_java_nio_VMSelector.c 26 Oct 2004 20:26:03 -0000 1.2 +++ native/jni/java-nio/gnu_java_nio_VMSelector.c 18 Mar 2005 03:02:27 -0000 @@ -1,5 +1,5 @@ /* gnu_java_nio_VMSelector.c - Native methods for SelectorImpl class - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -35,6 +35,11 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ +#include <sys/select.h> +#include <sys/time.h> + +#include <string.h> + #include <config.h> #include <errno.h> @@ -43,21 +48,234 @@ #include "gnu_java_nio_VMSelector.h" -#define IO_EXCEPTION "java/io/IOException" +/* Amount of characters in the error message buffer for strerror_r. */ +#define BUF_SIZE 250 + +void +helper_put_filedescriptors(JNIEnv *, jintArray, fd_set *, int *); + +void +helper_get_filedescriptors (JNIEnv *, jintArray*, fd_set *); + +void +helper_reset (JNIEnv *, jintArray*); + +int +helper_select (JNIEnv *, jclass, jmethodID, + int, fd_set *, fd_set *, fd_set *, + struct timeval *); + +void +helper_put_filedescriptors(JNIEnv *env, jintArray fdArray, fd_set *fds, int *max_fd) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements(env, fdArray, 0); + int size = (*env)->GetArrayLength(env, fdArray); + int index, fd; + + for( index = 0; index < size; index++) + { + fd = tmpFDArray [index]; + + if (fd > 0) + { + FD_SET (tmpFDArray [index], fds); + + if (tmpFDArray [index] > (*max_fd)) + (*max_fd) = tmpFDArray [index]; + } + } +} + +void +helper_get_filedescriptors (JNIEnv *env, jintArray* fdArray, fd_set *fds) +{ + jint *tmpFDArray = (*env)->GetIntArrayElements(env, fdArray, 0); + int size = (*env)->GetArrayLength(env, fdArray); + int index, fd; + + for (index = 0; index < size; index++) + { + fd = tmpFDArray [index]; + if (fd < 0 || !FD_ISSET (fd, fds)) + tmpFDArray [index] = 0; + } +} + +void +helper_reset (JNIEnv *env, jintArray* fdArray) +{ + jint* tmpFDArray = (*env)->GetIntArrayElements(env, fdArray, 0); + int size = (*env)->GetArrayLength(env, fdArray); + int index; + + for (index = 0; index < size; index++) + tmpFDArray [index] = 0; +} + +/* A wrapper for select() which ignores EINTR. + * Taken from gclib's posix.cc + */ +int +helper_select (JNIEnv *env, jclass thread_class, jmethodID thread_interrupted, + int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ +#ifdef HAVE_SYS_SELECT_H + /* If we have a timeout, compute the absolute ending time. */ + struct timeval end, delay, after; + int r; + + if (timeout) + { + gettimeofday (&end, NULL); + + end.tv_usec += timeout->tv_usec; + + if (end.tv_usec >= 1000000) + { + ++end.tv_sec; + end.tv_usec -= 1000000; + } + + end.tv_sec += timeout->tv_sec; + delay = *timeout; + } + else + { + /* Placate compiler. */ + delay.tv_sec = delay.tv_usec = 0; + } + + while (1) + { + r = select (n, readfds, writefds, exceptfds, + timeout ? &delay : NULL); + + if (r != -1 || errno != EINTR) + return r; + + /* Here we know we got EINTR. */ + if ( (*env)->CallStaticBooleanMethod(env, thread_class, thread_interrupted) ) + { + return EINTR; + } + + if (timeout) + { + gettimeofday (&after, NULL); + + /* Now compute new timeout argument. */ + delay.tv_usec = end.tv_usec - after.tv_usec; + delay.tv_sec = end.tv_sec - after.tv_sec; + + if (delay.tv_usec < 0) + { + --delay.tv_sec; + delay.tv_usec += 1000000; + } + + if (delay.tv_sec < 0) + { + /* We assume that the user wants a valid select() call + * more than precise timing. So if we get a series of + * EINTR we just keep trying with delay 0 until we get a + * valid result. + */ + delay.tv_sec = 0; + } + } + } +#else /* HAVE_SYS_SELECT_H */ + return 0; +#endif + +} JNIEXPORT jint JNICALL Java_gnu_java_nio_VMSelector_select (JNIEnv *env, jclass obj __attribute__ ((__unused__)), - jintArray read - __attribute__ ((__unused__)), - jintArray write - __attribute__ ((__unused__)), - jintArray except - __attribute__ ((__unused__)), - jlong timeout - __attribute__ ((__unused__))) + jintArray read, + jintArray write, + jintArray except, + jlong timeout) { - JCL_ThrowException (env, IO_EXCEPTION, "gnu.java.nio.VMSelector.select(): not implemented"); - return 0; + jint result; + jclass thread_class = (*env)->FindClass(env, "java/lang/Thread"); + jmethodID thread_current_thread = (*env)->GetStaticMethodID(env, thread_class, "currentThread", "()Ljava/lang/Thread;"); + jmethodID thread_interrupt = (*env)->GetMethodID(env, thread_class, "interrupt", "()V"); + jmethodID thread_interrupted = (*env)->GetMethodID(env, thread_class, "interrupted", "()Z"); + jobject current_thread; + int max_fd = 0; + fd_set read_fds; + fd_set write_fds; + fd_set except_fds; + struct timeval real_time_data; + struct timeval *time_data = NULL; + char message_buf[BUF_SIZE+1]; + + /* If a legal timeout value isn't given, use NULL. + * This means an infinite timeout. The specification + * also says that a zero timeout should be treated + * as infinite. Otherwise (if the timeout value is legal), + * fill our timeval struct and use it for the select. + */ + if (timeout > 0) + { + real_time_data.tv_sec = timeout / 1000; + real_time_data.tv_usec = (timeout % 1000) * 1000; + time_data = &real_time_data; + } + + /* Reset all fd_set structures */ + FD_ZERO (&read_fds); + FD_ZERO (&write_fds); + FD_ZERO (&except_fds); + + /* Fill the fd_set data structures for the _Jv_select() call. */ + helper_put_filedescriptors (env, read, &read_fds, &max_fd); + helper_put_filedescriptors (env, write, &write_fds, &max_fd); + helper_put_filedescriptors (env, except, &except_fds, &max_fd); + + /* Actually do the select */ + result = helper_select (env, thread_class, thread_interrupted, max_fd + 1, &read_fds, &write_fds, + &except_fds, time_data); + + if( result == EINTR ) { + /* The behavior of JRE 1.4.1 is that no exception is thrown + * when the thread is interrupted, but the thread's interrupt + * status is set. Clear all of our select sets and return 0, + * indicating that nothing was selected. + */ + current_thread = (*env)->CallStaticObjectMethod(env, thread_class, thread_current_thread); + (*env)->CallVoidMethod(env, current_thread, thread_interrupt); + + helper_reset (env, read); + helper_reset (env, write); + helper_reset (env, except); + + return 0; + } + + if (result < 0) + { + if( strerror_r(errno, message_buf, BUF_SIZE) ) + { + /* This would mean that message_buf was to small + * to hold the error message. + */ + JCL_ThrowException(env, "java/lang/InternalError", + "Not enough space in message buffer."); + } + + JCL_ThrowException (env, "java/io/IOException", message_buf); + return 0; + } + + /* Set the file descriptors according to the values returned from select(). */ + helper_get_filedescriptors (env, read, &read_fds); + helper_get_filedescriptors (env, write, &write_fds); + helper_get_filedescriptors (env, except, &except_fds); + + return result; }
_______________________________________________ Classpath-patches mailing list Classpath-patches@gnu.org http://lists.gnu.org/mailman/listinfo/classpath-patches