# HG changeset patch # User alanb # Date 1339001969 -3600 # Node ID 16fa902b1469906e9f2f2d6b6f3c208f8268b4e1 # Parent b583b4c82a8294b4a14c842a85bb604d769fdb7e 7172826: (se) Selector based on the Solaris event port mechanism Reviewed-by: coffeys, chegar diff -r b583b4c82a82 -r 16fa902b1469 jdk/make/java/nio/Makefile --- a/jdk/make/java/nio/Makefile Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/make/java/nio/Makefile Wed Jun 06 17:59:29 2012 +0100 @@ -55,6 +55,9 @@ sun/nio/ch/DevPollArrayWrapper.java \ sun/nio/ch/DevPollSelectorImpl.java \ sun/nio/ch/DevPollSelectorProvider.java \ + sun/nio/ch/EventPortSelectorImpl.java \ + sun/nio/ch/EventPortSelectorProvider.java \ + sun/nio/ch/EventPortWrapper.java \ sun/nio/ch/InheritedChannel.java \ sun/nio/ch/PollSelectorProvider.java \ sun/nio/ch/PollSelectorImpl.java \ diff -r b583b4c82a82 -r 16fa902b1469 jdk/make/java/nio/mapfile-linux --- a/jdk/make/java/nio/mapfile-linux Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/make/java/nio/mapfile-linux Wed Jun 06 17:59:29 2012 +0100 @@ -39,7 +39,6 @@ Java_sun_nio_ch_EPollArrayWrapper_epollCreate; Java_sun_nio_ch_EPollArrayWrapper_epollCtl; Java_sun_nio_ch_EPollArrayWrapper_epollWait; - Java_sun_nio_ch_EPollArrayWrapper_fdLimit; Java_sun_nio_ch_EPollArrayWrapper_init; Java_sun_nio_ch_EPollArrayWrapper_interrupt; Java_sun_nio_ch_EPollArrayWrapper_offsetofData; @@ -87,6 +86,7 @@ Java_sun_nio_ch_IOUtil_configureBlocking; Java_sun_nio_ch_IOUtil_drain; Java_sun_nio_ch_IOUtil_fdVal; + Java_sun_nio_ch_IOUtil_fdLimit; Java_sun_nio_ch_IOUtil_initIDs; Java_sun_nio_ch_IOUtil_makePipe; Java_sun_nio_ch_IOUtil_randomBytes; diff -r b583b4c82a82 -r 16fa902b1469 jdk/make/java/nio/mapfile-solaris --- a/jdk/make/java/nio/mapfile-solaris Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/make/java/nio/mapfile-solaris Wed Jun 06 17:59:29 2012 +0100 @@ -36,7 +36,6 @@ Java_sun_nio_ch_DatagramDispatcher_readv0; Java_sun_nio_ch_DatagramDispatcher_write0; Java_sun_nio_ch_DatagramDispatcher_writev0; - Java_sun_nio_ch_DevPollArrayWrapper_fdLimit; Java_sun_nio_ch_DevPollArrayWrapper_init; Java_sun_nio_ch_DevPollArrayWrapper_interrupt; Java_sun_nio_ch_DevPollArrayWrapper_poll0; @@ -74,6 +73,7 @@ Java_sun_nio_ch_InheritedChannel_soType0; Java_sun_nio_ch_IOUtil_configureBlocking; Java_sun_nio_ch_IOUtil_drain; + Java_sun_nio_ch_IOUtil_fdLimit; Java_sun_nio_ch_IOUtil_fdVal; Java_sun_nio_ch_IOUtil_initIDs; Java_sun_nio_ch_IOUtil_makePipe; @@ -112,13 +112,13 @@ Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0; Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs; Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect; - Java_sun_nio_ch_SolarisEventPort_init; - Java_sun_nio_ch_SolarisEventPort_portCreate; - Java_sun_nio_ch_SolarisEventPort_portClose; - Java_sun_nio_ch_SolarisEventPort_portAssociate; - Java_sun_nio_ch_SolarisEventPort_portGet; - Java_sun_nio_ch_SolarisEventPort_portGetn; - Java_sun_nio_ch_SolarisEventPort_portSend; + Java_sun_nio_ch_SolarisEventPort_port_1create; + Java_sun_nio_ch_SolarisEventPort_port_1close; + Java_sun_nio_ch_SolarisEventPort_port_1associate; + Java_sun_nio_ch_SolarisEventPort_port_1dissociate; + Java_sun_nio_ch_SolarisEventPort_port_1get; + Java_sun_nio_ch_SolarisEventPort_port_1getn; + Java_sun_nio_ch_SolarisEventPort_port_1send; Java_sun_nio_fs_GnomeFileTypeDetector_initializeGio; Java_sun_nio_fs_GnomeFileTypeDetector_probeUsingGio; Java_sun_nio_fs_GnomeFileTypeDetector_initializeGnomeVfs; diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/share/classes/sun/nio/ch/IOUtil.java --- a/jdk/src/share/classes/sun/nio/ch/IOUtil.java Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/IOUtil.java Wed Jun 06 17:59:29 2012 +0100 @@ -334,6 +334,8 @@ static native void setfdVal(FileDescriptor fd, int value); + static native int fdLimit(); + static native void initIDs(); static { diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java --- a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java Wed Jun 06 17:59:29 2012 +0100 @@ -71,7 +71,7 @@ static final byte CANCELLED = (byte)-1; // Maximum number of open file descriptors - static final int OPEN_MAX = fdLimit(); + static final int OPEN_MAX = IOUtil.fdLimit(); // Number of pollfd structures to create. // dpwrite/ioctl(DP_POLL) allows up to OPEN_MAX-1 @@ -308,5 +308,4 @@ private native int poll0(long pollAddress, int numfds, long timeout, int wfd); private static native void interrupt(int fd); - private static native int fdLimit(); } diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java --- a/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Wed Jun 06 17:59:29 2012 +0100 @@ -74,7 +74,7 @@ static final int EVENT_OFFSET = 0; static final int DATA_OFFSET = offsetofData(); static final int FD_OFFSET = DATA_OFFSET; - static final int NUM_EPOLLEVENTS = Math.min(fdLimit(), 8192); + static final int NUM_EPOLLEVENTS = Math.min(IOUtil.fdLimit(), 8192); // Base address of the native pollArray private final long pollArrayAddress; @@ -296,7 +296,6 @@ int epfd) throws IOException; private static native int sizeofEPollEvent(); private static native int offsetofData(); - private static native int fdLimit(); private static native void interrupt(int fd); private static native void init(); } diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java Wed Jun 06 17:59:29 2012 +0100 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.ch; + +import java.io.IOException; +import java.nio.channels.*; +import java.nio.channels.spi.*; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + +/** + * Selector implementation based on the Solaris event port mechanism. + */ + +class EventPortSelectorImpl + extends SelectorImpl +{ + private final EventPortWrapper pollWrapper; + + // Maps from file descriptors to keys + private Map fdToKey; + + // True if this Selector has been closed + private boolean closed = false; + + // Lock for interrupt triggering and clearing + private final Object interruptLock = new Object(); + private boolean interruptTriggered = false; + + /** + * Package private constructor called by factory method in + * the abstract superclass Selector. + */ + EventPortSelectorImpl(SelectorProvider sp) throws IOException { + super(sp); + pollWrapper = new EventPortWrapper(); + fdToKey = new HashMap<>(); + } + + protected int doSelect(long timeout) throws IOException { + if (closed) + throw new ClosedSelectorException(); + processDeregisterQueue(); + int entries; + try { + begin(); + entries = pollWrapper.poll(timeout); + } finally { + end(); + } + processDeregisterQueue(); + int numKeysUpdated = updateSelectedKeys(entries); + if (pollWrapper.interrupted()) { + synchronized (interruptLock) { + interruptTriggered = false; + } + } + return numKeysUpdated; + } + + private int updateSelectedKeys(int entries) { + int numKeysUpdated = 0; + for (int i=0; i i = keys.iterator(); + while (i.hasNext()) { + SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); + deregister(ski); + SelectableChannel selch = ski.channel(); + if (!selch.isOpen() && !selch.isRegistered()) + ((SelChImpl)selch).kill(); + i.remove(); + } + } + + protected void implRegister(SelectionKeyImpl ski) { + int fd = IOUtil.fdVal(ski.channel.getFD()); + fdToKey.put(Integer.valueOf(fd), ski); + keys.add(ski); + } + + protected void implDereg(SelectionKeyImpl ski) throws IOException { + int i = ski.getIndex(); + assert (i >= 0); + int fd = ski.channel.getFDVal(); + fdToKey.remove(Integer.valueOf(fd)); + pollWrapper.release(fd); + ski.setIndex(-1); + keys.remove(ski); + selectedKeys.remove(ski); + deregister((AbstractSelectionKey)ski); + SelectableChannel selch = ski.channel(); + if (!selch.isOpen() && !selch.isRegistered()) + ((SelChImpl)selch).kill(); + } + + public void putEventOps(SelectionKeyImpl sk, int ops) { + if (closed) + throw new ClosedSelectorException(); + int fd = sk.channel.getFDVal(); + pollWrapper.setInterest(fd, ops); + } + + public Selector wakeup() { + synchronized (interruptLock) { + if (!interruptTriggered) { + pollWrapper.interrupt(); + interruptTriggered = true; + } + } + return this; + } +} diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/classes/sun/nio/ch/EventPortSelectorProvider.java Wed Jun 06 17:59:29 2012 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.ch; + +import java.io.IOException; +import java.nio.channels.*; +import java.nio.channels.spi.*; + +public class EventPortSelectorProvider + extends SelectorProviderImpl +{ + public AbstractSelector openSelector() throws IOException { + return new EventPortSelectorImpl(this); + } + + public Channel inheritedChannel() throws IOException { + return InheritedChannel.getChannel(); + } +} diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java Wed Jun 06 17:59:29 2012 +0100 @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.ch; + +import sun.misc.Unsafe; +import java.io.IOException; +import java.util.*; +import static sun.nio.ch.SolarisEventPort.*; + +/** + * Manages a Solaris event port and manipulates a native array of pollfd structs + * on Solaris. + */ + +class EventPortWrapper { + private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final int addressSize = unsafe.addressSize(); + + // Maximum number of open file descriptors + static final int OPEN_MAX = IOUtil.fdLimit(); + + // Maximum number of events to retrive in one call to port_getn + static final int POLL_MAX = Math.min(OPEN_MAX-1, 1024); + + // initial size of the array to hold pending updates + private final int INITIAL_PENDING_UPDATE_SIZE = 256; + + // maximum size of updateArray + private final int MAX_UPDATE_ARRAY_SIZE = Math.min(OPEN_MAX, 64*1024); + + // special update status to indicate that it should be ignored + private static final byte IGNORE = -1; + + // port file descriptor + private final int pfd; + + // the poll array (populated by port_getn) + private final long pollArrayAddress; + private final AllocatedNativeObject pollArray; + + // required when accessing the update* fields + private final Object updateLock = new Object(); + + // the number of pending updates + private int updateCount; + + // queue of file descriptors with updates pending + private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE]; + + // events for file descriptors with registration changes pending, indexed + // by file descriptor and stored as bytes for efficiency reasons. For + // file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at + // least then the update is stored in a map. + private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE]; + private Map eventsHigh; + // Used by release and updateRegistrations to track whether a file + // descriptor is registered with /dev/poll. + private final BitSet registered = new BitSet(); + + // bit set to indicate if a file descriptor has been visited when + // processing updates (used to avoid duplicates calls to port_associate) + private BitSet visited = new BitSet(); + + EventPortWrapper() throws IOException { + int allocationSize = POLL_MAX * SIZEOF_PORT_EVENT; + pollArray = new AllocatedNativeObject(allocationSize, true); + pollArrayAddress = pollArray.address(); + this.pfd = port_create(); + if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE) + eventsHigh = new HashMap<>(); + } + + void close() throws IOException { + port_close(pfd); + pollArray.free(); + } + + private short getSource(int i) { + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_SOURCE; + return pollArray.getShort(offset); + } + + int getEventOps(int i) { + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_EVENTS; + return pollArray.getInt(offset); + } + + int getDescriptor(int i) { + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT; + if (addressSize == 4) { + return pollArray.getInt(offset); + } else { + return (int) pollArray.getLong(offset); + } + } + + private void setDescriptor(int i, int fd) { + int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT; + if (addressSize == 4) { + pollArray.putInt(offset, fd); + } else { + pollArray.putLong(offset, fd); + } + } + + private void setUpdate(int fd, byte events) { + if (fd < MAX_UPDATE_ARRAY_SIZE) { + eventsLow[fd] = events; + } else { + eventsHigh.put(Integer.valueOf(fd), Byte.valueOf(events)); + } + } + + private byte getUpdate(int fd) { + if (fd < MAX_UPDATE_ARRAY_SIZE) { + return eventsLow[fd]; + } else { + Byte result = eventsHigh.get(Integer.valueOf(fd)); + // result should never be null + return result.byteValue(); + } + } + + int poll(long timeout) throws IOException { + // update registrations prior to poll + synchronized (updateLock) { + + // process newest updates first + int i = updateCount - 1; + while (i >= 0) { + int fd = updateDescriptors[i]; + if (!visited.get(fd)) { + short ev = getUpdate(fd); + if (ev != IGNORE) { + if (ev == 0) { + if (registered.get(fd)) { + port_dissociate(pfd, PORT_SOURCE_FD, (long)fd); + registered.clear(fd); + } + } else { + if (port_associate(pfd, PORT_SOURCE_FD, (long)fd, ev)) { + registered.set(fd); + } + } + + } + visited.set(fd); + } + i--; + } + updateCount = 0; + } + + // poll for events + int updated = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout); + + // after polling we need to queue all polled file descriptors as they + // are candidates to register for the next poll. + synchronized (updateLock) { + for (int i=0; i= oldCapacity) { + int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE; + int[] newDescriptors = new int[newCapacity]; + System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity); + updateDescriptors = newDescriptors; + } + updateDescriptors[updateCount++] = fd; + visited.clear(fd); + } + + void setInterest(int fd, int mask) { + synchronized (updateLock) { + setInterest(fd); + setUpdate(fd, (byte)mask); + assert getUpdate(fd) == mask; + } + } + + void release(int fd) { + synchronized (updateLock) { + if (registered.get(fd)) { + try { + port_dissociate(pfd, PORT_SOURCE_FD, (long)fd); + } catch (IOException ioe) { + throw new InternalError(ioe); + } + registered.clear(fd); + } + setUpdate(fd, IGNORE); + } + } + + // -- wakeup support -- + + private boolean interrupted; + + public void interrupt() { + try { + port_send(pfd, 0); + } catch (IOException ioe) { + throw new InternalError(ioe); + } + } + + boolean interrupted() { + return interrupted; + } + + void clearInterrupted() { + interrupted = false; + } +} diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java --- a/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/classes/sun/nio/ch/SolarisEventPort.java Wed Jun 06 17:59:29 2012 +0100 @@ -31,8 +31,8 @@ import sun.misc.Unsafe; /** - * AsynchronousChannelGroup implementation based on the Solaris 10 event port - * framework. + * Provides an AsynchronousChannelGroup implementation based on the Solaris 10 + * event port framework and also provides direct access to that framework. */ class SolarisEventPort @@ -54,14 +54,14 @@ * void *portev_user; * } port_event_t; */ - private static final int SIZEOF_PORT_EVENT = dependsArch(16, 24); - private static final int OFFSETOF_EVENTS = 0; - private static final int OFFSETOF_SOURCE = 4; - private static final int OFFSETOF_OBJECT = 8; + static final int SIZEOF_PORT_EVENT = dependsArch(16, 24); + static final int OFFSETOF_EVENTS = 0; + static final int OFFSETOF_SOURCE = 4; + static final int OFFSETOF_OBJECT = 8; // port sources - private static final short PORT_SOURCE_USER = 3; - private static final short PORT_SOURCE_FD = 4; + static final short PORT_SOURCE_USER = 3; + static final short PORT_SOURCE_FD = 4; // file descriptor to event port. private final int port; @@ -75,7 +75,7 @@ super(provider, pool); // create event port - this.port = portCreate(); + this.port = port_create(); } SolarisEventPort start() { @@ -90,12 +90,12 @@ return; closed = true; } - portClose(port); + port_close(port); } private void wakeup() { try { - portSend(port, 0); + port_send(port, 0); } catch (IOException x) { throw new AssertionError(x); } @@ -124,7 +124,7 @@ // send user event to wakeup each thread while (nThreads-- > 0) { try { - portSend(port, 0); + port_send(port, 0); } catch (IOException x) { throw new AssertionError(x); } @@ -137,7 +137,7 @@ // (re-)associate file descriptor // no need to translate events try { - portAssociate(port, PORT_SOURCE_FD, fd, events); + port_associate(port, PORT_SOURCE_FD, fd, events); } catch (IOException x) { throw new AssertionError(); // should not happen } @@ -164,7 +164,7 @@ // A error here is fatal (thread will not be replaced) replaceMe = false; try { - portGet(port, address); + port_get(port, address); } catch (IOException x) { x.printStackTrace(); return; @@ -220,26 +220,46 @@ } } - // -- Native methods -- - - private static native void init(); - - private static native int portCreate() throws IOException; + /** + * Creates an event port + */ + static native int port_create() throws IOException; - private static native void portAssociate(int port, int source, long object, - int events) throws IOException; + /** + * Associates specific events of a given object with a port + */ + static native boolean port_associate(int port, int source, long object, int events) + throws IOException; - private static native void portGet(int port, long pe) throws IOException; - - private static native int portGetn(int port, long address, int max) + /** + * Removes the association of an object with a port. + */ + static native boolean port_dissociate(int port, int source, long object) throws IOException; - private static native void portSend(int port, int events) throws IOException; + /** + * Retrieves a single event from a port + */ + static native void port_get(int port, long pe) throws IOException; + + /** + * Retrieves at most {@code max} events from a port. + */ + static native int port_getn(int port, long address, int max, long timeout) + throws IOException; - private static native void portClose(int port); + /** + * Sends a user-defined eventto a specified port. + */ + static native void port_send(int port, int events) throws IOException; + + /** + * Closes a port. + */ + static native void port_close(int port); + static { Util.load(); - init(); } } diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/native/sun/nio/ch/DevPollArrayWrapper.c --- a/jdk/src/solaris/native/sun/nio/ch/DevPollArrayWrapper.c Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/native/sun/nio/ch/DevPollArrayWrapper.c Wed Jun 06 17:59:29 2012 +0100 @@ -28,9 +28,7 @@ #include "jvm.h" #include "jlong.h" #include "sun_nio_ch_DevPollArrayWrapper.h" -#include "java_lang_Integer.h" #include -#include #include #include @@ -178,21 +176,6 @@ return result; } -JNIEXPORT jint JNICALL -Java_sun_nio_ch_DevPollArrayWrapper_fdLimit(JNIEnv *env, jclass this) -{ - struct rlimit rlp; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) { - JNU_ThrowIOExceptionWithLastError(env, - "getrlimit failed"); - } - if (rlp.rlim_max < 0 || rlp.rlim_max > java_lang_Integer_MAX_VALUE) { - return java_lang_Integer_MAX_VALUE; - } else { - return (jint)rlp.rlim_max; - } -} - JNIEXPORT void JNICALL Java_sun_nio_ch_DevPollArrayWrapper_interrupt(JNIEnv *env, jclass this, jint fd) { diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/native/sun/nio/ch/EPollArrayWrapper.c --- a/jdk/src/solaris/native/sun/nio/ch/EPollArrayWrapper.c Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/native/sun/nio/ch/EPollArrayWrapper.c Wed Jun 06 17:59:29 2012 +0100 @@ -31,7 +31,6 @@ #include "sun_nio_ch_EPollArrayWrapper.h" #include -#include #include #include @@ -92,16 +91,6 @@ } JNIEXPORT jint JNICALL -Java_sun_nio_ch_EPollArrayWrapper_fdLimit(JNIEnv *env, jclass this) -{ - struct rlimit rlp; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) { - JNU_ThrowIOExceptionWithLastError(env, "getrlimit failed"); - } - return (jint)rlp.rlim_max; -} - -JNIEXPORT jint JNICALL Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent(JNIEnv* env, jclass this) { return sizeof(struct epoll_event); diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/native/sun/nio/ch/IOUtil.c --- a/jdk/src/solaris/native/sun/nio/ch/IOUtil.c Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/native/sun/nio/ch/IOUtil.c Wed Jun 06 17:59:29 2012 +0100 @@ -25,11 +25,14 @@ #include #include +#include + #include "jni.h" #include "jni_util.h" #include "jvm.h" #include "jlong.h" #include "sun_nio_ch_IOUtil.h" +#include "java_lang_Integer.h" #include "nio.h" #include "nio_util.h" @@ -118,6 +121,20 @@ } } +JNIEXPORT jint JNICALL +Java_sun_nio_ch_IOUtil_fdLimit(JNIEnv *env, jclass this) +{ + struct rlimit rlp; + if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) { + JNU_ThrowIOExceptionWithLastError(env, "getrlimit failed"); + return -1; + } + if (rlp.rlim_max < 0 || rlp.rlim_max > java_lang_Integer_MAX_VALUE) { + return java_lang_Integer_MAX_VALUE; + } else { + return (jint)rlp.rlim_max; + } +} /* Declared in nio_util.h for use elsewhere in NIO */ diff -r b583b4c82a82 -r 16fa902b1469 jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c --- a/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/src/solaris/native/sun/nio/ch/SolarisEventPort.c Wed Jun 06 17:59:29 2012 +0100 @@ -32,17 +32,12 @@ #include #include #include -#include // Solaris 10 +#include #include "sun_nio_ch_SolarisEventPort.h" -JNIEXPORT void JNICALL -Java_sun_nio_ch_SolarisEventPort_init(JNIEnv *env, jclass clazz) -{ -} - JNIEXPORT jint JNICALL -Java_sun_nio_ch_SolarisEventPort_portCreate +Java_sun_nio_ch_SolarisEventPort_port_1create (JNIEnv* env, jclass clazz) { int port = port_create(); @@ -53,37 +48,44 @@ } JNIEXPORT void JNICALL -Java_sun_nio_ch_SolarisEventPort_portClose +Java_sun_nio_ch_SolarisEventPort_port_1close (JNIEnv* env, jclass clazz, jint port) { int res; RESTARTABLE(close(port), res); } -JNIEXPORT void JNICALL -Java_sun_nio_ch_SolarisEventPort_portAssociate +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_SolarisEventPort_port_1associate (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress, jint events) { uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); + if (port_associate((int)port, (int)source, object, (int)events, NULL) == 0) { + return JNI_TRUE; + } else { + if (errno != EBADFD) + JNU_ThrowIOExceptionWithLastError(env, "port_associate"); + return JNI_FALSE; + } +} - if (port_associate((int)port, (int)source, object, (int)events, NULL) == -1) { - JNU_ThrowIOExceptionWithLastError(env, "port_associate"); +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_SolarisEventPort_port_1dissociate + (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress) +{ + uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); + + if (port_dissociate((int)port, (int)source, object) == 0) { + return JNI_TRUE; + } else { + if (errno != ENOENT) + JNU_ThrowIOExceptionWithLastError(env, "port_dissociate"); + return JNI_FALSE; } } JNIEXPORT void JNICALL -Java_sun_nio_ch_SolarisEventPort_portDissociate - (JNIEnv* env, jclass clazz, jint port, jint source, jlong objectAddress) -{ - uintptr_t object = (uintptr_t)jlong_to_ptr(objectAddress); - - if (port_dissociate((int)port, (int)source, object) == -1) { - JNU_ThrowIOExceptionWithLastError(env, "port_dissociate"); - } -} - -JNIEXPORT void JNICALL -Java_sun_nio_ch_SolarisEventPort_portSend(JNIEnv* env, jclass clazz, +Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz, jint port, jint events) { if (port_send((int)port, (int)events, NULL) == -1) { @@ -92,7 +94,7 @@ } JNIEXPORT void JNICALL -Java_sun_nio_ch_SolarisEventPort_portGet(JNIEnv* env, jclass clazz, +Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz, jint port, jlong eventAddress) { int res; @@ -105,16 +107,28 @@ } JNIEXPORT jint JNICALL -Java_sun_nio_ch_SolarisEventPort_portGetn(JNIEnv* env, jclass clazz, - jint port, jlong arrayAddress, jint max) +Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz, + jint port, jlong arrayAddress, jint max, jlong timeout) { int res; uint_t n = 1; port_event_t* list = (port_event_t*)jlong_to_ptr(arrayAddress); + timespec_t ts; + timespec_t* tsp; - RESTARTABLE(port_getn((int)port, list, (uint_t)max, &n, NULL), res); + if (timeout >= 0L) { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = 1000000 * (timeout % 1000); + tsp = &ts; + } else { + tsp = NULL; + } + + res = port_getn((int)port, list, (uint_t)max, &n, tsp); if (res == -1) { - JNU_ThrowIOExceptionWithLastError(env, "port_getn"); + if (errno != ETIME && errno != EINTR) + JNU_ThrowIOExceptionWithLastError(env, "port_getn"); } + return (jint)n; } diff -r b583b4c82a82 -r 16fa902b1469 jdk/test/java/nio/channels/Selector/lots_of_updates.sh --- a/jdk/test/java/nio/channels/Selector/lots_of_updates.sh Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/test/java/nio/channels/Selector/lots_of_updates.sh Wed Jun 06 17:59:29 2012 +0100 @@ -46,4 +46,4 @@ ulimit -n 2048 fi -${TESTJAVA}/bin/java LotsOfUpdates +${TESTJAVA}/bin/java ${TESTVMOPTS} LotsOfUpdates diff -r b583b4c82a82 -r 16fa902b1469 jdk/test/java/nio/channels/SocketChannel/Open.sh --- a/jdk/test/java/nio/channels/SocketChannel/Open.sh Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/test/java/nio/channels/SocketChannel/Open.sh Wed Jun 06 17:59:29 2012 +0100 @@ -29,7 +29,7 @@ case "$OS" in SunOS ) ulimit -n 100 - $TESTJAVA/bin/java -classpath $TESTCLASSES Open ;; + $TESTJAVA/bin/java ${TESTVMOPTS} -classpath $TESTCLASSES Open ;; * ) echo "unrecognized system: $OS" ;; esac diff -r b583b4c82a82 -r 16fa902b1469 jdk/test/sun/nio/ch/SelProvider.java --- a/jdk/test/sun/nio/ch/SelProvider.java Wed Jun 06 10:05:54 2012 +0800 +++ b/jdk/test/sun/nio/ch/SelProvider.java Wed Jun 06 17:59:29 2012 +0100 @@ -31,19 +31,23 @@ public class SelProvider { public static void main(String[] args) throws Exception { - String osname = System.getProperty("os.name"); - String osver = System.getProperty("os.version"); - String spName = SelectorProvider.provider().getClass().getName(); - String expected = null; - if ("SunOS".equals(osname)) { - expected = "sun.nio.ch.DevPollSelectorProvider"; - } else if ("Linux".equals(osname)) { - expected = "sun.nio.ch.EPollSelectorProvider"; - } else if (osname.contains("OS X")) { - expected = "sun.nio.ch.KQueueSelectorProvider"; - } else - return; - if (!spName.equals(expected)) + String expected = System.getProperty("java.nio.channels.spi.SelectorProvider"); + if (expected == null) { + String osname = System.getProperty("os.name"); + String osver = System.getProperty("os.version"); + if ("SunOS".equals(osname)) { + expected = "sun.nio.ch.DevPollSelectorProvider"; + } else if ("Linux".equals(osname)) { + expected = "sun.nio.ch.EPollSelectorProvider"; + } else if (osname.contains("OS X")) { + expected = "sun.nio.ch.KQueueSelectorProvider"; + } else { + return; + } + } + String cn = SelectorProvider.provider().getClass().getName(); + System.out.println(cn); + if (!cn.equals(expected)) throw new Exception("failed"); } }