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