8266369: (se) Add wepoll based Selector

Reviewed-by: chegar, michaelm, vtewari, dfuchs, bpb
This commit is contained in:
Alan Bateman 2021-05-08 07:14:36 +00:00
parent ff77ca8bd4
commit be4f25b0c8
23 changed files with 3234 additions and 102 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
@ -679,6 +679,10 @@ public class Net {
*/
static native int sendOOB(FileDescriptor fd, byte data) throws IOException;
/**
* Read and discard urgent data (MSG_OOB) on the socket.
*/
static native boolean discardOOB(FileDescriptor fd) throws IOException;
// -- Multicast support --

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
@ -25,6 +25,7 @@
package sun.nio.ch;
import java.io.FileDescriptor;
import java.lang.invoke.ConstantBootstraps;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
@ -74,6 +75,10 @@ public final class SelectionKeyImpl
throw new CancelledKeyException();
}
FileDescriptor getFD() {
return channel.getFD();
}
int getFDVal() {
return channel.getFDVal();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, 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
@ -35,7 +35,7 @@ import java.security.PrivilegedAction;
public class DefaultSelectorProvider {
private static final SelectorProviderImpl INSTANCE;
static {
PrivilegedAction<SelectorProviderImpl> pa = WindowsSelectorProvider::new;
PrivilegedAction<SelectorProviderImpl> pa = WEPollSelectorProvider::new;
INSTANCE = AccessController.doPrivileged(pa);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -61,10 +61,10 @@ class PipeImpl
private static final Random RANDOM_NUMBER_GENERATOR = new SecureRandom();
// Source and sink channels
private final SourceChannel source;
private final SinkChannel sink;
private final SourceChannelImpl source;
private final SinkChannelImpl sink;
private class Initializer
private static class Initializer
implements PrivilegedExceptionAction<Void>
{
@ -203,11 +203,11 @@ class PipeImpl
this.sink = initializer.sink;
}
public SourceChannel source() {
public SourceChannelImpl source() {
return source;
}
public SinkChannel sink() {
public SinkChannelImpl sink() {
return sink;
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2020, 2021, 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 jdk.internal.misc.Unsafe;
/**
* Provides access to wepoll.
*/
class WEPoll {
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
private static final int ADDRESS_SIZE = UNSAFE.addressSize();
private WEPoll() { }
/**
* typedef union epoll_data {
* void *ptr;
* int fd;
* uint32_t u32;
* uint64_t u64;
* SOCKET sock; // Windows specific
* HANDLE hnd; // Windows specific
* } epoll_data_t;
*
* struct epoll_event {
* uint32_t events;
* epoll_data_t data;
* }
*/
private static final int SIZEOF_EPOLLEVENT = eventSize();
private static final int OFFSETOF_EVENTS = eventsOffset();
private static final int OFFSETOF_SOCK = dataOffset();
// opcodes
static final int EPOLL_CTL_ADD = 1;
static final int EPOLL_CTL_MOD = 2;
static final int EPOLL_CTL_DEL = 3;
// events
static final int EPOLLIN = (1 << 0);
static final int EPOLLPRI = (1 << 1);
static final int EPOLLOUT = (1 << 2);
static final int EPOLLERR = (1 << 3);
static final int EPOLLHUP = (1 << 4);
// flags
static final int EPOLLONESHOT = (1 << 31);
/**
* Allocates a poll array to handle up to {@code count} events.
*/
static long allocatePollArray(int count) {
long size = (long) count * SIZEOF_EPOLLEVENT;
long base = UNSAFE.allocateMemory(size);
UNSAFE.setMemory(base, size, (byte) 0);
return base;
}
/**
* Free a poll array
*/
static void freePollArray(long address) {
UNSAFE.freeMemory(address);
}
/**
* Returns event[i];
*/
static long getEvent(long address, int i) {
return address + (SIZEOF_EPOLLEVENT*i);
}
/**
* Returns event->data.socket
*/
static long getSocket(long eventAddress) {
if (ADDRESS_SIZE == 8) {
return UNSAFE.getLong(eventAddress + OFFSETOF_SOCK);
} else {
return UNSAFE.getInt(eventAddress + OFFSETOF_SOCK);
}
}
/**
* Return event->data.socket as an int file descriptor
*/
static int getDescriptor(long eventAddress) {
long s = getSocket(eventAddress);
int fd = (int) s;
assert ((long) fd) == s;
return fd;
}
/**
* Returns event->events
*/
static int getEvents(long eventAddress) {
return UNSAFE.getInt(eventAddress + OFFSETOF_EVENTS);
}
// -- Native methods --
private static native int eventSize();
private static native int eventsOffset();
private static native int dataOffset();
static native long create() throws IOException;
static native int ctl(long h, int opcode, long s, int events);
static native int wait(long h, long pollAddress, int numfds, int timeout)
throws IOException;
static native void close(long h);
static {
IOUtil.load();
}
}

View File

@ -0,0 +1,276 @@
/*
* Copyright (c) 2020, 2021, 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.FileDescriptor;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.Pipe;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import static sun.nio.ch.WEPoll.*;
/**
* Windows wepoll based Selector implementation
*/
class WEPollSelectorImpl extends SelectorImpl {
// maximum number of events to poll in one call to epoll_wait
private static final int NUM_EPOLLEVENTS = 256;
// wepoll handle
private final long eph;
// address of epoll_event array when polling with epoll_wait
private final long pollArrayAddress;
// maps SOCKET to selection key, synchronize on selector
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
// pending new registrations/updates, queued by setEventOps
private final Object updateLock = new Object();
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
// interrupt/wakeup
private final Object interruptLock = new Object();
private boolean interruptTriggered;
private final PipeImpl pipe;
private final int fd0Val, fd1Val;
WEPollSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
this.eph = WEPoll.create();
this.pollArrayAddress = WEPoll.allocatePollArray(NUM_EPOLLEVENTS);
// wakeup support
try {
this.pipe = new PipeImpl(sp, /*buffering*/ false);
} catch (IOException ioe) {
WEPoll.freePollArray(pollArrayAddress);
WEPoll.close(eph);
throw ioe;
}
this.fd0Val = pipe.source().getFDVal();
this.fd1Val = pipe.sink().getFDVal();
// register one end of the pipe for wakeups
WEPoll.ctl(eph, EPOLL_CTL_ADD, fd0Val, WEPoll.EPOLLIN);
}
private void ensureOpen() {
if (!isOpen())
throw new ClosedSelectorException();
}
@Override
protected int doSelect(Consumer<SelectionKey> action, long timeout)
throws IOException
{
assert Thread.holdsLock(this);
// epoll_wait timeout is int
int to = (int) Math.min(timeout, Integer.MAX_VALUE);
boolean blocking = (to != 0);
int numEntries;
processUpdateQueue();
processDeregisterQueue();
try {
begin(blocking);
numEntries = WEPoll.wait(eph, pollArrayAddress, NUM_EPOLLEVENTS, to);
} finally {
end(blocking);
}
processDeregisterQueue();
return processEvents(numEntries, action);
}
/**
* Process changes to the interest ops.
*/
private void processUpdateQueue() {
assert Thread.holdsLock(this);
synchronized (updateLock) {
SelectionKeyImpl ski;
while ((ski = updateKeys.pollFirst()) != null) {
if (ski.isValid()) {
int fd = ski.getFDVal();
// add to fdToKey if needed
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
assert (previous == null) || (previous == ski);
int newOps = ski.translateInterestOps();
int registeredOps = ski.registeredEvents();
if (newOps != registeredOps) {
if (newOps == 0) {
// remove from epoll
WEPoll.ctl(eph, EPOLL_CTL_DEL, fd, 0);
} else {
int events = toEPollEvents(newOps);
if (registeredOps == 0) {
// add to epoll
WEPoll.ctl(eph, EPOLL_CTL_ADD, fd, events);
} else {
// modify events
WEPoll.ctl(eph, EPOLL_CTL_MOD, fd, events);
}
}
ski.registeredEvents(newOps);
}
}
}
}
}
/**
* Process the polled events.
* If the interrupt fd has been selected, drain it and clear the interrupt.
*/
private int processEvents(int numEntries, Consumer<SelectionKey> action)
throws IOException
{
assert Thread.holdsLock(this);
boolean interrupted = false;
int numKeysUpdated = 0;
for (int i = 0; i < numEntries; i++) {
long event = WEPoll.getEvent(pollArrayAddress, i);
int fd = WEPoll.getDescriptor(event);
if (fd == fd0Val) {
interrupted = true;
} else {
SelectionKeyImpl ski = fdToKey.get(fd);
if (ski != null) {
int events = WEPoll.getEvents(event);
if ((events & WEPoll.EPOLLPRI) != 0) {
Net.discardOOB(ski.getFD());
}
int rOps = toReadyOps(events);
numKeysUpdated += processReadyEvents(rOps, ski, action);
}
}
}
if (interrupted) {
clearInterrupt();
}
return numKeysUpdated;
}
@Override
protected void implClose() throws IOException {
assert !isOpen() && Thread.holdsLock(this);
// prevent further wakeup
synchronized (interruptLock) {
interruptTriggered = true;
}
// close the epoll port and free resources
WEPoll.close(eph);
WEPoll.freePollArray(pollArrayAddress);
pipe.sink().close();
pipe.source().close();
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
assert !ski.isValid() && Thread.holdsLock(this);
int fd = ski.getFDVal();
if (fdToKey.remove(fd) != null) {
if (ski.registeredEvents() != 0) {
WEPoll.ctl(eph, EPOLL_CTL_DEL, fd, 0);
ski.registeredEvents(0);
}
} else {
assert ski.registeredEvents() == 0;
}
}
@Override
public void setEventOps(SelectionKeyImpl ski) {
ensureOpen();
synchronized (updateLock) {
updateKeys.addLast(ski);
}
}
@Override
public Selector wakeup() {
synchronized (interruptLock) {
if (!interruptTriggered) {
try {
IOUtil.write1(fd1Val, (byte) 0);
} catch (IOException ioe) {
throw new InternalError(ioe);
}
interruptTriggered = true;
}
}
return this;
}
private void clearInterrupt() throws IOException {
synchronized (interruptLock) {
IOUtil.drain(fd0Val);
interruptTriggered = false;
}
}
/**
* Maps interest ops to epoll events
*/
private static int toEPollEvents(int ops) {
int events = EPOLLPRI;
if ((ops & Net.POLLIN) != 0)
events |= EPOLLIN;
if ((ops & (Net.POLLOUT | Net.POLLCONN)) != 0)
events |= EPOLLOUT;
return events;
}
/**
* Map epoll events to ready ops
*/
private static int toReadyOps(int events) {
int ops = 0;
if ((events & WEPoll.EPOLLIN) != 0) ops |= Net.POLLIN;
if ((events & WEPoll.EPOLLOUT) != 0) ops |= (Net.POLLOUT | Net.POLLCONN);
if ((events & WEPoll.EPOLLHUP) != 0) ops |= Net.POLLHUP;
if ((events & WEPoll.EPOLLERR) != 0) ops |= Net.POLLERR;
return ops;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020, 2021, 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.spi.AbstractSelector;
public class WEPollSelectorProvider extends SelectorProviderImpl {
public AbstractSelector openSelector() throws IOException {
return new WEPollSelectorImpl(this);
}
}

View File

@ -365,7 +365,9 @@ class WindowsSelectorImpl extends SelectorImpl {
private native int poll0(long pollAddress, int numfds,
int[] readFds, int[] writeFds, int[] exceptFds, long timeout, long fdsBuffer);
private int processSelectedKeys(long updateCount, Consumer<SelectionKey> action) {
private int processSelectedKeys(long updateCount, Consumer<SelectionKey> action)
throws IOException
{
int numKeysUpdated = 0;
numKeysUpdated += processFDSet(updateCount, action, readFds,
Net.POLLIN,
@ -392,6 +394,7 @@ class WindowsSelectorImpl extends SelectorImpl {
Consumer<SelectionKey> action,
int[] fds, int rOps,
boolean isExceptFds)
throws IOException
{
int numKeysUpdated = 0;
for (int i = 1; i <= fds[0]; i++) {
@ -415,7 +418,7 @@ class WindowsSelectorImpl extends SelectorImpl {
SelectableChannel sc = ski.channel();
if (isExceptFds && (sc instanceof SocketChannelImpl)
&& ((SocketChannelImpl) sc).isNetSocket()
&& discardUrgentData(desc)) {
&& Net.discardOOB(ski.getFD())) {
continue;
}
@ -511,8 +514,6 @@ class WindowsSelectorImpl extends SelectorImpl {
private native void resetWakeupSocket0(int wakeupSourceFd);
private native boolean discardUrgentData(int fd);
// We increment this counter on each call to updateSelectedKeys()
// each entry in SubSelector.fdsMap has a memorized value of
// updateCount. When we increment numKeysUpdated we set updateCount
@ -523,7 +524,7 @@ class WindowsSelectorImpl extends SelectorImpl {
// Update ops of the corresponding Channels. Add the ready keys to the
// ready queue.
private int updateSelectedKeys(Consumer<SelectionKey> action) {
private int updateSelectedKeys(Consumer<SelectionKey> action) throws IOException {
updateCount++;
int numKeysUpdated = 0;
numKeysUpdated += subSelector.processSelectedKeys(updateCount, action);

View File

@ -0,0 +1,34 @@
## Bert Belder: wepoll v 1.5.8
### wepoll License
```
wepoll - epoll for Windows
https://github.com/piscisaureus/wepoll
Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
@ -148,45 +148,36 @@ Java_sun_nio_ch_IOUtil_configureBlocking(JNIEnv *env, jclass clazz,
}
}
/* Note: Drain uses the int fd value. It is currently not called
on windows.
*/
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd)
{
DWORD read = 0;
int totalRead = 0;
BOOL result = 0;
HANDLE h = (HANDLE)_get_osfhandle(fd);
char buf[128];
if (h == INVALID_HANDLE_VALUE) {
JNU_ThrowIOExceptionWithLastError(env, "Read failed");
return JNI_FALSE;
}
char buf[16];
jboolean readBytes = JNI_FALSE;
for (;;) {
result = ReadFile(h, /* File handle to read */
(LPVOID)&buf, /* address to put data */
128, /* number of bytes to read */
&read, /* number of bytes read */
NULL); /* no overlapped struct */
if (result == 0) {
int error = GetLastError();
if (error == ERROR_NO_DATA) {
return (totalRead > 0) ? JNI_TRUE : JNI_FALSE;
int n = recv((SOCKET) fd, buf, sizeof(buf), 0);
if (n == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
JNU_ThrowIOExceptionWithLastError(env, "recv failed");
}
JNU_ThrowIOExceptionWithLastError(env, "Drain");
return JNI_FALSE;
}
if (read > 0) {
totalRead += read;
} else {
break;
return readBytes;
}
if (n <= 0)
return readBytes;
if (n < (int)sizeof(buf))
return JNI_TRUE;
readBytes = JNI_TRUE;
}
return (totalRead > 0) ? JNI_TRUE : JNI_FALSE;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_IOUtil_write1(JNIEnv *env, jclass cl, jint fd, jbyte b)
{
int n = send((SOCKET) fd, &b, 1, 0);
if (n == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
JNU_ThrowIOExceptionWithLastError(env, "send failed");
return IOS_THROWN;
}
return (n == 1) ? 1 : 0;
}
/* Note: This function returns the int fd value from file descriptor.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, 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
@ -654,8 +654,7 @@ Java_sun_nio_ch_Net_poll(JNIEnv* env, jclass this, jobject fdo, jint events, jlo
if (events & POLLIN) {
FD_SET(fd, &rd);
}
if (events & POLLOUT ||
events & POLLCONN) {
if (events & POLLOUT) {
FD_SET(fd, &wr);
}
FD_SET(fd, &ex);
@ -768,7 +767,7 @@ Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this)
JNIEXPORT jshort JNICALL
Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this)
{
return (jshort)POLLCONN;
return (jshort)POLLOUT;
}
JNIEXPORT jint JNICALL
@ -786,3 +785,24 @@ Java_sun_nio_ch_Net_sendOOB(JNIEnv* env, jclass this, jobject fdo, jbyte b)
return n;
}
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_discardOOB(JNIEnv* env, jclass clazz, jobject fdo)
{
char buf[8];
jboolean discarded = JNI_FALSE;
for (;;) {
int n = recv(fdval(env, fdo), (char*)&buf, sizeof(buf), MSG_OOB);
if (n == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
JNU_ThrowIOExceptionWithLastError(env, "recv failed");
}
return discarded;
}
if (n <= 0)
return discarded;
if (n < (int)sizeof(buf))
return JNI_TRUE;
discarded = JNI_TRUE;
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2020, 2021, 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.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include "wepoll.h"
#include "sun_nio_ch_WEPoll.h"
JNIEXPORT jint JNICALL
Java_sun_nio_ch_WEPoll_eventSize(JNIEnv* env, jclass clazz)
{
return sizeof(struct epoll_event);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_WEPoll_eventsOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct epoll_event, events);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_WEPoll_dataOffset(JNIEnv* env, jclass clazz)
{
return offsetof(struct epoll_event, data);
}
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_WEPoll_create(JNIEnv *env, jclass clazz) {
HANDLE h = epoll_create1(0);
if (h == NULL) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_create1 failed");
}
return ptr_to_jlong(h);
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_WEPoll_ctl(JNIEnv *env, jclass clazz, jlong h,
jint opcode, jlong s, jint events)
{
struct epoll_event event;
int res;
SOCKET socket = (SOCKET) jlong_to_ptr(s);
event.events = (uint32_t) events;
event.data.sock = socket;
res = epoll_ctl(jlong_to_ptr(h), opcode, socket, &event);
return (res == 0) ? 0 : errno;
}
JNIEXPORT jint JNICALL
Java_sun_nio_ch_WEPoll_wait(JNIEnv *env, jclass clazz, jlong h,
jlong address, jint numfds, jint timeout)
{
struct epoll_event *events = jlong_to_ptr(address);
int res = epoll_wait(jlong_to_ptr(h), events, numfds, timeout);
if (res < 0) {
JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
return IOS_THROWN;
}
return res;
}
JNIEXPORT void JNICALL
Java_sun_nio_ch_WEPoll_close(JNIEnv *env, jclass clazz, jlong h) {
epoll_close(jlong_to_ptr(h));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -99,8 +99,7 @@ Java_sun_nio_ch_WindowsSelectorImpl_00024SubSelector_poll0(JNIEnv *env, jobject
readfds->fd_array[read_count] = fds[i].fd;
read_count++;
}
if (fds[i].events & (POLLOUT | POLLCONN))
{
if (fds[i].events & POLLOUT) {
writefds->fd_array[write_count] = fds[i].fd;
write_count++;
}
@ -190,19 +189,3 @@ Java_sun_nio_ch_WindowsSelectorImpl_resetWakeupSocket0(JNIEnv *env, jclass this,
recv(scinFd, bytes, WAKEUP_SOCKET_BUF_SIZE, 0);
}
}
JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_WindowsSelectorImpl_discardUrgentData(JNIEnv* env, jobject this,
jint s)
{
char data[8];
jboolean discarded = JNI_FALSE;
int n;
do {
n = recv(s, (char*)&data, sizeof(data), MSG_OOB);
if (n > 0) {
discarded = JNI_TRUE;
}
} while (n > 0);
return discarded;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2021, 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
@ -64,22 +64,6 @@ struct iovec {
#endif
#ifndef POLLIN
/* WSAPoll()/WSAPOLLFD and the corresponding constants are only defined */
/* in Windows Vista / Windows Server 2008 and later. If we are on an */
/* older release we just use the Solaris constants as this was previously */
/* done in PollArrayWrapper.java. */
#define POLLIN 0x0001
#define POLLOUT 0x0004
#define POLLERR 0x0008
#define POLLHUP 0x0010
#define POLLNVAL 0x0020
#define POLLCONN 0x0002
#else
/* POLLCONN must not equal any of the other constants (see winsock2.h). */
#define POLLCONN 0x2000
#endif
/* Defined in UnixDomainSockets.c */
jbyteArray sockaddrToUnixAddressBytes(JNIEnv *env, struct sockaddr_un *sa, socklen_t len);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2020, 2021, 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
* wepoll - epoll for Windows
* https://github.com/piscisaureus/wepoll
*
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WEPOLL_H_
#define WEPOLL_H_
#ifndef WEPOLL_EXPORT
#define WEPOLL_EXPORT
#endif
#include <stdint.h>
enum EPOLL_EVENTS {
EPOLLIN = (int) (1U << 0),
EPOLLPRI = (int) (1U << 1),
EPOLLOUT = (int) (1U << 2),
EPOLLERR = (int) (1U << 3),
EPOLLHUP = (int) (1U << 4),
EPOLLRDNORM = (int) (1U << 6),
EPOLLRDBAND = (int) (1U << 7),
EPOLLWRNORM = (int) (1U << 8),
EPOLLWRBAND = (int) (1U << 9),
EPOLLMSG = (int) (1U << 10), /* Never reported. */
EPOLLRDHUP = (int) (1U << 13),
EPOLLONESHOT = (int) (1U << 31)
};
#define EPOLLIN (1U << 0)
#define EPOLLPRI (1U << 1)
#define EPOLLOUT (1U << 2)
#define EPOLLERR (1U << 3)
#define EPOLLHUP (1U << 4)
#define EPOLLRDNORM (1U << 6)
#define EPOLLRDBAND (1U << 7)
#define EPOLLWRNORM (1U << 8)
#define EPOLLWRBAND (1U << 9)
#define EPOLLMSG (1U << 10)
#define EPOLLRDHUP (1U << 13)
#define EPOLLONESHOT (1U << 31)
#define EPOLL_CTL_ADD 1
#define EPOLL_CTL_MOD 2
#define EPOLL_CTL_DEL 3
typedef void* HANDLE;
typedef uintptr_t SOCKET;
typedef union epoll_data {
void* ptr;
int fd;
uint32_t u32;
uint64_t u64;
SOCKET sock; /* Windows specific */
HANDLE hnd; /* Windows specific */
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events and flags */
epoll_data_t data; /* User data variable */
};
#ifdef __cplusplus
extern "C" {
#endif
WEPOLL_EXPORT HANDLE epoll_create(int size);
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
WEPOLL_EXPORT int epoll_close(HANDLE ephnd);
WEPOLL_EXPORT int epoll_ctl(HANDLE ephnd,
int op,
SOCKET sock,
struct epoll_event* event);
WEPOLL_EXPORT int epoll_wait(HANDLE ephnd,
struct epoll_event* events,
int maxevents,
int timeout);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WEPOLL_H_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2021, 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
@ -27,6 +27,11 @@
* @summary Test that Selector doesn't spin when changing interest ops
*/
/* @test
* @requires (os.family == "windows")
* @run main/othervm -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider ChangingInterests
*/
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2021, 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
@ -29,6 +29,11 @@
* @author kladko
*/
/* @test
* @requires (os.family == "windows")
* @run main/othervm -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider LotsOfChannels
*/
import java.net.*;
import java.io.*;
import java.nio.*;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2021, 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
@ -23,11 +23,12 @@
/* @test
* @bug 6213702
* @requires (os.family != "mac") | (os.version == "10.10.5")
* | (os.simpleVersion != "10.8" & os.simpleVersion != "10.9"
* & os.simpleVersion != "10.10")
* @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be
* selected
* @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be selected
*/
/* @test
* @requires (os.family == "windows")
* @run main/othervm -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider OutOfBand
*/
import java.net.*;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, 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
@ -39,6 +39,12 @@ import java.nio.channels.SocketChannel;
* @author Frank Ding
* @run main/timeout=1200 RacyDeregister
*/
/* @test
* @requires (os.family == "windows")
* @run main/othervm/timeout=1200 -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider RacyDeregister
*/
public class RacyDeregister {
// 90% of 1200 second timeout as milliseconds

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, 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
@ -22,10 +22,14 @@
*/
/* @test
* @summary Unit test for Selector.select/selectNow(Consumer)
* @bug 8199433 8208780
* @run testng SelectWithConsumer
* @summary Unit test for Selector select(Consumer), select(Consumer,long) and
* selectNow(Consumer)
*/
/* @test
* @requires (os.family == "windows")
* @run testng/othervm -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.WindowsSelectorProvider SelectWithConsumer
*/
import java.io.Closeable;

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2021, 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.
*
* 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 org.openjdk.bench.java.nio.channels;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Selector;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Benchmark for Selector.select(Consumer) when there is one channel ready.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class SelectOne {
private Selector sel;
private List<SocketChannel> clients;
private List<SocketChannel> peers;
private final int nready = 1; // one channel ready for reading
@Param({"1", "10", "100", "1000", "10000"})
private int nchannels; // number of registered channels
@Setup
public void setup() throws IOException {
sel = Selector.open();
clients = new ArrayList<SocketChannel>();
peers = new ArrayList<SocketChannel>();
try (ServerSocketChannel listener = ServerSocketChannel.open()) {
InetAddress loopback = InetAddress.getLoopbackAddress();
listener.bind(new InetSocketAddress(loopback, 0));
SocketAddress remote = listener.getLocalAddress();
for (int i = 0; i < nchannels; i++) {
SocketChannel sc = SocketChannel.open(remote);
sc.configureBlocking(false);
sc.register(sel, SelectionKey.OP_READ);
clients.add(sc);
SocketChannel peer = listener.accept();
peers.add(peer);
}
for (int i = nready - 1; i >= 0; i--) {
SocketChannel peer = peers.get(i);
peer.write(ByteBuffer.allocate(1));
}
}
}
@TearDown
public void teardown() throws IOException {
for (SocketChannel sc: clients) {
sc.close();
}
for (SocketChannel sc: peers) {
sc.close();
}
if (sel != null) {
sel.close();
}
}
@Benchmark
public void testSelectOne() throws IOException {
int nselected = sel.select(k -> { });
if (nselected != 1) {
throw new RuntimeException();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle America, Inc.
* Copyright (c) 2021, Oracle America, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,7 +29,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.bench.java.nio;
package org.openjdk.bench.java.nio.channels;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Level;