rust/cargo-c: update to 0.10.7+cargo-0.84.0
[oi-userland.git] / components / runtime / openjdk-23 / patches / illumos-pollerprovider.patch
blob03c407332343099320598b5b0fd766ef8a99ac36
1 --- /dev/null Sun May 15 10:42:57 2022
2 +++ a/src/java.base/solaris/classes/sun/nio/ch/DefaultPollerProvider.java Sun May 15 10:17:39 2022
3 @@ -0,0 +1,44 @@
4 +/*
5 + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7 + *
8 + * This code is free software; you can redistribute it and/or modify it
9 + * under the terms of the GNU General Public License version 2 only, as
10 + * published by the Free Software Foundation. Oracle designates this
11 + * particular file as subject to the "Classpath" exception as provided
12 + * by Oracle in the LICENSE file that accompanied this code.
13 + *
14 + * This code is distributed in the hope that it will be useful, but WITHOUT
15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 + * version 2 for more details (a copy is included in the LICENSE file that
18 + * accompanied this code).
19 + *
20 + * You should have received a copy of the GNU General Public License version
21 + * 2 along with this work; if not, write to the Free Software Foundation,
22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23 + *
24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25 + * or visit www.oracle.com if you need additional information or have any
26 + * questions.
27 + */
28 +package sun.nio.ch;
30 +import java.io.IOException;
32 +/**
33 + * Default PollerProvider for illumos/Solaris.
34 + */
35 +class DefaultPollerProvider extends PollerProvider {
36 + DefaultPollerProvider() { }
38 + @Override
39 + Poller readPoller(boolean subPoller) throws IOException {
40 + return new SolarisEventPortPoller(subPoller, true);
41 + }
43 + @Override
44 + Poller writePoller(boolean subPoller) throws IOException {
45 + return new SolarisEventPortPoller(subPoller, false);
46 + }
48 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPoll.java jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPoll.java
49 --- jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPoll.java 1970-01-01 01:00:00.000000000 +0100
50 +++ jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPoll.java 2023-11-09 09:45:49.844024203 +0000
51 @@ -0,0 +1,121 @@
52 +/*
53 + * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
54 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55 + *
56 + * This code is free software; you can redistribute it and/or modify it
57 + * under the terms of the GNU General Public License version 2 only, as
58 + * published by the Free Software Foundation. Oracle designates this
59 + * particular file as subject to the "Classpath" exception as provided
60 + * by Oracle in the LICENSE file that accompanied this code.
61 + *
62 + * This code is distributed in the hope that it will be useful, but WITHOUT
63 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
64 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
65 + * version 2 for more details (a copy is included in the LICENSE file that
66 + * accompanied this code).
67 + *
68 + * You should have received a copy of the GNU General Public License version
69 + * 2 along with this work; if not, write to the Free Software Foundation,
70 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
71 + *
72 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
73 + * or visit www.oracle.com if you need additional information or have any
74 + * questions.
75 + */
77 +package sun.nio.ch;
79 +import java.io.IOException;
80 +import jdk.internal.misc.Unsafe;
82 +/**
83 + * Provides access to the Linux epoll facility.
84 + */
86 +class EPoll {
87 + private EPoll() { }
89 + private static final Unsafe unsafe = Unsafe.getUnsafe();
91 + /**
92 + * typedef union epoll_data {
93 + * void *ptr;
94 + * int fd;
95 + * __uint32_t u32;
96 + * __uint64_t u64;
97 + * } epoll_data_t;
98 + *
99 + * struct epoll_event {
100 + * __uint32_t events;
101 + * epoll_data_t data;
102 + * }
103 + */
104 + static {
105 + IOUtil.load();
107 + private static final int SIZEOF_EPOLLEVENT = eventSize();
108 + private static final int OFFSETOF_EVENTS = eventsOffset();
109 + private static final int OFFSETOF_FD = dataOffset();
111 + // opcodes
112 + static final int EPOLL_CTL_ADD = 1;
113 + static final int EPOLL_CTL_DEL = 2;
114 + static final int EPOLL_CTL_MOD = 3;
116 + // events
117 + static final int EPOLLIN = 0x1;
118 + static final int EPOLLOUT = 0x4;
120 + // flags
121 + static final int EPOLLONESHOT = (1 << 30);
123 + /**
124 + * Allocates a poll array to handle up to {@code count} events.
125 + */
126 + static long allocatePollArray(int count) {
127 + return unsafe.allocateMemory(count * SIZEOF_EPOLLEVENT);
130 + /**
131 + * Free a poll array
132 + */
133 + static void freePollArray(long address) {
134 + unsafe.freeMemory(address);
137 + /**
138 + * Returns event[i];
139 + */
140 + static long getEvent(long address, int i) {
141 + return address + (SIZEOF_EPOLLEVENT*i);
144 + /**
145 + * Returns event->data.fd
146 + */
147 + static int getDescriptor(long eventAddress) {
148 + return unsafe.getInt(eventAddress + OFFSETOF_FD);
151 + /**
152 + * Returns event->events
153 + */
154 + static int getEvents(long eventAddress) {
155 + return unsafe.getInt(eventAddress + OFFSETOF_EVENTS);
158 + // -- Native methods --
160 + private static native int eventSize();
162 + private static native int eventsOffset();
164 + private static native int dataOffset();
166 + static native int create() throws IOException;
168 + static native int ctl(int epfd, int opcode, int fd, int events);
170 + static native int wait(int epfd, long pollAddress, int numfds, int timeout)
171 + throws IOException;
173 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollPoller.java jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollPoller.java
174 --- jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollPoller.java 1970-01-01 01:00:00.000000000 +0100
175 +++ jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollPoller.java 2023-11-09 09:45:51.976254333 +0000
176 @@ -0,0 +1,85 @@
178 + * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
179 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
181 + * This code is free software; you can redistribute it and/or modify it
182 + * under the terms of the GNU General Public License version 2 only, as
183 + * published by the Free Software Foundation. Oracle designates this
184 + * particular file as subject to the "Classpath" exception as provided
185 + * by Oracle in the LICENSE file that accompanied this code.
187 + * This code is distributed in the hope that it will be useful, but WITHOUT
188 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
189 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
190 + * version 2 for more details (a copy is included in the LICENSE file that
191 + * accompanied this code).
193 + * You should have received a copy of the GNU General Public License version
194 + * 2 along with this work; if not, write to the Free Software Foundation,
195 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
197 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
198 + * or visit www.oracle.com if you need additional information or have any
199 + * questions.
200 + */
201 +package sun.nio.ch;
203 +import java.io.IOException;
204 +import static sun.nio.ch.EPoll.*;
206 +/**
207 + * Poller implementation based on the epoll facility.
208 + */
210 +class EPollPoller extends Poller {
211 + private static final int ENOENT = 2;
213 + private final int epfd;
214 + private final int event;
215 + private final int maxEvents;
216 + private final long address;
218 + EPollPoller(boolean subPoller, boolean read) throws IOException {
219 + this.epfd = EPoll.create();
220 + this.event = (read) ? EPOLLIN : EPOLLOUT;
221 + this.maxEvents = (subPoller) ? 64 : 512;
222 + this.address = EPoll.allocatePollArray(maxEvents);
225 + @Override
226 + int fdVal() {
227 + return epfd;
230 + @Override
231 + void implRegister(int fdVal) throws IOException {
232 + // re-arm
233 + int err = EPoll.ctl(epfd, EPOLL_CTL_MOD, fdVal, (event | EPOLLONESHOT));
234 + if (err == ENOENT)
235 + err = EPoll.ctl(epfd, EPOLL_CTL_ADD, fdVal, (event | EPOLLONESHOT));
236 + if (err != 0)
237 + throw new IOException("epoll_ctl failed: " + err);
240 + @Override
241 + void implDeregister(int fdVal, boolean polled) {
242 + // event is disabled if already polled
243 + if (!polled) {
244 + EPoll.ctl(epfd, EPOLL_CTL_DEL, fdVal, 0);
248 + @Override
249 + int poll(int timeout) throws IOException {
250 + int n = EPoll.wait(epfd, address, maxEvents, timeout);
251 + int i = 0;
252 + while (i < n) {
253 + long eventAddress = EPoll.getEvent(address, i);
254 + int fdVal = EPoll.getDescriptor(eventAddress);
255 + polled(fdVal);
256 + i++;
258 + return n;
262 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollPort.java jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollPort.java
263 --- jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollPort.java 1970-01-01 01:00:00.000000000 +0100
264 +++ jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollPort.java 2023-11-09 09:45:51.976499486 +0000
265 @@ -0,0 +1,320 @@
267 + * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
268 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
270 + * This code is free software; you can redistribute it and/or modify it
271 + * under the terms of the GNU General Public License version 2 only, as
272 + * published by the Free Software Foundation. Oracle designates this
273 + * particular file as subject to the "Classpath" exception as provided
274 + * by Oracle in the LICENSE file that accompanied this code.
276 + * This code is distributed in the hope that it will be useful, but WITHOUT
277 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
278 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
279 + * version 2 for more details (a copy is included in the LICENSE file that
280 + * accompanied this code).
282 + * You should have received a copy of the GNU General Public License version
283 + * 2 along with this work; if not, write to the Free Software Foundation,
284 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
286 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
287 + * or visit www.oracle.com if you need additional information or have any
288 + * questions.
289 + */
291 +package sun.nio.ch;
293 +import java.nio.channels.spi.AsynchronousChannelProvider;
294 +import java.io.IOException;
295 +import java.util.concurrent.ArrayBlockingQueue;
296 +import java.util.concurrent.RejectedExecutionException;
297 +import java.util.concurrent.atomic.AtomicInteger;
299 +import static sun.nio.ch.EPoll.EPOLLIN;
300 +import static sun.nio.ch.EPoll.EPOLLONESHOT;
301 +import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
302 +import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
305 +/**
306 + * AsynchronousChannelGroup implementation based on the Linux epoll facility.
307 + */
309 +final class EPollPort
310 + extends Port
312 + // maximum number of events to poll at a time
313 + private static final int MAX_EPOLL_EVENTS = 512;
315 + // errors
316 + private static final int ENOENT = 2;
318 + // epoll file descriptor
319 + private final int epfd;
321 + // address of the poll array passed to epoll_wait
322 + private final long address;
324 + // true if epoll closed
325 + private boolean closed;
327 + // socket pair used for wakeup
328 + private final int sp[];
330 + // number of wakeups pending
331 + private final AtomicInteger wakeupCount = new AtomicInteger();
333 + // encapsulates an event for a channel
334 + static class Event {
335 + final PollableChannel channel;
336 + final int events;
338 + Event(PollableChannel channel, int events) {
339 + this.channel = channel;
340 + this.events = events;
343 + PollableChannel channel() { return channel; }
344 + int events() { return events; }
347 + // queue of events for cases that a polling thread dequeues more than one
348 + // event
349 + private final ArrayBlockingQueue<Event> queue;
350 + private final Event NEED_TO_POLL = new Event(null, 0);
351 + private final Event EXECUTE_TASK_OR_SHUTDOWN = new Event(null, 0);
353 + EPollPort(AsynchronousChannelProvider provider, ThreadPool pool)
354 + throws IOException
356 + super(provider, pool);
358 + this.epfd = EPoll.create();
359 + this.address = EPoll.allocatePollArray(MAX_EPOLL_EVENTS);
361 + // create socket pair for wakeup mechanism
362 + try {
363 + long fds = IOUtil.makePipe(true);
364 + this.sp = new int[]{(int) (fds >>> 32), (int) fds};
365 + } catch (IOException ioe) {
366 + EPoll.freePollArray(address);
367 + FileDispatcherImpl.closeIntFD(epfd);
368 + throw ioe;
371 + // register one end with epoll
372 + EPoll.ctl(epfd, EPOLL_CTL_ADD, sp[0], EPOLLIN);
374 + // create the queue and offer the special event to ensure that the first
375 + // threads polls
376 + this.queue = new ArrayBlockingQueue<>(MAX_EPOLL_EVENTS);
377 + this.queue.offer(NEED_TO_POLL);
380 + EPollPort start() {
381 + startThreads(new EventHandlerTask());
382 + return this;
385 + /**
386 + * Release all resources
387 + */
388 + private void implClose() {
389 + synchronized (this) {
390 + if (closed)
391 + return;
392 + closed = true;
394 + try { FileDispatcherImpl.closeIntFD(epfd); } catch (IOException ioe) { }
395 + try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
396 + try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
397 + EPoll.freePollArray(address);
400 + private void wakeup() {
401 + if (wakeupCount.incrementAndGet() == 1) {
402 + // write byte to socketpair to force wakeup
403 + try {
404 + IOUtil.write1(sp[1], (byte)0);
405 + } catch (IOException x) {
406 + throw new AssertionError(x);
411 + @Override
412 + void executeOnHandlerTask(Runnable task) {
413 + synchronized (this) {
414 + if (closed)
415 + throw new RejectedExecutionException();
416 + offerTask(task);
417 + wakeup();
421 + @Override
422 + void shutdownHandlerTasks() {
423 + /*
424 + * If no tasks are running then just release resources; otherwise
425 + * write to the one end of the socketpair to wakeup any polling threads.
426 + */
427 + int nThreads = threadCount();
428 + if (nThreads == 0) {
429 + implClose();
430 + } else {
431 + // send wakeup to each thread
432 + while (nThreads-- > 0) {
433 + wakeup();
438 + // invoke by clients to register a file descriptor
439 + @Override
440 + void startPoll(int fd, int events) {
441 + // update events (or add to epoll on first usage)
442 + int err = EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
443 + if (err == ENOENT)
444 + err = EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
445 + if (err != 0)
446 + throw new AssertionError(); // should not happen
449 + /**
450 + * Task to process events from epoll and dispatch to the channel's
451 + * onEvent handler.
453 + * Events are retrieved from epoll in batch and offered to a BlockingQueue
454 + * where they are consumed by handler threads. A special "NEED_TO_POLL"
455 + * event is used to signal one consumer to re-poll when all events have
456 + * been consumed.
457 + */
458 + private class EventHandlerTask implements Runnable {
459 + private Event poll() throws IOException {
460 + try {
461 + for (;;) {
462 + int n;
463 + do {
464 + n = EPoll.wait(epfd, address, MAX_EPOLL_EVENTS, -1);
465 + } while (n == IOStatus.INTERRUPTED);
467 + /**
468 + * 'n' events have been read. Here we map them to their
469 + * corresponding channel in batch and queue n-1 so that
470 + * they can be handled by other handler threads. The last
471 + * event is handled by this thread (and so is not queued).
472 + */
473 + fdToChannelLock.readLock().lock();
474 + try {
475 + while (n-- > 0) {
476 + long eventAddress = EPoll.getEvent(address, n);
477 + int fd = EPoll.getDescriptor(eventAddress);
479 + // wakeup
480 + if (fd == sp[0]) {
481 + if (wakeupCount.decrementAndGet() == 0) {
482 + // consume one wakeup byte, never more as this
483 + // would interfere with shutdown when there is
484 + // a wakeup byte queued to wake each thread
485 + int nread;
486 + do {
487 + nread = IOUtil.drain1(sp[0]);
488 + } while (nread == IOStatus.INTERRUPTED);
491 + // queue special event if there are more events
492 + // to handle.
493 + if (n > 0) {
494 + queue.offer(EXECUTE_TASK_OR_SHUTDOWN);
495 + continue;
497 + return EXECUTE_TASK_OR_SHUTDOWN;
500 + PollableChannel channel = fdToChannel.get(fd);
501 + if (channel != null) {
502 + int events = EPoll.getEvents(eventAddress);
503 + Event ev = new Event(channel, events);
505 + // n-1 events are queued; This thread handles
506 + // the last one except for the wakeup
507 + if (n > 0) {
508 + queue.offer(ev);
509 + } else {
510 + return ev;
514 + } finally {
515 + fdToChannelLock.readLock().unlock();
518 + } finally {
519 + // to ensure that some thread will poll when all events have
520 + // been consumed
521 + queue.offer(NEED_TO_POLL);
525 + public void run() {
526 + Invoker.GroupAndInvokeCount myGroupAndInvokeCount =
527 + Invoker.getGroupAndInvokeCount();
528 + final boolean isPooledThread = (myGroupAndInvokeCount != null);
529 + boolean replaceMe = false;
530 + Event ev;
531 + try {
532 + for (;;) {
533 + // reset invoke count
534 + if (isPooledThread)
535 + myGroupAndInvokeCount.resetInvokeCount();
537 + try {
538 + replaceMe = false;
539 + ev = queue.take();
541 + // no events and this thread has been "selected" to
542 + // poll for more.
543 + if (ev == NEED_TO_POLL) {
544 + try {
545 + ev = poll();
546 + } catch (IOException x) {
547 + x.printStackTrace();
548 + return;
551 + } catch (InterruptedException x) {
552 + continue;
555 + // handle wakeup to execute task or shutdown
556 + if (ev == EXECUTE_TASK_OR_SHUTDOWN) {
557 + Runnable task = pollTask();
558 + if (task == null) {
559 + // shutdown request
560 + return;
562 + // run task (may throw error/exception)
563 + replaceMe = true;
564 + task.run();
565 + continue;
568 + // process event
569 + try {
570 + ev.channel().onEvent(ev.events(), isPooledThread);
571 + } catch (Error | RuntimeException x) {
572 + replaceMe = true;
573 + throw x;
576 + } finally {
577 + // last handler to exit when shutdown releases resources
578 + int remaining = threadExit(this, replaceMe);
579 + if (remaining == 0 && isShutdown()) {
580 + implClose();
586 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorImpl.java jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorImpl.java
587 --- jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorImpl.java 1970-01-01 01:00:00.000000000 +0100
588 +++ jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorImpl.java 2023-11-09 09:45:51.976701355 +0000
589 @@ -0,0 +1,273 @@
591 + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
592 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
594 + * This code is free software; you can redistribute it and/or modify it
595 + * under the terms of the GNU General Public License version 2 only, as
596 + * published by the Free Software Foundation. Oracle designates this
597 + * particular file as subject to the "Classpath" exception as provided
598 + * by Oracle in the LICENSE file that accompanied this code.
600 + * This code is distributed in the hope that it will be useful, but WITHOUT
601 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
602 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
603 + * version 2 for more details (a copy is included in the LICENSE file that
604 + * accompanied this code).
606 + * You should have received a copy of the GNU General Public License version
607 + * 2 along with this work; if not, write to the Free Software Foundation,
608 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
610 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
611 + * or visit www.oracle.com if you need additional information or have any
612 + * questions.
613 + */
615 +package sun.nio.ch;
617 +import java.io.IOException;
618 +import java.nio.channels.ClosedSelectorException;
619 +import java.nio.channels.SelectionKey;
620 +import java.nio.channels.Selector;
621 +import java.nio.channels.spi.SelectorProvider;
622 +import java.util.ArrayDeque;
623 +import java.util.Deque;
624 +import java.util.HashMap;
625 +import java.util.Map;
626 +import java.util.concurrent.TimeUnit;
627 +import java.util.function.Consumer;
628 +import jdk.internal.misc.Blocker;
630 +import static sun.nio.ch.EPoll.EPOLLIN;
631 +import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
632 +import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
633 +import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
636 +/**
637 + * Linux epoll based Selector implementation
638 + */
640 +class EPollSelectorImpl extends SelectorImpl {
642 + // maximum number of events to poll in one call to epoll_wait
643 + private static final int NUM_EPOLLEVENTS = Math.min(IOUtil.fdLimit(), 1024);
645 + // epoll file descriptor
646 + private final int epfd;
648 + // address of poll array when polling with epoll_wait
649 + private final long pollArrayAddress;
651 + // eventfd object used for interrupt
652 + private final EventFD eventfd;
654 + // maps file descriptor to selection key, synchronize on selector
655 + private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
657 + // pending new registrations/updates, queued by setEventOps
658 + private final Object updateLock = new Object();
659 + private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
661 + // interrupt triggering and clearing
662 + private final Object interruptLock = new Object();
663 + private boolean interruptTriggered;
665 + EPollSelectorImpl(SelectorProvider sp) throws IOException {
666 + super(sp);
668 + this.epfd = EPoll.create();
669 + this.pollArrayAddress = EPoll.allocatePollArray(NUM_EPOLLEVENTS);
671 + try {
672 + this.eventfd = new EventFD();
673 + IOUtil.configureBlocking(IOUtil.newFD(eventfd.efd()), false);
674 + } catch (IOException ioe) {
675 + EPoll.freePollArray(pollArrayAddress);
676 + FileDispatcherImpl.closeIntFD(epfd);
677 + throw ioe;
680 + // register the eventfd object for wakeups
681 + EPoll.ctl(epfd, EPOLL_CTL_ADD, eventfd.efd(), EPOLLIN);
684 + private void ensureOpen() {
685 + if (!isOpen())
686 + throw new ClosedSelectorException();
689 + @Override
690 + protected int doSelect(Consumer<SelectionKey> action, long timeout)
691 + throws IOException
693 + assert Thread.holdsLock(this);
695 + // epoll_wait timeout is int
696 + int to = (int) Math.min(timeout, Integer.MAX_VALUE);
697 + boolean blocking = (to != 0);
698 + boolean timedPoll = (to > 0);
700 + int numEntries;
701 + processUpdateQueue();
702 + processDeregisterQueue();
703 + try {
704 + begin(blocking);
706 + do {
707 + long startTime = timedPoll ? System.nanoTime() : 0;
708 + boolean attempted = Blocker.begin(blocking);
709 + try {
710 + numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, to);
711 + } finally {
712 + Blocker.end(attempted);
714 + if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
715 + // timed poll interrupted so need to adjust timeout
716 + long adjust = System.nanoTime() - startTime;
717 + to -= (int) TimeUnit.NANOSECONDS.toMillis(adjust);
718 + if (to <= 0) {
719 + // timeout expired so no retry
720 + numEntries = 0;
723 + } while (numEntries == IOStatus.INTERRUPTED);
724 + assert IOStatus.check(numEntries);
726 + } finally {
727 + end(blocking);
729 + processDeregisterQueue();
730 + return processEvents(numEntries, action);
733 + /**
734 + * Process changes to the interest ops.
735 + */
736 + private void processUpdateQueue() {
737 + assert Thread.holdsLock(this);
739 + synchronized (updateLock) {
740 + SelectionKeyImpl ski;
741 + while ((ski = updateKeys.pollFirst()) != null) {
742 + if (ski.isValid()) {
743 + int fd = ski.getFDVal();
744 + // add to fdToKey if needed
745 + SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
746 + assert (previous == null) || (previous == ski);
748 + int newEvents = ski.translateInterestOps();
749 + int registeredEvents = ski.registeredEvents();
750 + if (newEvents != registeredEvents) {
751 + if (newEvents == 0) {
752 + // remove from epoll
753 + EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
754 + } else {
755 + if (registeredEvents == 0) {
756 + // add to epoll
757 + EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, newEvents);
758 + } else {
759 + // modify events
760 + EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, newEvents);
763 + ski.registeredEvents(newEvents);
770 + /**
771 + * Process the polled events.
772 + * If the interrupt fd has been selected, drain it and clear the interrupt.
773 + */
774 + private int processEvents(int numEntries, Consumer<SelectionKey> action)
775 + throws IOException
777 + assert Thread.holdsLock(this);
779 + boolean interrupted = false;
780 + int numKeysUpdated = 0;
781 + for (int i=0; i<numEntries; i++) {
782 + long event = EPoll.getEvent(pollArrayAddress, i);
783 + int fd = EPoll.getDescriptor(event);
784 + if (fd == eventfd.efd()) {
785 + interrupted = true;
786 + } else {
787 + SelectionKeyImpl ski = fdToKey.get(fd);
788 + if (ski != null) {
789 + int rOps = EPoll.getEvents(event);
790 + numKeysUpdated += processReadyEvents(rOps, ski, action);
795 + if (interrupted) {
796 + clearInterrupt();
799 + return numKeysUpdated;
802 + @Override
803 + protected void implClose() throws IOException {
804 + assert Thread.holdsLock(this);
806 + // prevent further wakeup
807 + synchronized (interruptLock) {
808 + interruptTriggered = true;
811 + FileDispatcherImpl.closeIntFD(epfd);
812 + EPoll.freePollArray(pollArrayAddress);
814 + eventfd.close();
817 + @Override
818 + protected void implDereg(SelectionKeyImpl ski) throws IOException {
819 + assert !ski.isValid();
820 + assert Thread.holdsLock(this);
822 + int fd = ski.getFDVal();
823 + if (fdToKey.remove(fd) != null) {
824 + if (ski.registeredEvents() != 0) {
825 + EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
826 + ski.registeredEvents(0);
828 + } else {
829 + assert ski.registeredEvents() == 0;
833 + @Override
834 + public void setEventOps(SelectionKeyImpl ski) {
835 + ensureOpen();
836 + synchronized (updateLock) {
837 + updateKeys.addLast(ski);
841 + @Override
842 + public Selector wakeup() {
843 + synchronized (interruptLock) {
844 + if (!interruptTriggered) {
845 + try {
846 + eventfd.set();
847 + } catch (IOException ioe) {
848 + throw new InternalError(ioe);
850 + interruptTriggered = true;
853 + return this;
856 + private void clearInterrupt() throws IOException {
857 + synchronized (interruptLock) {
858 + eventfd.reset();
859 + interruptTriggered = false;
863 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorProvider.java jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorProvider.java
864 --- jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorProvider.java 1970-01-01 01:00:00.000000000 +0100
865 +++ jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EPollSelectorProvider.java 2023-11-09 09:45:51.976886100 +0000
866 @@ -0,0 +1,42 @@
868 + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
869 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
871 + * This code is free software; you can redistribute it and/or modify it
872 + * under the terms of the GNU General Public License version 2 only, as
873 + * published by the Free Software Foundation. Oracle designates this
874 + * particular file as subject to the "Classpath" exception as provided
875 + * by Oracle in the LICENSE file that accompanied this code.
877 + * This code is distributed in the hope that it will be useful, but WITHOUT
878 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
879 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
880 + * version 2 for more details (a copy is included in the LICENSE file that
881 + * accompanied this code).
883 + * You should have received a copy of the GNU General Public License version
884 + * 2 along with this work; if not, write to the Free Software Foundation,
885 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
887 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
888 + * or visit www.oracle.com if you need additional information or have any
889 + * questions.
890 + */
892 +package sun.nio.ch;
894 +import java.io.IOException;
895 +import java.nio.channels.*;
896 +import java.nio.channels.spi.*;
898 +public class EPollSelectorProvider
899 + extends SelectorProviderImpl
901 + public AbstractSelector openSelector() throws IOException {
902 + return new EPollSelectorImpl(this);
905 + public Channel inheritedChannel() throws IOException {
906 + return InheritedChannel.getChannel();
909 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EventFD.java jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EventFD.java
910 --- jdk-jdk-22-22/src/java.base/solaris/classes/sun/nio/ch/EventFD.java 1970-01-01 01:00:00.000000000 +0100
911 +++ jdk-jdk-22-23/src/java.base/solaris/classes/sun/nio/ch/EventFD.java 2023-11-09 09:51:38.680862380 +0000
912 @@ -0,0 +1,73 @@
914 + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
915 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
917 + * This code is free software; you can redistribute it and/or modify it
918 + * under the terms of the GNU General Public License version 2 only, as
919 + * published by the Free Software Foundation. Oracle designates this
920 + * particular file as subject to the "Classpath" exception as provided
921 + * by Oracle in the LICENSE file that accompanied this code.
923 + * This code is distributed in the hope that it will be useful, but WITHOUT
924 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
925 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
926 + * version 2 for more details (a copy is included in the LICENSE file that
927 + * accompanied this code).
929 + * You should have received a copy of the GNU General Public License version
930 + * 2 along with this work; if not, write to the Free Software Foundation,
931 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
933 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
934 + * or visit www.oracle.com if you need additional information or have any
935 + * questions.
936 + */
938 +package sun.nio.ch;
940 +import java.io.IOException;
943 + * Provides access to the Linux eventfd object.
944 + */
945 +final class EventFD {
946 + private final int efd;
948 + /**
949 + * Creates a blocking eventfd object with initial value zero.
950 + */
951 + EventFD() throws IOException {
952 + efd = eventfd0();
955 + int efd() {
956 + return efd;
959 + void set() throws IOException {
960 + set0(efd);
963 + void reset() throws IOException {
964 + IOUtil.drain(efd);
967 + void close() throws IOException {
968 + FileDispatcherImpl.closeIntFD(efd);
971 + private static native int eventfd0() throws IOException;
973 + /**
974 + * Writes the value 1 to the eventfd object as a long in the
975 + * native byte order of the platform.
977 + * @param the integral eventfd file descriptor
978 + * @return the number of bytes written; should equal 8
979 + */
980 + private static native int set0(int efd) throws IOException;
982 + static {
983 + IOUtil.load();
986 diff --new-file -ur jdk-jdk-22-22/src/java.base/solaris/native/libnio/ch/EPoll.c jdk-jdk-22-23/src/java.base/solaris/native/libnio/ch/EPoll.c
987 --- jdk-jdk-22-22/src/java.base/solaris/native/libnio/ch/EPoll.c 1970-01-01 01:00:00.000000000 +0100
988 +++ jdk-jdk-22-23/src/java.base/solaris/native/libnio/ch/EPoll.c 2023-11-09 09:46:09.429493149 +0000
989 @@ -0,0 +1,96 @@
991 + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
992 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
994 + * This code is free software; you can redistribute it and/or modify it
995 + * under the terms of the GNU General Public License version 2 only, as
996 + * published by the Free Software Foundation. Oracle designates this
997 + * particular file as subject to the "Classpath" exception as provided
998 + * by Oracle in the LICENSE file that accompanied this code.
1000 + * This code is distributed in the hope that it will be useful, but WITHOUT
1001 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1002 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1003 + * version 2 for more details (a copy is included in the LICENSE file that
1004 + * accompanied this code).
1006 + * You should have received a copy of the GNU General Public License version
1007 + * 2 along with this work; if not, write to the Free Software Foundation,
1008 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1010 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1011 + * or visit www.oracle.com if you need additional information or have any
1012 + * questions.
1013 + */
1015 + #include <dlfcn.h>
1016 + #include <unistd.h>
1017 + #include <sys/types.h>
1018 + #include <sys/epoll.h>
1020 +#include "jni.h"
1021 +#include "jni_util.h"
1022 +#include "jvm.h"
1023 +#include "jlong.h"
1024 +#include "nio.h"
1025 +#include "nio_util.h"
1027 +#include "sun_nio_ch_EPoll.h"
1029 +JNIEXPORT jint JNICALL
1030 +Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass clazz)
1032 + return sizeof(struct epoll_event);
1035 +JNIEXPORT jint JNICALL
1036 +Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass clazz)
1038 + return offsetof(struct epoll_event, events);
1041 +JNIEXPORT jint JNICALL
1042 +Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass clazz)
1044 + return offsetof(struct epoll_event, data);
1047 +JNIEXPORT jint JNICALL
1048 +Java_sun_nio_ch_EPoll_create(JNIEnv *env, jclass clazz) {
1049 + int epfd = epoll_create1(EPOLL_CLOEXEC);
1050 + if (epfd < 0) {
1051 + JNU_ThrowIOExceptionWithLastError(env, "epoll_create1 failed");
1053 + return epfd;
1056 +JNIEXPORT jint JNICALL
1057 +Java_sun_nio_ch_EPoll_ctl(JNIEnv *env, jclass clazz, jint epfd,
1058 + jint opcode, jint fd, jint events)
1060 + struct epoll_event event;
1061 + int res;
1063 + event.events = events;
1064 + event.data.fd = fd;
1066 + res = epoll_ctl(epfd, (int)opcode, (int)fd, &event);
1067 + return (res == 0) ? 0 : errno;
1070 +JNIEXPORT jint JNICALL
1071 +Java_sun_nio_ch_EPoll_wait(JNIEnv *env, jclass clazz, jint epfd,
1072 + jlong address, jint numfds, jint timeout)
1074 + struct epoll_event *events = jlong_to_ptr(address);
1075 + int res = epoll_wait(epfd, events, numfds, timeout);
1076 + if (res < 0) {
1077 + if (errno == EINTR) {
1078 + return IOS_INTERRUPTED;
1079 + } else {
1080 + JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
1081 + return IOS_THROWN;
1084 + return res;
1086 --- /dev/null
1087 +++ a/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPortPoller.java
1088 @@ -0,0 +1,105 @@
1090 +* Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
1091 +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1093 +* This code is free software; you can redistribute it and/or modify it
1094 +* under the terms of the GNU General Public License version 2 only, as
1095 +* published by the Free Software Foundation. Oracle designates this
1096 +* particular file as subject to the "Classpath" exception as provided
1097 +* by Oracle in the LICENSE file that accompanied this code.
1099 +* This code is distributed in the hope that it will be useful, but WITHOUT
1100 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1101 +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1102 +* version 2 for more details (a copy is included in the LICENSE file that
1103 +* accompanied this code).
1105 +* You should have received a copy of the GNU General Public License version
1106 +* 2 along with this work; if not, write to the Free Software Foundation,
1107 +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1109 +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1110 +* or visit www.oracle.com if you need additional information or have any
1111 +* questions.
1114 +package sun.nio.ch;
1116 +import java.io.IOException;
1117 +import jdk.internal.misc.Unsafe;
1119 +import static sun.nio.ch.SolarisEventPort.OFFSETOF_OBJECT;
1120 +import static sun.nio.ch.SolarisEventPort.POLLIN;
1121 +import static sun.nio.ch.SolarisEventPort.POLLOUT;
1122 +import static sun.nio.ch.SolarisEventPort.PORT_SOURCE_FD;
1123 +import static sun.nio.ch.SolarisEventPort.SIZEOF_PORT_EVENT;
1125 +class SolarisEventPortPoller extends Poller {
1127 + private static final Unsafe unsafe = Unsafe.getUnsafe();
1129 + private static final int MAX_EVENTS = 512;
1131 + // File descriptor to event port.
1132 + private final int epid;
1133 + private final int event;
1135 + // the poll array (populated by port_getn)
1136 + private final long pollArrayAddress;
1137 + private final AllocatedNativeObject pollArray;
1139 + SolarisEventPortPoller(boolean subPoller, boolean read) throws IOException {
1140 + this.epid = SolarisEventPort.port_create();
1141 + this.event = (read) ? POLLIN : POLLOUT;
1143 + int allocationSize = MAX_EVENTS * SIZEOF_PORT_EVENT;
1144 + this.pollArray = new AllocatedNativeObject(allocationSize, false);
1145 + this.pollArrayAddress = pollArray.address();
1148 + @Override
1149 + int fdVal() {
1150 + return epid;
1153 + @Override
1154 + void implRegister(int fdVal) throws IOException {
1155 + boolean result = SolarisEventPort.port_associate(epid, PORT_SOURCE_FD, fdVal, event);
1156 + // 'SolarisEventPort.c' will already throw an IOException if the native 'port_associate' method returns
1157 + // an error code which is not 'EBADFD'.
1158 + if (!result) {
1159 + throw new IOException("Event ports 'port_associate' call failed. Error code: " + result);
1163 + @Override
1164 + void implDeregister(int fdVal, boolean polled) {
1165 + // event is disabled if already polled
1166 + if (!polled) {
1167 + try{
1168 + SolarisEventPort.port_dissociate(epid, PORT_SOURCE_FD, fdVal);
1169 + } catch (IOException e) {
1170 + // Ignore.
1175 + @Override
1176 + int poll(int timeout) throws IOException {
1177 + int numEvents = SolarisEventPort.port_getn(epid, pollArrayAddress, MAX_EVENTS, timeout);
1178 + if (numEvents < 0) {
1179 + throw new IOException("Event ports 'port_getn' call failed. Error code: " + numEvents);
1182 + int i = 0;
1183 + while (i < numEvents) {
1184 + long eventAddress = pollArrayAddress + (SIZEOF_PORT_EVENT * i);
1185 + // pe->portev_object is file descriptor
1186 + int fdVal = (int)unsafe.getAddress(eventAddress + OFFSETOF_OBJECT);
1187 + polled(fdVal);
1188 + i++;
1191 + return numEvents;