7172826: (se) Selector based on the Solaris event port mechanism
Reviewed-by: coffeys, chegar
--- 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 \
--- 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;
--- 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;
--- 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 {
--- 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();
}
--- 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();
}
--- /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<Integer,SelectionKeyImpl> 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<entries; i++) {
+ int nextFD = pollWrapper.getDescriptor(i);
+ SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
+ if (ski != null) {
+ int rOps = pollWrapper.getEventOps(i);
+ if (selectedKeys.contains(ski)) {
+ if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
+ numKeysUpdated++;
+ }
+ } else {
+ ski.channel.translateAndSetReadyOps(rOps, ski);
+ if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
+ selectedKeys.add(ski);
+ numKeysUpdated++;
+ }
+ }
+ }
+ }
+ return numKeysUpdated;
+ }
+
+ protected void implClose() throws IOException {
+ if (closed)
+ return;
+ closed = true;
+
+ // prevent further wakeup
+ synchronized (interruptLock) {
+ interruptTriggered = true;
+ }
+
+ pollWrapper.close();
+ selectedKeys = null;
+
+ // Deregister channels
+ Iterator<SelectionKey> 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;
+ }
+}
--- /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();
+ }
+}
--- /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<Integer,Byte> 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<updated; i++) {
+ if (getSource(i) == PORT_SOURCE_USER) {
+ interrupted = true;
+ setDescriptor(i, -1);
+ } else {
+ // the default is to re-associate for the next poll
+ int fd = getDescriptor(i);
+ registered.clear(fd);
+ setInterest(fd);
+ }
+ }
+ }
+
+ return updated;
+ }
+
+ private void setInterest(int fd) {
+ assert Thread.holdsLock(updateLock);
+
+ // record the file descriptor and events, expanding the
+ // respective arrays first if necessary.
+ int oldCapacity = updateDescriptors.length;
+ if (updateCount >= 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;
+ }
+}
--- 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();
}
}
--- 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 <sys/poll.h>
-#include <sys/resource.h>
#include <unistd.h>
#include <sys/time.h>
@@ -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)
{
--- 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 <unistd.h>
-#include <sys/resource.h>
#include <sys/time.h>
#include <sys/epoll.h>
@@ -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);
--- 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 <sys/types.h>
#include <string.h>
+#include <sys/resource.h>
+
#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 */
--- 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 <stdlib.h>
#include <dlfcn.h>
#include <sys/types.h>
-#include <port.h> // Solaris 10
+#include <port.h>
#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;
}
--- 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
--- 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
--- 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");
}
}