Skip to content

Commit a8073ef

Browse files
author
Brian Burkhalter
committed
8253478: (se) epoll Selector should use eventfd for wakeup instead of pipe
Reviewed-by: alanb
1 parent 34eb8b3 commit a8073ef

File tree

4 files changed

+200
-14
lines changed

4 files changed

+200
-14
lines changed

src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -58,9 +58,8 @@ class EPollSelectorImpl extends SelectorImpl {
5858
// address of poll array when polling with epoll_wait
5959
private final long pollArrayAddress;
6060

61-
// file descriptors used for interrupt
62-
private final int fd0;
63-
private final int fd1;
61+
// eventfd object used for interrupt
62+
private final EventFD eventfd;
6463

6564
// maps file descriptor to selection key, synchronize on selector
6665
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
@@ -80,17 +79,16 @@ class EPollSelectorImpl extends SelectorImpl {
8079
this.pollArrayAddress = EPoll.allocatePollArray(NUM_EPOLLEVENTS);
8180

8281
try {
83-
long fds = IOUtil.makePipe(false);
84-
this.fd0 = (int) (fds >>> 32);
85-
this.fd1 = (int) fds;
82+
this.eventfd = new EventFD();
83+
IOUtil.configureBlocking(IOUtil.newFD(eventfd.efd()), false);
8684
} catch (IOException ioe) {
8785
EPoll.freePollArray(pollArrayAddress);
8886
FileDispatcherImpl.closeIntFD(epfd);
8987
throw ioe;
9088
}
9189

92-
// register one end of the socket pair for wakeups
93-
EPoll.ctl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
90+
// register the eventfd object for wakeups
91+
EPoll.ctl(epfd, EPOLL_CTL_ADD, eventfd.efd(), EPOLLIN);
9492
}
9593

9694
private void ensureOpen() {
@@ -188,7 +186,7 @@ private int processEvents(int numEntries, Consumer<SelectionKey> action)
188186
for (int i=0; i<numEntries; i++) {
189187
long event = EPoll.getEvent(pollArrayAddress, i);
190188
int fd = EPoll.getDescriptor(event);
191-
if (fd == fd0) {
189+
if (fd == eventfd.efd()) {
192190
interrupted = true;
193191
} else {
194192
SelectionKeyImpl ski = fdToKey.get(fd);
@@ -218,8 +216,7 @@ protected void implClose() throws IOException {
218216
FileDispatcherImpl.closeIntFD(epfd);
219217
EPoll.freePollArray(pollArrayAddress);
220218

221-
FileDispatcherImpl.closeIntFD(fd0);
222-
FileDispatcherImpl.closeIntFD(fd1);
219+
eventfd.close();
223220
}
224221

225222
@Override
@@ -251,7 +248,7 @@ public Selector wakeup() {
251248
synchronized (interruptLock) {
252249
if (!interruptTriggered) {
253250
try {
254-
IOUtil.write1(fd1, (byte)0);
251+
eventfd.set();
255252
} catch (IOException ioe) {
256253
throw new InternalError(ioe);
257254
}
@@ -263,7 +260,7 @@ public Selector wakeup() {
263260

264261
private void clearInterrupt() throws IOException {
265262
synchronized (interruptLock) {
266-
IOUtil.drain(fd0);
263+
eventfd.reset();
267264
interruptTriggered = false;
268265
}
269266
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package sun.nio.ch;
27+
28+
import java.io.IOException;
29+
30+
/*
31+
* Provides access to the Linux eventfd object.
32+
*/
33+
final class EventFD {
34+
private final int efd;
35+
36+
/**
37+
* Creates a blocking eventfd object with initial value zero.
38+
*/
39+
EventFD() throws IOException {
40+
efd = eventfd0();
41+
}
42+
43+
int efd() {
44+
return efd;
45+
}
46+
47+
void set() throws IOException {
48+
set0(efd);
49+
}
50+
51+
void reset() throws IOException {
52+
IOUtil.drain(efd);
53+
}
54+
55+
void close() throws IOException {
56+
FileDispatcherImpl.closeIntFD(efd);
57+
}
58+
59+
private static native int eventfd0() throws IOException;
60+
61+
/**
62+
* Writes the value 1 to the eventfd object as a long in the
63+
* native byte order of the platform.
64+
*
65+
* @param the integral eventfd file descriptor
66+
* @return the number of bytes written; should equal 8
67+
*/
68+
private static native int set0(int efd) throws IOException;
69+
70+
static {
71+
IOUtil.load();
72+
}
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
#include <sys/eventfd.h>
27+
28+
#include "jni.h"
29+
#include "jni_util.h"
30+
#include "jvm.h"
31+
#include "jlong.h"
32+
#include "nio.h"
33+
#include "nio_util.h"
34+
35+
#include "sun_nio_ch_EventFD.h"
36+
37+
JNIEXPORT jint JNICALL
38+
Java_sun_nio_ch_EventFD_eventfd0(JNIEnv *env, jclass klazz)
39+
{
40+
int efd = eventfd((uint64_t)0, 0);
41+
if (efd == -1) {
42+
JNU_ThrowIOExceptionWithLastError(env, "eventfd failed");
43+
return IOS_THROWN;
44+
}
45+
return efd;
46+
}
47+
48+
JNIEXPORT jint JNICALL
49+
Java_sun_nio_ch_EventFD_set0(JNIEnv *env, jclass klazz, jint efd)
50+
{
51+
long one = 1L;
52+
return convertReturnVal(env, write(efd, (void*)&one, sizeof(long)),
53+
JNI_FALSE);
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2014, Oracle America, Inc.
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* * Redistributions of source code must retain the above copyright notice,
9+
* this list of conditions and the following disclaimer.
10+
*
11+
* * Redistributions in binary form must reproduce the above copyright
12+
* notice, this list of conditions and the following disclaimer in the
13+
* documentation and/or other materials provided with the distribution.
14+
*
15+
* * Neither the name of Oracle nor the names of its contributors may be used
16+
* to endorse or promote products derived from this software without
17+
* specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29+
* THE POSSIBILITY OF SUCH DAMAGE.
30+
*/
31+
32+
package org.openjdk.bench.java.nio;
33+
34+
import org.openjdk.jmh.annotations.Benchmark;
35+
import org.openjdk.jmh.annotations.Level;
36+
import org.openjdk.jmh.annotations.Scope;
37+
import org.openjdk.jmh.annotations.Setup;
38+
import org.openjdk.jmh.annotations.State;
39+
40+
import java.io.*;
41+
import java.net.*;
42+
import java.nio.*;
43+
import java.nio.channels.*;
44+
45+
/**
46+
* Benchmark for the Selector wakeup mechanism. Intended primarily for the
47+
* epoll(7)-based implementation on Linux.
48+
*/
49+
@State(Scope.Thread)
50+
public class SelectorWakeup {
51+
private Selector sel;
52+
53+
@Setup(Level.Iteration)
54+
public void setup() throws IOException {
55+
sel = Selector.open();
56+
}
57+
58+
@Benchmark
59+
public int test() throws IOException {
60+
return sel.wakeup().select();
61+
}
62+
}

0 commit comments

Comments
 (0)