1 /*
2 * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2023, IBM Corp.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26 package sun.nio.ch;
27
28 import java.io.IOException;
29 import java.time.Instant;
30 import sun.nio.ch.Pollset;
31
32 /**
33 * Poller implementation based on the AIX Pollset library.
34 */
35
36 class PollsetPoller extends Poller {
37
38 private static final int MAX_EVENTS_TO_POLL;
39
40 static {
41 Pollset.init(); /* Dynamically loads pollset C functions */
42 MAX_EVENTS_TO_POLL = 512;
43 }
44
45 private final int event;
46 private final int setid;
47 private final long pollBuffer;
48
49 PollsetPoller(boolean read) throws IOException {
50 this.event = (read) ? Net.POLLIN : Net.POLLOUT;
51 this.setid = Pollset.pollsetCreate();
52 this.pollBuffer = Pollset.allocatePollArray(MAX_EVENTS_TO_POLL);
53 }
54
55 @Override
56 int fdVal() {
57 return setid;
58 }
59
60 @Override
61 void implRegister(int fd) throws IOException {
62 int ret = Pollset.pollsetCtl(setid, Pollset.PS_MOD, fd, Pollset.PS_POLLPRI | event);
63 if (ret != 0) {
64 throw new IOException("Unable to register fd " + fd);
65 }
66 }
67
68 @Override
69 void implDeregister(int fd, boolean polled) {
70 int ret = Pollset.pollsetCtl(setid, Pollset.PS_DELETE, fd, 0);
71 assert ret == 0;
72 }
73
74 /**
75 * Main poll method. The AIX Pollset library does not appear to pick up changes to the pollset
76 * (the set of fds being polled) while blocked on a call to this method. These changes happen
77 * regularly in the poll-loop thread and update thread from Poller.java.
78 * To address this difficulty, we break poll calls into 100ms sub-calls and emulate the timout.
79 */
80 @Override
81 int poll(int timeout) throws IOException {
82 int n;
83 switch (timeout) {
84 case 0:
85 n = pollInner(0);
86 break;
87 case Pollset.PS_NO_TIMEOUT:
88 do { n = pollInner(100); } while (n == 0);
89 break;
90 default:
91 Instant end = Instant.now().plusMillis(timeout);
92 do { n = pollInner(100); } while (n == 0 && Instant.now().isBefore(end));
93 break;
94 }
95 return n;
96 }
97
98 int pollInner(int subInterval) throws IOException {
99 int n = Pollset.pollsetPoll(setid, pollBuffer, MAX_EVENTS_TO_POLL, subInterval);
100 for (int i=0; i<n; i++) {
101 long eventAddress = Pollset.getEvent(pollBuffer, i);
102 int fd = Pollset.getDescriptor(eventAddress);
103 polled(fd);
104 }
105 return n;
106 }
107 }
108