7172826: (se) Selector based on the Solaris event port mechanism
Reviewed-by: coffeys, chegar
This commit is contained in:
parent
dfccae97eb
commit
08c4f120c9
@ -55,6 +55,9 @@ FILES_java += \
|
||||
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 \
|
||||
|
@ -39,7 +39,6 @@ SUNWprivate_1.1 {
|
||||
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 @@ SUNWprivate_1.1 {
|
||||
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;
|
||||
|
@ -36,7 +36,6 @@ SUNWprivate_1.1 {
|
||||
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 @@ SUNWprivate_1.1 {
|
||||
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 @@ SUNWprivate_1.1 {
|
||||
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;
|
||||
|
@ -334,6 +334,8 @@ public class IOUtil {
|
||||
|
||||
static native void setfdVal(FileDescriptor fd, int value);
|
||||
|
||||
static native int fdLimit();
|
||||
|
||||
static native void initIDs();
|
||||
|
||||
static {
|
||||
|
@ -71,7 +71,7 @@ class DevPollArrayWrapper {
|
||||
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 @@ class DevPollArrayWrapper {
|
||||
private native int poll0(long pollAddress, int numfds, long timeout,
|
||||
int wfd);
|
||||
private static native void interrupt(int fd);
|
||||
private static native int fdLimit();
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ class EPollArrayWrapper {
|
||||
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 @@ class EPollArrayWrapper {
|
||||
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();
|
||||
}
|
||||
|
170
jdk/src/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java
Normal file
170
jdk/src/solaris/classes/sun/nio/ch/EventPortSelectorImpl.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
256
jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java
Normal file
256
jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -31,8 +31,8 @@ import java.io.IOException;
|
||||
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 @@ class SolarisEventPort
|
||||
* 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 @@ class SolarisEventPort
|
||||
super(provider, pool);
|
||||
|
||||
// create event port
|
||||
this.port = portCreate();
|
||||
this.port = port_create();
|
||||
}
|
||||
|
||||
SolarisEventPort start() {
|
||||
@ -90,12 +90,12 @@ class SolarisEventPort
|
||||
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 @@ class SolarisEventPort
|
||||
// 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 @@ class SolarisEventPort
|
||||
// (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 @@ class SolarisEventPort
|
||||
// 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 @@ class SolarisEventPort
|
||||
}
|
||||
}
|
||||
|
||||
// -- Native methods --
|
||||
/**
|
||||
* Creates an event port
|
||||
*/
|
||||
static native int port_create() throws IOException;
|
||||
|
||||
private static native void init();
|
||||
|
||||
private static native int portCreate() throws IOException;
|
||||
|
||||
private static native void portAssociate(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)
|
||||
/**
|
||||
* 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 portSend(int port, int events) throws IOException;
|
||||
/**
|
||||
* Removes the association of an object with a port.
|
||||
*/
|
||||
static native boolean port_dissociate(int port, int source, long object)
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
private static native void portClose(int port);
|
||||
|
||||
static {
|
||||
Util.load();
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
|
||||
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)
|
||||
{
|
||||
|
@ -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>
|
||||
|
||||
@ -91,16 +90,6 @@ Java_sun_nio_ch_EPollArrayWrapper_epollCreate(JNIEnv *env, jobject this)
|
||||
return epfd;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 @@ Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd)
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -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 @@ Java_sun_nio_ch_SolarisEventPort_portCreate
|
||||
}
|
||||
|
||||
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) == -1) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_associate");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_nio_ch_SolarisEventPort_portDissociate
|
||||
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) == -1) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_dissociate");
|
||||
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_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 @@ Java_sun_nio_ch_SolarisEventPort_portSend(JNIEnv* env, jclass clazz,
|
||||
}
|
||||
|
||||
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 @@ Java_sun_nio_ch_SolarisEventPort_portGet(JNIEnv* env, jclass clazz,
|
||||
}
|
||||
|
||||
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 (res == -1) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_getn");
|
||||
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) {
|
||||
if (errno != ETIME && errno != EINTR)
|
||||
JNU_ThrowIOExceptionWithLastError(env, "port_getn");
|
||||
}
|
||||
|
||||
return (jint)n;
|
||||
}
|
||||
|
@ -46,4 +46,4 @@ if [ "$NOFILES" = "unlimited" ] || [ $NOFILES -ge 10000 ]; then
|
||||
ulimit -n 2048
|
||||
fi
|
||||
|
||||
${TESTJAVA}/bin/java LotsOfUpdates
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} LotsOfUpdates
|
||||
|
@ -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
|
||||
|
@ -31,19 +31,23 @@ import java.nio.channels.spi.*;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user