提交 2144e7e0 编写于 作者: A alanb

7172826: (se) Selector based on the Solaris event port mechanism

Reviewed-by: coffeys, chegar
上级 0f47388e
......@@ -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();
}
/*
* 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;
}
}
/*
* 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();
}
}
/*
* 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 --
private static native void init();
/**
* Creates an event port
*/
static native int port_create() throws IOException;
private static native int portCreate() 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 portAssociate(int port, int source, long object,
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;
private static native void portGet(int port, long pe) throws IOException;
/**
* Retrieves a single event from a port
*/
static native void port_get(int port, long pe) throws IOException;
private static native int portGetn(int port, long address, int max)
/**
* 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 portSend(int port, int events) 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 (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;
}
......@@ -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");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册