Casey Marshall wrote:
> Note, too, that you can disable epoll (or kqueue) at run time by setting
> the system property "gnu.java.nio.selectorImpl" to any string other than
> "epoll" (or "kqueue"), and use the old select() based version. Maybe we
> can detect ENOSYS at run time, and disable epoll selectors.
> 

OK. I've attached a revised patch that tries epoll selectors if support
was compiled in, and if that fails with ENOSYS, we set a flag that
disables trying it again. In any case, if creating an epoll selector
fails, we fall back on the select- (actually, whatever backs VMSelector)
based version.

Warning, I've neither tried, nor tried to compile, this yet.
### Eclipse Workspace Patch 1.0
#P classpath
Index: include/Makefile.am
===================================================================
RCS file: /cvsroot/classpath/classpath/include/Makefile.am,v
retrieving revision 1.70
diff -u -r1.70 Makefile.am
--- include/Makefile.am 17 Sep 2006 07:31:41 -0000      1.70
+++ include/Makefile.am 19 Sep 2006 21:46:56 -0000
@@ -128,6 +128,7 @@
 $(top_srcdir)/include/gnu_java_net_VMPlainDatagramSocketImpl.h \
 $(top_srcdir)/include/gnu_java_net_VMPlainSocketImpl.h \
 $(top_srcdir)/include/gnu_java_net_local_LocalSocketImpl.h \
+$(top_srcdir)/include/gnu_java_nio_EpollSelectorImpl.h \
 $(top_srcdir)/include/gnu_java_nio_FileChannelImpl.h \
 $(top_srcdir)/include/gnu_java_nio_KqueueSelectorImpl.h \
 $(top_srcdir)/include/gnu_java_nio_VMChannel.h \
@@ -227,6 +228,9 @@
 $(top_srcdir)/include/gnu_java_nio_KqueueSelectorImpl.h: 
$(top_srcdir)/gnu/java/nio/KqueueSelectorImpl.java
        $(JAVAH) -o $@ gnu.java.nio.KqueueSelectorImpl
 
+$(top_srcdir)/include/gnu_java_nio_EpollSelectorImpl.h: 
$(top_srcdir)/gnu/java/nio/EpollSelectorImpl.java
+       $(JAVAH) -o $@ gnu.java.nio.EpollSelectorImpl
+
 $(top_srcdir)/include/gnu_java_nio_charset_iconv_IconvDecoder.h: 
$(top_srcdir)/gnu/java/nio/charset/iconv/IconvDecoder.java
        $(JAVAH) -o $@ gnu.java.nio.charset.iconv.IconvDecoder
 $(top_srcdir)/include/gnu_java_nio_charset_iconv_IconvEncoder.h: 
$(top_srcdir)/gnu/java/nio/charset/iconv/IconvEncoder.java
Index: gnu/java/nio/SelectorProviderImpl.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/nio/SelectorProviderImpl.java,v
retrieving revision 1.9
diff -u -r1.9 SelectorProviderImpl.java
--- gnu/java/nio/SelectorProviderImpl.java      17 Sep 2006 07:31:41 -0000      
1.9
+++ gnu/java/nio/SelectorProviderImpl.java      19 Sep 2006 21:46:56 -0000
@@ -53,6 +53,7 @@
   private static final String SELECTOR_IMPL_KQUEUE = "kqueue";
   private static final String SELECTOR_IMPL_EPOLL = "epoll";
   private static final String SELECTOR_IMPL = "gnu.java.nio.selectorImpl";
+  private static boolean epoll_failed = false;
   
   public SelectorProviderImpl ()
   {
@@ -76,12 +77,31 @@
     String selectorImpl = "default";
     if (KqueueSelectorImpl.kqueue_supported())
       selectorImpl = SELECTOR_IMPL_KQUEUE;
+    if (EpollSelectorImpl.epoll_supported() && !epoll_failed)
+      selectorImpl = SELECTOR_IMPL_EPOLL;
     selectorImpl = SystemProperties.getProperty(SELECTOR_IMPL, selectorImpl);
 
     if (selectorImpl.equals(SELECTOR_IMPL_KQUEUE))
       return new KqueueSelectorImpl(this);
+
     if (selectorImpl.equals(SELECTOR_IMPL_EPOLL))
-      throw new UnsupportedOperationException("epoll selector not yet 
implemented");
+      {
+        // We jump through these hoops because even though epoll may look
+        // like it's available (sys/epoll.h exists, and you can link against
+        // all the epoll functions) it may not be available in the kernel
+        // (especially 2.4 kernels), meaning you will get ENOSYS at run time.
+        //
+        // Madness!
+        try
+          {
+            return new EpollSelectorImpl(this);
+          }
+        catch (InternalError e)
+          {
+            // epoll_create throws this on ENOSYS.
+            epoll_failed = true;
+          }
+      }
 
     return new SelectorImpl (this);
   }
Index: configure.ac
===================================================================
RCS file: /cvsroot/classpath/classpath/configure.ac,v
retrieving revision 1.183
diff -u -r1.183 configure.ac
--- configure.ac        17 Sep 2006 07:31:41 -0000      1.183
+++ configure.ac        19 Sep 2006 21:46:56 -0000
@@ -357,7 +357,7 @@
                     fcntl.h \
                    sys/mman.h \
                    magic.h \
-                    sys/event.h])
+                    sys/event.h sys/epoll.h])
 
   AC_EGREP_HEADER(uint32_t, stdint.h, AC_DEFINE(HAVE_INT32_DEFINED, 1, [Define 
to 1 if you have uint32_t]))
   AC_EGREP_HEADER(uint32_t, inttypes.h, AC_DEFINE(HAVE_INT32_DEFINED, 1, 
[Define to 1 if you have uint32_t]))
@@ -375,7 +375,7 @@
                  mmap munmap mincore msync madvise getpagesize sysconf \
                  lstat readlink \
                  inet_aton inet_addr inet_pton \
-                 getifaddrs kqueue kevent])
+                 getifaddrs kqueue kevent epoll_create])
 
   LIBMAGIC=
   AC_CHECK_LIB(magic, magic_open, LIBMAGIC=-lmagic)
Index: native/jni/java-nio/Makefile.am
===================================================================
RCS file: /cvsroot/classpath/classpath/native/jni/java-nio/Makefile.am,v
retrieving revision 1.25
diff -u -r1.25 Makefile.am
--- native/jni/java-nio/Makefile.am     17 Sep 2006 07:31:43 -0000      1.25
+++ native/jni/java-nio/Makefile.am     19 Sep 2006 21:46:56 -0000
@@ -7,6 +7,7 @@
                        gnu_java_nio_charset_iconv_IconvEncoder.c \
                        java_nio_MappedByteBufferImpl.c \
                        java_nio_VMDirectByteBuffer.c \
+                       gnu_java_nio_EpollSelectorImpl.c \
                        gnu_java_nio_KqueueSelectorImpl.c
 
 libjavanio_la_LIBADD = $(top_builddir)/native/jni/classpath/jcl.lo \
Index: include/gnu_java_nio_EpollSelectorImpl.h
===================================================================
RCS file: include/gnu_java_nio_EpollSelectorImpl.h
diff -N include/gnu_java_nio_EpollSelectorImpl.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ include/gnu_java_nio_EpollSelectorImpl.h    1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,95 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class gnu_java_nio_EpollSelectorImpl */
+
+#ifndef _Included_gnu_java_nio_EpollSelectorImpl
+#define _Included_gnu_java_nio_EpollSelectorImpl
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef gnu_java_nio_EpollSelectorImpl_DEFAULT_EPOLL_SIZE
+#define gnu_java_nio_EpollSelectorImpl_DEFAULT_EPOLL_SIZE 128L
+#undef gnu_java_nio_EpollSelectorImpl_OP_ACCEPT
+#define gnu_java_nio_EpollSelectorImpl_OP_ACCEPT 16L
+#undef gnu_java_nio_EpollSelectorImpl_OP_CONNECT
+#define gnu_java_nio_EpollSelectorImpl_OP_CONNECT 8L
+#undef gnu_java_nio_EpollSelectorImpl_OP_READ
+#define gnu_java_nio_EpollSelectorImpl_OP_READ 1L
+#undef gnu_java_nio_EpollSelectorImpl_OP_WRITE
+#define gnu_java_nio_EpollSelectorImpl_OP_WRITE 4L
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_supported
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_gnu_java_nio_EpollSelectorImpl_epoll_1supported
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    sizeof_struct
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_nio_EpollSelectorImpl_sizeof_1struct
+  (JNIEnv *, jclass);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_create
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_nio_EpollSelectorImpl_epoll_1create
+  (JNIEnv *, jclass, jint);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_add
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_gnu_java_nio_EpollSelectorImpl_epoll_1add
+  (JNIEnv *, jclass, jint, jint, jint);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_modify
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL Java_gnu_java_nio_EpollSelectorImpl_epoll_1modify
+  (JNIEnv *, jclass, jint, jint, jint);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_delete
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_gnu_java_nio_EpollSelectorImpl_epoll_1delete
+  (JNIEnv *, jclass, jint, jint);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_wait
+ * Signature: (ILjava/nio/ByteBuffer;II)I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_nio_EpollSelectorImpl_epoll_1wait
+  (JNIEnv *, jclass, jint, jobject, jint, jint);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    selected_fd
+ * Signature: (Ljava/nio/ByteBuffer;)I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_nio_EpollSelectorImpl_selected_1fd
+  (JNIEnv *, jclass, jobject);
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    selected_ops
+ * Signature: (Ljava/nio/ByteBuffer;)I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_nio_EpollSelectorImpl_selected_1ops
+  (JNIEnv *, jclass, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: gnu/java/nio/EpollSelectorImpl.java
===================================================================
RCS file: gnu/java/nio/EpollSelectorImpl.java
diff -N gnu/java/nio/EpollSelectorImpl.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gnu/java/nio/EpollSelectorImpl.java 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,342 @@
+/* EpollSelectorImpl.java -- selector implementation using epoll
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+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., 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
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import gnu.classpath.Configuration;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * An implementation of [EMAIL PROTECTED] Selector} that uses the epoll event
+ * notification mechanism on GNU/Linux.
+ *
+ * @author Casey Marshall ([EMAIL PROTECTED])
+ */
+public class EpollSelectorImpl extends AbstractSelector
+{
+  // XXX is this reasonable? Does it matter?
+  private static final int DEFAULT_EPOLL_SIZE = 128;
+  private static final int sizeof_struct_epoll_event;
+  
+  private static final int OP_ACCEPT  = SelectionKey.OP_ACCEPT;
+  private static final int OP_CONNECT = SelectionKey.OP_CONNECT;
+  private static final int OP_READ    = SelectionKey.OP_READ;
+  private static final int OP_WRITE   = SelectionKey.OP_WRITE;
+  
+  /** our epoll file descriptor. */
+  private int epoll_fd;
+  
+  private final HashMap keys;
+  private Set selectedKeys;
+  private final Set cancelledKeys;
+  private Thread waitingThread;
+
+  static
+  {
+    if (Configuration.INIT_LOAD_LIBRARY)
+      System.loadLibrary("javanio");
+    
+    if (epoll_supported())
+      sizeof_struct_epoll_event = sizeof_struct();
+    else
+      sizeof_struct_epoll_event = -1;
+  }
+  
+  public EpollSelectorImpl(SelectorProvider provider)
+    throws IOException
+  {
+    super(provider);
+    epoll_fd = epoll_create(DEFAULT_EPOLL_SIZE);
+    keys = new HashMap();
+    selectedKeys = null;
+    cancelledKeys = new HashSet();
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.Selector#keys()
+   */
+  public Set keys()
+  {
+    return new HashSet(keys.values());
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.Selector#select()
+   */
+  public int select() throws IOException
+  {
+    return doSelect(-1);
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.Selector#select(long)
+   */
+  public int select(long timeout) throws IOException
+  {
+    if (timeout > Integer.MAX_VALUE)
+      throw new IllegalArgumentException("timeout is too large");
+    if (timeout < 0)
+      throw new IllegalArgumentException("invalid timeout");
+    return doSelect((int) timeout);
+  }
+    
+  private int doSelect(int timeout) throws IOException
+  {
+    synchronized (keys)
+    {
+      synchronized (cancelledKeys)
+      {
+        for (Iterator it = cancelledKeys.iterator(); it.hasNext(); )
+          {
+            EpollSelectionKeyImpl key = (EpollSelectionKeyImpl) it.next();
+            epoll_delete(epoll_fd, key.fd);
+            key.valid = false;
+            keys.remove(new Integer(key.fd));
+          }
+
+        ByteBuffer selected =
+          ByteBuffer.allocateDirect(keys.size() * sizeof_struct_epoll_event);
+      
+        waitingThread = Thread.currentThread();
+        int ret = epoll_wait(epoll_fd, selected, keys.size(), timeout);
+        Thread.interrupted();
+        waitingThread = null;
+      
+        HashSet s = new HashSet(ret);
+        for (int i = 0; i < ret; i++)
+          {
+            selected.position(i * sizeof_struct_epoll_event);
+            ByteBuffer b = selected.slice();
+            int fd = selected_fd(b);
+            EpollSelectionKeyImpl key
+              = (EpollSelectionKeyImpl) keys.get(new Integer(fd));
+            if (key == null)
+              throw new IOException("fd was selected, but no key found");
+            key.selectedOps = selected_ops(b) & key.interestOps;
+            s.add(key);
+          }
+        selectedKeys = s;
+        return ret;
+      }
+    }
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.Selector#selectedKeys()
+   */
+  public Set selectedKeys()
+  {
+    return selectedKeys;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.Selector#selectNow()
+   */
+  public int selectNow() throws IOException
+  {
+    return doSelect(0);
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.Selector#wakeup()
+   */
+  public Selector wakeup()
+  {
+    try
+      {
+        waitingThread.interrupt();
+      }
+    catch (NullPointerException npe)
+      {
+      }
+    return this;
+  }
+  
+  /* (non-Javadoc)
+   * @see java.nio.channels.spi.AbstractSelector#implCloseSelector()
+   */
+  protected void implCloseSelector() throws IOException
+  {
+    VMChannel.close(epoll_fd);
+  }
+
+  /* (non-Javadoc)
+   * @see 
java.nio.channels.spi.AbstractSelector#register(java.nio.channels.spi.AbstractSelectableChannel,
 int, java.lang.Object)
+   */
+  protected SelectionKey register(AbstractSelectableChannel ch, int ops, 
Object att)
+  {
+    if (!(ch instanceof VMChannelOwner))
+      throw new IllegalArgumentException("unsupported channel type");
+
+    VMChannel channel = ((VMChannelOwner) ch).getVMChannel();
+    try
+      {
+        int native_fd = channel.getState().getNativeFD();
+        synchronized (keys)
+        {
+          if (keys.containsKey(new Integer(native_fd)))
+            throw new IllegalArgumentException("channel already registered");
+          EpollSelectionKeyImpl result =
+            new EpollSelectionKeyImpl(this, ch, native_fd);
+          if ((ops & ~(ch.validOps())) != 0)
+            throw new IllegalArgumentException("invalid ops for channel");
+          result.interestOps = ops;
+          result.selectedOps = 0;
+          result.valid = true;
+          result.attach(att);
+          result.key = System.identityHashCode(result);
+          epoll_add(epoll_fd, result.fd, ops);
+          keys.put(new Integer(native_fd), result);
+          return result;
+        }
+      }
+    catch (IOException ioe)
+      {
+        throw new IllegalArgumentException(ioe);
+      }
+  }
+  
+  void epoll_modify(EpollSelectionKeyImpl key, int ops) throws IOException
+  {
+    epoll_modify(epoll_fd, key.fd, ops);
+  }
+  
+  void cancel(EpollSelectionKeyImpl key)
+  {
+    synchronized (cancelledKeys)
+    {
+      cancelledKeys.add(key);
+    }
+  }
+  
+  /**
+   * Tell if epoll is supported by this system, and support was compiled in.
+   *
+   * @return True if this system supports event notification with epoll.
+   */
+  public static native boolean epoll_supported();
+
+
+  /**
+   * Returns the size of `struct epoll_event'.
+   *
+   * @return The size of `struct epoll_event'.
+   */
+  private static native int sizeof_struct();
+  
+ 
+  /**
+   * Open a new epoll file descriptor.
+   *
+   * @param size The size hint for the new epoll descriptor.
+   * @return The new file descriptor integer.
+   * @throws IOException If allocating a new epoll descriptor fails.
+   */
+  private static native int epoll_create(int size) throws IOException;
+  
+  /**
+   * Add a file descriptor to this selector.
+   *
+   * @param efd The epoll file descriptor.
+   * @param fd  The file descriptor to add (or modify).
+   * @param ops The interest opts.
+   */
+  private static native void epoll_add(int efd, int fd, int ops)
+    throws IOException;
+  
+  /**
+   * Modify the interest ops of the key selecting for the given FD.
+   *
+   * @param efd The epoll file descriptor.
+   * @param fd  The file descriptor to modify.
+   * @param ops The ops.
+   * @throws IOException
+   */
+  private static native void epoll_modify(int efd, int fd, int ops)
+    throws IOException;
+  
+  /**
+   * Remove a file descriptor from this selector.
+   *
+   * @param efd The epoll file descriptor.
+   * @param fd  The file descriptor.
+   * @throws IOException
+   */
+  private static native void epoll_delete(int efd, int fd) throws IOException;
+  
+  /**
+   * Select events.
+   *
+   * @param efd     The epoll file descriptor.
+   * @param state   The buffer to hold selected events.
+   * @param n       The number of events that may be put in `state'.
+   * @param timeout The timeout.
+   * @return The number of events selected.
+   * @throws IOException
+   */
+  private static native int epoll_wait(int efd, ByteBuffer state, int n, int 
timeout)
+    throws IOException;
+  
+  /**
+   * Fetch the fd value from a selected struct epoll_event.
+   *
+   * @param struct The direct buffer holding the struct.
+   * @return The fd value.
+   */
+  private static native int selected_fd(ByteBuffer struct);
+  
+  /**
+   * Fetch the enabled operations from a selected struct epoll_event.
+   *
+   * @param struct The direct buffer holding the struct.
+   * @return The selected operations.
+   */
+  private static native int selected_ops(ByteBuffer struct);
+}
Index: native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c
===================================================================
RCS file: native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c
diff -N native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ native/jni/java-nio/gnu_java_nio_EpollSelectorImpl.c        1 Jan 1970 
00:00:00 -0000
@@ -0,0 +1,405 @@
+/* gnu_java_nio_EpollSelectorImpl.c -- 
+   Copyright (C) 2006  Free Software Foundation, Inc.
+
+This file is a part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at
+your option) any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, 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
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version.  */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_SYS_EPOLL_H
+#include <sys/epoll.h>
+#endif /* HAVE_SYS_EPOLL_H */
+
+#include <gnu_java_nio_EpollSelectorImpl.h>
+#include <jcl.h>
+#include <errno.h>
+#include <string.h>
+
+#define IO_EXCEPTION "java/io/IOException"
+
+/* #define TRACE_EPOLL 1 */
+
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_supported
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_epoll_1supported (JNIEnv *e 
__attribute__((unused)),
+                                                      jclass c 
__attribute__((unused)))
+{
+#ifdef HAVE_EPOLL_CREATE
+  return JNI_TRUE;
+#else
+  return JNI_FALSE;
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    sizeof_struct
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_sizeof_1struct (JNIEnv *env,
+                                                    jclass c 
__attribute__((unused)))
+{
+#ifdef HAVE_EPOLL_CREATE
+  (void) env;
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: sizeof is %d\n", __FUNCTION__, sizeof (struct 
epoll_event));
+#endif /* TRACE_EPOLL */
+  return sizeof (struct epoll_event);
+#else
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+  return -1;
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_create
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_epoll_1create (JNIEnv *env,
+                                                   jclass c 
__attribute__((unused)),
+                                                   jint size)
+{
+#ifdef HAVE_EPOLL_CREATE
+  int fd = epoll_create (size);
+  
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: epoll_create returns %d\n", __FUNCTION__, fd);
+#endif /* TRACE_EPOLL */
+
+  if (fd == -1)
+    {
+      if (ENOSYS == errno)
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            strerror (errno));
+      else
+        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+    }
+  return fd;
+#else
+  (void) size;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+  return -1;
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_add
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_epoll_1add (JNIEnv *env,
+                                                jclass c 
__attribute__((unused)),
+                                                jint efd, jint fd, jint ops)
+{
+#ifdef HAVE_EPOLL_CREATE
+  struct epoll_event event;
+
+  memset (&event, 0, sizeof (struct epoll_event));
+
+  if ((ops & gnu_java_nio_EpollSelectorImpl_OP_ACCEPT) != 0
+      || (ops & gnu_java_nio_EpollSelectorImpl_OP_READ) != 0)
+    event.events = EPOLLIN;
+
+  if ((ops & gnu_java_nio_EpollSelectorImpl_OP_CONNECT) != 0
+      || (ops & gnu_java_nio_EpollSelectorImpl_OP_WRITE) != 0)
+    event.events |= EPOLLOUT;
+
+  event.data.fd = fd;
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: adding struct epoll_event { events: %o; data.fd: %d 
}\n",
+           __FUNCTION__, event.events, event.data.fd);
+#endif /* TRACE_EPOLL */
+
+  if (epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event) == -1)
+    {
+      if (ENOSYS == errno)
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            strerror (errno));
+      else
+        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+    }
+#else
+  (void) efd;
+  (void) fd;
+  (void) ops;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_modify
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_epoll_1modify (JNIEnv *env,
+                                                   jclass c 
__attribute__((unused)),
+                                                   jint efd, jint fd, jint ops)
+{
+#ifdef HAVE_EPOLL_CREATE
+  struct epoll_event event;
+
+  memset (&event, 0, sizeof (struct epoll_event));
+
+  if ((ops & gnu_java_nio_EpollSelectorImpl_OP_ACCEPT) != 0
+      || (ops & gnu_java_nio_EpollSelectorImpl_OP_READ) != 0)
+    event.events = EPOLLIN;
+
+  if ((ops & gnu_java_nio_EpollSelectorImpl_OP_CONNECT) != 0
+      || (ops & gnu_java_nio_EpollSelectorImpl_OP_WRITE) != 0)
+    event.events |= EPOLLOUT;
+
+  event.data.fd = fd;
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: modding struct epoll_event { events: %o; data.fd: %d 
}\n",
+           __FUNCTION__, event.events, event.data.fd);
+#endif /* TRACE_EPOLL */
+
+  if (epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event) == -1)
+    {
+      if (ENOSYS == errno)
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            strerror (errno));
+      else
+        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+    }
+#else
+  (void) efd;
+  (void) fd;
+  (void) ops;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_delete
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_epoll_1delete (JNIEnv *env,
+                                                   jclass c 
__attribute__((unused)),
+                                                   jint efd, jint fd)
+{
+#ifdef HAVE_EPOLL_CREATE
+  struct epoll_event event;
+
+  memset (&event, 0, sizeof (struct epoll_event));
+  event.data.fd = fd;
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: delete events on fd %d\n", __FUNCTION__, fd);
+#endif /* TRACE_EPOLL */
+
+  /* Older kernel versions require a non-null `event' parameter,
+   * even though it is ignored by this call.
+   */
+  if (epoll_ctl (efd, EPOLL_CTL_DEL, fd, &event) == -1)
+    {
+      if (ENOSYS == errno)
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            strerror (errno));
+      else
+        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+    }
+#else
+  (void) efd;
+  (void) fd;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    epoll_wait
+ * Signature: (ILjava/nio/ByteBuffer;II)I
+ */
+JNIEXPORT jint JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_epoll_1wait (JNIEnv *env,
+                                                 jclass c 
__attribute__((unused)),
+                                                 jint efd, jobject nstate,
+                                                 jint num_events, jint timeout)
+{
+#ifdef HAVE_EPOLL_CREATE
+  void *p = (*env)->GetDirectBufferAddress (env, nstate);
+  struct epoll_event *events = (struct epoll_event *) p;
+  int ret;
+
+  if (p == NULL)
+    {
+      if (!(*env)->ExceptionCheck (env))
+        JCL_ThrowException (env, IO_EXCEPTION, "getting native state failed");
+      return -1;
+    }
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: events: %p; num_events: %d; timeout: %d\n",
+           __FUNCTION__, p, num_events, timeout);
+#endif /* TRACE_EPOLL */
+
+  ret = epoll_wait (efd, events, num_events, timeout);
+  if (ret == -1)
+    {
+      if (ENOSYS == errno)
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            strerror (errno));
+      else
+        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
+    }
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "  epoll_wait returns %d\n", ret);
+  {
+    int i;
+    for (i = 0; i < ret; i++)
+      {
+        fprintf (stderr, "  [%4i]: events: %o; data.fd: %d\n", i, 
events[i].events,
+                 events[i].data.fd);
+      }
+  }
+  fflush (stderr);
+#endif /* TRACE_EPOLL */
+
+  return ret;
+#else
+  (void) efd;
+  (void) nstate;
+  (void) num_events;
+  (void) timeout;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+  return -1;
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    selected_fd
+ * Signature: (Ljava/nio/ByteBuffer;)I
+ */
+JNIEXPORT jint JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_selected_1fd (JNIEnv *env,
+                                                  jclass c 
__attribute__((unused)),
+                                                  jobject value)
+{
+#ifdef HAVE_EPOLL_CREATE
+  void *p = (*env)->GetDirectBufferAddress (env, value);
+  struct epoll_event *event = (struct epoll_event *) p;
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: event: %p\n", __FUNCTION__, p);
+#endif /* TRACE_EPOLL */
+
+  if (p == NULL)
+    {
+      if (!(*env)->ExceptionCheck (env))
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            "getting native state failed");
+      return -1;
+    }
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "  data.fd: %d\n", event->data.fd);
+  fflush (stderr);
+#endif /* TRACE_EPOLL */
+
+  return event->data.fd;
+#else
+  (void) value;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+  return -1;
+#endif /* HAVE_EPOLL_CREATE */
+}
+
+
+/*
+ * Class:     gnu_java_nio_EpollSelectorImpl
+ * Method:    selected_ops
+ * Signature: (Ljava/nio/ByteBuffer;)I
+ */
+JNIEXPORT jint JNICALL
+Java_gnu_java_nio_EpollSelectorImpl_selected_1ops (JNIEnv *env,
+                                                   jclass c 
__attribute__((unused)),
+                                                   jobject value)
+{
+#ifdef HAVE_EPOLL_CREATE
+  void *p = (*env)->GetDirectBufferAddress (env, value);
+  struct epoll_event *event = (struct epoll_event *) p;
+  int ret = 0;
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "%s: event: %p\n", __FUNCTION__, p);
+#endif /* TRACE_EPOLL */
+
+  if (p == NULL)
+    {
+      if (!(*env)->ExceptionCheck (env))
+        JCL_ThrowException (env, "java/lang/InternalError",
+                            "getting native state failed");
+      return -1;
+    }
+
+  if ((event->events & EPOLLIN) != 0)
+    ret |= gnu_java_nio_EpollSelectorImpl_OP_ACCEPT | 
gnu_java_nio_EpollSelectorImpl_OP_READ;
+  if ((event->events & EPOLLOUT) != 0)
+    ret |= gnu_java_nio_EpollSelectorImpl_OP_CONNECT | 
gnu_java_nio_EpollSelectorImpl_OP_WRITE;
+
+#ifdef TRACE_EPOLL
+  fprintf (stderr, "  events: %o\n", event->events);
+  fflush (stderr);
+#endif /* TRACE_EPOLL */
+
+  return ret;
+#else
+  (void) value;
+  JCL_ThrowException (env, "java/lang/InternalError", "epoll support not 
available");
+  return -1;
+#endif /* HAVE_EPOLL_CREATE */
+}
Index: gnu/java/nio/EpollSelectionKeyImpl.java
===================================================================
RCS file: gnu/java/nio/EpollSelectionKeyImpl.java
diff -N gnu/java/nio/EpollSelectionKeyImpl.java
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ gnu/java/nio/EpollSelectionKeyImpl.java     1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,138 @@
+/* EpollSelectionKeyImpl.java -- selection key for the epoll selector.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+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., 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
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module.  An independent module is a module which is not derived from
+or based on this library.  If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so.  If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package gnu.java.nio;
+
+import java.io.IOException;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+
+/**
+ * @author Casey Marshall ([EMAIL PROTECTED])
+ */
+public class EpollSelectionKeyImpl extends SelectionKey
+{
+  final int fd;
+  private final EpollSelectorImpl selector;
+  private final SelectableChannel channel;
+  int interestOps;
+  int selectedOps;
+  int key;
+  boolean valid;
+  boolean cancelled;
+  
+  EpollSelectionKeyImpl(EpollSelectorImpl selector,
+                        SelectableChannel channel, int fd)
+  {
+    this.selector = selector;
+    this.channel = channel;
+    this.fd = fd;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#cancel()
+   */
+  public void cancel()
+  {
+    cancelled = true;
+    selector.cancel(this);
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#channel()
+   */
+  public SelectableChannel channel()
+  {
+    return channel;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#interestOps()
+   */
+  public int interestOps()
+  {
+    return interestOps;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#interestOps(int)
+   */
+  public SelectionKey interestOps(int ops)
+  {
+    if (cancelled)
+      throw new CancelledKeyException();
+    if ((ops & ~(channel.validOps())) != 0)
+      throw new IllegalArgumentException("unsupported channel ops");
+    try
+      {
+        selector.epoll_modify(this, ops);
+        interestOps = ops;
+      }
+    catch (IOException ioe)
+      {
+        throw new IllegalArgumentException(ioe);
+      }
+    return this;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#isValid()
+   */
+  public boolean isValid()
+  {
+    return valid;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#readyOps()
+   */
+  public int readyOps()
+  {
+    return selectedOps;
+  }
+
+  /* (non-Javadoc)
+   * @see java.nio.channels.SelectionKey#selector()
+   */
+  public Selector selector()
+  {
+    return selector;
+  }
+}

Reply via email to