Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
32288 views
1
/*
2
* Copyright (c) 2001, 2013, 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
import java.security.AccessController;
30
import java.util.BitSet;
31
import java.util.Map;
32
import java.util.HashMap;
33
import sun.security.action.GetIntegerAction;
34
35
36
/**
37
* Manipulates a native array of pollfd structs on Solaris:
38
*
39
* typedef struct pollfd {
40
* int fd;
41
* short events;
42
* short revents;
43
* } pollfd_t;
44
*
45
* @author Mike McCloskey
46
* @since 1.4
47
*/
48
49
class DevPollArrayWrapper {
50
51
// Event masks
52
static final short POLLIN = 0x0001;
53
static final short POLLPRI = 0x0002;
54
static final short POLLOUT = 0x0004;
55
static final short POLLRDNORM = 0x0040;
56
static final short POLLWRNORM = POLLOUT;
57
static final short POLLRDBAND = 0x0080;
58
static final short POLLWRBAND = 0x0100;
59
static final short POLLNORM = POLLRDNORM;
60
static final short POLLERR = 0x0008;
61
static final short POLLHUP = 0x0010;
62
static final short POLLNVAL = 0x0020;
63
static final short POLLREMOVE = 0x0800;
64
static final short POLLCONN = POLLOUT;
65
66
// Miscellaneous constants
67
static final short SIZE_POLLFD = 8;
68
static final short FD_OFFSET = 0;
69
static final short EVENT_OFFSET = 4;
70
static final short REVENT_OFFSET = 6;
71
72
// Special value to indicate that an update should be ignored
73
static final byte IGNORE = (byte)-1;
74
75
// Maximum number of open file descriptors
76
static final int OPEN_MAX = IOUtil.fdLimit();
77
78
// Number of pollfd structures to create.
79
// dpwrite/ioctl(DP_POLL) allows up to OPEN_MAX-1
80
static final int NUM_POLLFDS = Math.min(OPEN_MAX-1, 8192);
81
82
// Initial size of arrays for fd registration changes
83
private static final int INITIAL_PENDING_UPDATE_SIZE = 64;
84
85
// maximum size of updatesLow
86
private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged(
87
new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024)));
88
89
// The pollfd array for results from devpoll driver
90
private final AllocatedNativeObject pollArray;
91
92
// Base address of the native pollArray
93
private final long pollArrayAddress;
94
95
// The fd of the devpoll driver
96
private int wfd;
97
98
// The fd of the interrupt line going out
99
private int outgoingInterruptFD;
100
101
// The fd of the interrupt line coming in
102
private int incomingInterruptFD;
103
104
// The index of the interrupt FD
105
private int interruptedIndex;
106
107
// Number of updated pollfd entries
108
int updated;
109
110
// object to synchronize fd registration changes
111
private final Object updateLock = new Object();
112
113
// number of file descriptors with registration changes pending
114
private int updateCount;
115
116
// file descriptors with registration changes pending
117
private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
118
119
// events for file descriptors with registration changes pending, indexed
120
// by file descriptor and stored as bytes for efficiency reasons. For
121
// file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
122
// least then the update is stored in a map.
123
private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
124
private Map<Integer,Byte> eventsHigh;
125
126
// Used by release and updateRegistrations to track whether a file
127
// descriptor is registered with /dev/poll.
128
private final BitSet registered = new BitSet();
129
130
DevPollArrayWrapper() {
131
int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
132
pollArray = new AllocatedNativeObject(allocationSize, true);
133
pollArrayAddress = pollArray.address();
134
wfd = init();
135
if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE)
136
eventsHigh = new HashMap<>();
137
}
138
139
void initInterrupt(int fd0, int fd1) {
140
outgoingInterruptFD = fd1;
141
incomingInterruptFD = fd0;
142
register(wfd, fd0, POLLIN);
143
}
144
145
void putReventOps(int i, int revent) {
146
int offset = SIZE_POLLFD * i + REVENT_OFFSET;
147
pollArray.putShort(offset, (short)revent);
148
}
149
150
int getEventOps(int i) {
151
int offset = SIZE_POLLFD * i + EVENT_OFFSET;
152
return pollArray.getShort(offset);
153
}
154
155
int getReventOps(int i) {
156
int offset = SIZE_POLLFD * i + REVENT_OFFSET;
157
return pollArray.getShort(offset);
158
}
159
160
int getDescriptor(int i) {
161
int offset = SIZE_POLLFD * i + FD_OFFSET;
162
return pollArray.getInt(offset);
163
}
164
165
private void setUpdateEvents(int fd, byte events) {
166
if (fd < MAX_UPDATE_ARRAY_SIZE) {
167
eventsLow[fd] = events;
168
} else {
169
eventsHigh.put(Integer.valueOf(fd), Byte.valueOf(events));
170
}
171
}
172
173
private byte getUpdateEvents(int fd) {
174
if (fd < MAX_UPDATE_ARRAY_SIZE) {
175
return eventsLow[fd];
176
} else {
177
Byte result = eventsHigh.get(Integer.valueOf(fd));
178
// result should never be null
179
return result.byteValue();
180
}
181
}
182
183
void setInterest(int fd, int mask) {
184
synchronized (updateLock) {
185
// record the file descriptor and events, expanding the
186
// respective arrays first if necessary.
187
int oldCapacity = updateDescriptors.length;
188
if (updateCount == oldCapacity) {
189
int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
190
int[] newDescriptors = new int[newCapacity];
191
System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
192
updateDescriptors = newDescriptors;
193
}
194
updateDescriptors[updateCount++] = fd;
195
196
// events are stored as bytes for efficiency reasons
197
byte b = (byte)mask;
198
assert (b == mask) && (b != IGNORE);
199
setUpdateEvents(fd, b);
200
}
201
}
202
203
void release(int fd) {
204
synchronized (updateLock) {
205
// ignore any pending update for this file descriptor
206
setUpdateEvents(fd, IGNORE);
207
208
// remove from /dev/poll
209
if (registered.get(fd)) {
210
register(wfd, fd, POLLREMOVE);
211
registered.clear(fd);
212
}
213
}
214
}
215
216
void closeDevPollFD() throws IOException {
217
FileDispatcherImpl.closeIntFD(wfd);
218
pollArray.free();
219
}
220
221
int poll(long timeout) throws IOException {
222
updateRegistrations();
223
updated = poll0(pollArrayAddress, NUM_POLLFDS, timeout, wfd);
224
for (int i=0; i<updated; i++) {
225
if (getDescriptor(i) == incomingInterruptFD) {
226
interruptedIndex = i;
227
interrupted = true;
228
break;
229
}
230
}
231
return updated;
232
}
233
234
void updateRegistrations() throws IOException {
235
synchronized (updateLock) {
236
// Populate pollfd array with updated masks
237
int j = 0;
238
int index = 0;
239
while (j < updateCount) {
240
int fd = updateDescriptors[j];
241
short events = getUpdateEvents(fd);
242
boolean wasRegistered = registered.get(fd);
243
244
// events = 0 => POLLREMOVE or do-nothing
245
if (events != IGNORE) {
246
if (events == 0) {
247
if (wasRegistered) {
248
events = POLLREMOVE;
249
registered.clear(fd);
250
} else {
251
events = IGNORE;
252
}
253
} else {
254
if (!wasRegistered) {
255
registered.set(fd);
256
}
257
}
258
}
259
260
// populate pollfd array with updated event
261
if (events != IGNORE) {
262
// insert POLLREMOVE if changing events
263
if (wasRegistered && events != POLLREMOVE) {
264
putPollFD(pollArray, index, fd, POLLREMOVE);
265
index++;
266
}
267
putPollFD(pollArray, index, fd, events);
268
index++;
269
if (index >= (NUM_POLLFDS-1)) {
270
registerMultiple(wfd, pollArray.address(), index);
271
index = 0;
272
}
273
274
// events for this fd now up to date
275
setUpdateEvents(fd, IGNORE);
276
}
277
j++;
278
}
279
280
// write any remaining updates
281
if (index > 0)
282
registerMultiple(wfd, pollArray.address(), index);
283
284
updateCount = 0;
285
}
286
}
287
288
private void putPollFD(AllocatedNativeObject array, int index, int fd,
289
short event)
290
{
291
int structIndex = SIZE_POLLFD * index;
292
array.putInt(structIndex + FD_OFFSET, fd);
293
array.putShort(structIndex + EVENT_OFFSET, event);
294
array.putShort(structIndex + REVENT_OFFSET, (short)0);
295
}
296
297
boolean interrupted = false;
298
299
public void interrupt() {
300
interrupt(outgoingInterruptFD);
301
}
302
303
public int interruptedIndex() {
304
return interruptedIndex;
305
}
306
307
boolean interrupted() {
308
return interrupted;
309
}
310
311
void clearInterrupted() {
312
interrupted = false;
313
}
314
315
private native int init();
316
private native void register(int wfd, int fd, int mask);
317
private native void registerMultiple(int wfd, long address, int len)
318
throws IOException;
319
private native int poll0(long pollAddress, int numfds, long timeout,
320
int wfd);
321
private static native void interrupt(int fd);
322
323
static {
324
IOUtil.load();
325
}
326
}
327
328