classpath-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[cp-patches] FYI: final VMSelector patch


From: Robert Schuster
Subject: [cp-patches] FYI: final VMSelector patch
Date: Fri, 18 Mar 2005 04:09:07 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; de-AT; rv:1.7.5) Gecko/20050107

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  <address@hidden>

   * 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;
 }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]