Skip to content

Commit cd5256d

Browse files
author
Alan Bateman
committed
8374170: I/O Poller updates
Reviewed-by: michaelm
1 parent 9f13ec1 commit cd5256d

33 files changed

+1005
-473
lines changed

src/java.base/aix/classes/sun/nio/ch/DefaultPollerProvider.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, 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
@@ -30,15 +30,28 @@
3030
* Default PollerProvider for AIX.
3131
*/
3232
class DefaultPollerProvider extends PollerProvider {
33-
DefaultPollerProvider() { }
33+
DefaultPollerProvider(Poller.Mode mode) {
34+
if (mode != Poller.Mode.SYSTEM_THREADS) {
35+
throw new UnsupportedOperationException();
36+
}
37+
super(mode);
38+
}
39+
40+
DefaultPollerProvider() {
41+
this(Poller.Mode.SYSTEM_THREADS);
42+
}
3443

3544
@Override
3645
Poller readPoller(boolean subPoller) throws IOException {
46+
if (subPoller)
47+
throw new UnsupportedOperationException();
3748
return new PollsetPoller(true);
3849
}
3950

4051
@Override
4152
Poller writePoller(boolean subPoller) throws IOException {
53+
if (subPoller)
54+
throw new UnsupportedOperationException();
4255
return new PollsetPoller(false);
4356
}
4457
}

src/java.base/aix/classes/sun/nio/ch/PollsetPoller.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2026, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2023, IBM Corp.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -52,21 +52,27 @@ class PollsetPoller extends Poller {
5252
this.pollBuffer = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL);
5353
}
5454

55+
@Override
56+
void close() {
57+
Pollset.pollsetDestroy(setid);
58+
Pollset.freePollArray(pollBuffer);
59+
}
60+
5561
@Override
5662
int fdVal() {
5763
return setid;
5864
}
5965

6066
@Override
61-
void implRegister(int fd) throws IOException {
67+
void implStartPoll(int fd) throws IOException {
6268
int ret = Pollset.pollsetCtl(setid, Pollset.PS_MOD, fd, Pollset.PS_POLLPRI | event);
6369
if (ret != 0) {
6470
throw new IOException("Unable to register fd " + fd);
6571
}
6672
}
6773

6874
@Override
69-
void implDeregister(int fd, boolean polled) {
75+
void implStopPoll(int fd, boolean polled) {
7076
int ret = Pollset.pollsetCtl(setid, Pollset.PS_DELETE, fd, 0);
7177
assert ret == 0;
7278
}

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

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, 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
@@ -31,34 +31,34 @@
3131
* Default PollerProvider for Linux.
3232
*/
3333
class DefaultPollerProvider extends PollerProvider {
34-
DefaultPollerProvider() { }
34+
DefaultPollerProvider(Poller.Mode mode) {
35+
super(mode);
36+
}
3537

36-
@Override
37-
Poller.Mode defaultPollerMode() {
38-
if (ContinuationSupport.isSupported()) {
39-
return Poller.Mode.VTHREAD_POLLERS;
40-
} else {
41-
return Poller.Mode.SYSTEM_THREADS;
42-
}
38+
DefaultPollerProvider() {
39+
var mode = ContinuationSupport.isSupported()
40+
? Poller.Mode.VTHREAD_POLLERS
41+
: Poller.Mode.SYSTEM_THREADS;
42+
this(mode);
4343
}
4444

4545
@Override
46-
int defaultReadPollers(Poller.Mode mode) {
46+
int defaultReadPollers() {
4747
int ncpus = Runtime.getRuntime().availableProcessors();
48-
if (mode == Poller.Mode.VTHREAD_POLLERS) {
49-
return Math.min(Integer.highestOneBit(ncpus), 32);
50-
} else {
51-
return Math.max(Integer.highestOneBit(ncpus / 4), 1);
52-
}
48+
return switch (pollerMode()) {
49+
case SYSTEM_THREADS -> Math.max(Integer.highestOneBit(ncpus / 4), 1);
50+
case VTHREAD_POLLERS -> Math.min(Integer.highestOneBit(ncpus), 32);
51+
default -> super.defaultReadPollers();
52+
};
5353
}
5454

5555
@Override
5656
Poller readPoller(boolean subPoller) throws IOException {
57-
return new EPollPoller(subPoller, true);
57+
return new EPollPoller(pollerMode(), subPoller, true);
5858
}
5959

6060
@Override
6161
Poller writePoller(boolean subPoller) throws IOException {
62-
return new EPollPoller(subPoller, false);
62+
return new EPollPoller(pollerMode(), subPoller, false);
6363
}
6464
}

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

Lines changed: 83 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, 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
@@ -25,6 +25,8 @@
2525
package sun.nio.ch;
2626

2727
import java.io.IOException;
28+
import java.lang.ref.Cleaner.Cleanable;
29+
import jdk.internal.ref.CleanerFactory;
2830
import static sun.nio.ch.EPoll.*;
2931

3032
/**
@@ -38,12 +40,70 @@ class EPollPoller extends Poller {
3840
private final int event;
3941
private final int maxEvents;
4042
private final long address;
43+
private final EventFD eventfd; // wakeup event, used for shutdown
4144

42-
EPollPoller(boolean subPoller, boolean read) throws IOException {
43-
this.epfd = EPoll.create();
45+
// close action, and cleaner if this is subpoller
46+
private final Runnable closer;
47+
private final Cleanable cleaner;
48+
49+
EPollPoller(Poller.Mode mode, boolean subPoller, boolean read) throws IOException {
50+
boolean wakeable = (mode == Mode.POLLER_PER_CARRIER) && subPoller;
51+
int maxEvents = (subPoller) ? 16 : 64;
52+
53+
int epfd = EPoll.create();
54+
long address = 0L;
55+
EventFD eventfd = null;
56+
try {
57+
address = EPoll.allocatePollArray(maxEvents);
58+
59+
// register one end of the pipe with epoll to allow for wakeup
60+
if (wakeable) {
61+
eventfd = new EventFD();
62+
IOUtil.configureBlocking(eventfd.efd(), false);
63+
EPoll.ctl(epfd, EPOLL_CTL_ADD, eventfd.efd(), EPOLLIN);
64+
}
65+
} catch (Throwable e) {
66+
FileDispatcherImpl.closeIntFD(epfd);
67+
if (address != 0L) EPoll.freePollArray(address);
68+
if (eventfd != null) eventfd.close();
69+
throw e;
70+
}
71+
72+
this.epfd = epfd;
4473
this.event = (read) ? EPOLLIN : EPOLLOUT;
45-
this.maxEvents = (subPoller) ? 64 : 512;
46-
this.address = EPoll.allocatePollArray(maxEvents);
74+
this.maxEvents = maxEvents;
75+
this.address = address;
76+
this.eventfd = eventfd;
77+
78+
// create action to close epoll instance, register cleaner when wakeable
79+
this.closer = closer(epfd, address, eventfd);
80+
if (wakeable) {
81+
this.cleaner = CleanerFactory.cleaner().register(this, closer);
82+
} else {
83+
this.cleaner = null;
84+
}
85+
}
86+
87+
/**
88+
* Returns an action to close the epoll instance and release other resources.
89+
*/
90+
private static Runnable closer(int epfd, long address, EventFD eventfd) {
91+
return () -> {
92+
try {
93+
FileDispatcherImpl.closeIntFD(epfd);
94+
EPoll.freePollArray(address);
95+
if (eventfd != null) eventfd.close();
96+
} catch (IOException _) { }
97+
};
98+
}
99+
100+
@Override
101+
void close() {
102+
if (cleaner != null) {
103+
cleaner.clean();
104+
} else {
105+
closer.run();
106+
}
47107
}
48108

49109
@Override
@@ -52,8 +112,8 @@ int fdVal() {
52112
}
53113

54114
@Override
55-
void implRegister(int fdVal) throws IOException {
56-
// re-arm
115+
void implStartPoll(int fdVal) throws IOException {
116+
// re-enable if already registered but disabled (previously polled)
57117
int err = EPoll.ctl(epfd, EPOLL_CTL_MOD, fdVal, (event | EPOLLONESHOT));
58118
if (err == ENOENT)
59119
err = EPoll.ctl(epfd, EPOLL_CTL_ADD, fdVal, (event | EPOLLONESHOT));
@@ -62,24 +122,36 @@ void implRegister(int fdVal) throws IOException {
62122
}
63123

64124
@Override
65-
void implDeregister(int fdVal, boolean polled) {
125+
void implStopPoll(int fdVal, boolean polled) {
66126
// event is disabled if already polled
67127
if (!polled) {
68128
EPoll.ctl(epfd, EPOLL_CTL_DEL, fdVal, 0);
69129
}
70130
}
71131

132+
@Override
133+
void wakeupPoller() throws IOException {
134+
if (eventfd == null) {
135+
throw new UnsupportedOperationException();
136+
}
137+
eventfd.set();
138+
}
139+
72140
@Override
73141
int poll(int timeout) throws IOException {
74142
int n = EPoll.wait(epfd, address, maxEvents, timeout);
143+
int polled = 0;
75144
int i = 0;
76145
while (i < n) {
77146
long eventAddress = EPoll.getEvent(address, i);
78-
int fdVal = EPoll.getDescriptor(eventAddress);
79-
polled(fdVal);
147+
int fd = EPoll.getDescriptor(eventAddress);
148+
if (eventfd == null || fd != eventfd.efd()) {
149+
polled(fd);
150+
polled++;
151+
}
80152
i++;
81153
}
82-
return n;
154+
return polled;
83155
}
84156
}
85157

src/java.base/macosx/classes/sun/nio/ch/DefaultPollerProvider.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, 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
@@ -30,15 +30,21 @@
3030
* Default PollerProvider for macOS.
3131
*/
3232
class DefaultPollerProvider extends PollerProvider {
33-
DefaultPollerProvider() { }
33+
DefaultPollerProvider(Poller.Mode mode) {
34+
super(mode);
35+
}
36+
37+
DefaultPollerProvider() {
38+
this(Poller.Mode.SYSTEM_THREADS);
39+
}
3440

3541
@Override
3642
Poller readPoller(boolean subPoller) throws IOException {
37-
return new KQueuePoller(subPoller, true);
43+
return new KQueuePoller(pollerMode(), subPoller, true);
3844
}
3945

4046
@Override
4147
Poller writePoller(boolean subPoller) throws IOException {
42-
return new KQueuePoller(subPoller, false);
48+
return new KQueuePoller(pollerMode(), subPoller, false);
4349
}
4450
}

0 commit comments

Comments
 (0)