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/EventPortWrapper.java
32288 views
1
/*
2
* Copyright (c) 2012, 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.HashMap;
32
import java.util.Map;
33
34
import sun.misc.Unsafe;
35
import sun.security.action.GetIntegerAction;
36
import static sun.nio.ch.SolarisEventPort.*;
37
38
/**
39
* Manages a Solaris event port and manipulates a native array of pollfd structs
40
* on Solaris.
41
*/
42
43
class EventPortWrapper {
44
private static final Unsafe unsafe = Unsafe.getUnsafe();
45
private static final int addressSize = unsafe.addressSize();
46
47
// Maximum number of open file descriptors
48
static final int OPEN_MAX = IOUtil.fdLimit();
49
50
// Maximum number of events to retrive in one call to port_getn
51
static final int POLL_MAX = Math.min(OPEN_MAX-1, 1024);
52
53
// initial size of the array to hold pending updates
54
private final int INITIAL_PENDING_UPDATE_SIZE = 256;
55
56
// maximum size of updateArray
57
private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged(
58
new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024)));
59
60
// special update status to indicate that it should be ignored
61
private static final byte IGNORE = -1;
62
63
// port file descriptor
64
private final int pfd;
65
66
// the poll array (populated by port_getn)
67
private final long pollArrayAddress;
68
private final AllocatedNativeObject pollArray;
69
70
// required when accessing the update* fields
71
private final Object updateLock = new Object();
72
73
// the number of pending updates
74
private int updateCount;
75
76
// queue of file descriptors with updates pending
77
private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
78
79
// events for file descriptors with registration changes pending, indexed
80
// by file descriptor and stored as bytes for efficiency reasons. For
81
// file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
82
// least then the update is stored in a map.
83
private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
84
private Map<Integer,Byte> eventsHigh;
85
// Used by release and updateRegistrations to track whether a file
86
// descriptor is registered with /dev/poll.
87
private final BitSet registered = new BitSet();
88
89
// bit set to indicate if a file descriptor has been visited when
90
// processing updates (used to avoid duplicates calls to port_associate)
91
private BitSet visited = new BitSet();
92
93
EventPortWrapper() throws IOException {
94
int allocationSize = POLL_MAX * SIZEOF_PORT_EVENT;
95
pollArray = new AllocatedNativeObject(allocationSize, true);
96
pollArrayAddress = pollArray.address();
97
this.pfd = port_create();
98
if (OPEN_MAX > MAX_UPDATE_ARRAY_SIZE)
99
eventsHigh = new HashMap<>();
100
}
101
102
void close() throws IOException {
103
port_close(pfd);
104
pollArray.free();
105
}
106
107
private short getSource(int i) {
108
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_SOURCE;
109
return pollArray.getShort(offset);
110
}
111
112
int getEventOps(int i) {
113
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_EVENTS;
114
return pollArray.getInt(offset);
115
}
116
117
int getDescriptor(int i) {
118
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT;
119
if (addressSize == 4) {
120
return pollArray.getInt(offset);
121
} else {
122
return (int) pollArray.getLong(offset);
123
}
124
}
125
126
private void setDescriptor(int i, int fd) {
127
int offset = SIZEOF_PORT_EVENT * i + OFFSETOF_OBJECT;
128
if (addressSize == 4) {
129
pollArray.putInt(offset, fd);
130
} else {
131
pollArray.putLong(offset, fd);
132
}
133
}
134
135
private void setUpdate(int fd, byte events) {
136
if (fd < MAX_UPDATE_ARRAY_SIZE) {
137
eventsLow[fd] = events;
138
} else {
139
eventsHigh.put(Integer.valueOf(fd), Byte.valueOf(events));
140
}
141
}
142
143
private byte getUpdate(int fd) {
144
if (fd < MAX_UPDATE_ARRAY_SIZE) {
145
return eventsLow[fd];
146
} else {
147
Byte result = eventsHigh.get(Integer.valueOf(fd));
148
// result should never be null
149
return result.byteValue();
150
}
151
}
152
153
int poll(long timeout) throws IOException {
154
// update registrations prior to poll
155
synchronized (updateLock) {
156
157
// process newest updates first
158
int i = updateCount - 1;
159
while (i >= 0) {
160
int fd = updateDescriptors[i];
161
if (!visited.get(fd)) {
162
short ev = getUpdate(fd);
163
if (ev != IGNORE) {
164
if (ev == 0) {
165
if (registered.get(fd)) {
166
port_dissociate(pfd, PORT_SOURCE_FD, (long)fd);
167
registered.clear(fd);
168
}
169
} else {
170
if (port_associate(pfd, PORT_SOURCE_FD, (long)fd, ev)) {
171
registered.set(fd);
172
}
173
}
174
175
}
176
visited.set(fd);
177
}
178
i--;
179
}
180
updateCount = 0;
181
}
182
183
// poll for events
184
int updated = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
185
186
// after polling we need to queue all polled file descriptors as they
187
// are candidates to register for the next poll.
188
synchronized (updateLock) {
189
for (int i=0; i<updated; i++) {
190
if (getSource(i) == PORT_SOURCE_USER) {
191
interrupted = true;
192
setDescriptor(i, -1);
193
} else {
194
// the default is to re-associate for the next poll
195
int fd = getDescriptor(i);
196
registered.clear(fd);
197
setInterest(fd);
198
}
199
}
200
}
201
202
return updated;
203
}
204
205
private void setInterest(int fd) {
206
assert Thread.holdsLock(updateLock);
207
208
// record the file descriptor and events, expanding the
209
// respective arrays first if necessary.
210
int oldCapacity = updateDescriptors.length;
211
if (updateCount >= oldCapacity) {
212
int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
213
int[] newDescriptors = new int[newCapacity];
214
System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
215
updateDescriptors = newDescriptors;
216
}
217
updateDescriptors[updateCount++] = fd;
218
visited.clear(fd);
219
}
220
221
void setInterest(int fd, int mask) {
222
synchronized (updateLock) {
223
setInterest(fd);
224
setUpdate(fd, (byte)mask);
225
assert getUpdate(fd) == mask;
226
}
227
}
228
229
void release(int fd) {
230
synchronized (updateLock) {
231
if (registered.get(fd)) {
232
try {
233
port_dissociate(pfd, PORT_SOURCE_FD, (long)fd);
234
} catch (IOException ioe) {
235
throw new InternalError(ioe);
236
}
237
registered.clear(fd);
238
}
239
setUpdate(fd, IGNORE);
240
}
241
}
242
243
// -- wakeup support --
244
245
private boolean interrupted;
246
247
public void interrupt() {
248
try {
249
port_send(pfd, 0);
250
} catch (IOException ioe) {
251
throw new InternalError(ioe);
252
}
253
}
254
255
boolean interrupted() {
256
return interrupted;
257
}
258
259
void clearInterrupted() {
260
interrupted = false;
261
}
262
}
263
264