Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/nio/ch/IOUtil.java
41159 views
1
/*
2
* Copyright (c) 2000, 2021, 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.FileDescriptor;
29
import java.io.IOException;
30
import java.nio.ByteBuffer;
31
import java.util.Objects;
32
import jdk.internal.access.JavaNioAccess;
33
import jdk.internal.access.SharedSecrets;
34
import jdk.internal.misc.ScopedMemoryAccess.Scope;
35
36
/**
37
* File-descriptor based I/O utilities that are shared by NIO classes.
38
*/
39
40
public class IOUtil {
41
42
/**
43
* Max number of iovec structures that readv/writev supports
44
*/
45
static final int IOV_MAX;
46
47
private IOUtil() { } // No instantiation
48
49
static int write(FileDescriptor fd, ByteBuffer src, long position,
50
NativeDispatcher nd)
51
throws IOException
52
{
53
return write(fd, src, position, false, false, -1, nd);
54
}
55
56
static int write(FileDescriptor fd, ByteBuffer src, long position,
57
boolean async, NativeDispatcher nd)
58
throws IOException
59
{
60
return write(fd, src, position, false, async, -1, nd);
61
}
62
63
static int write(FileDescriptor fd, ByteBuffer src, long position,
64
boolean directIO, int alignment, NativeDispatcher nd)
65
throws IOException
66
{
67
return write(fd, src, position, directIO, false, alignment, nd);
68
}
69
70
static int write(FileDescriptor fd, ByteBuffer src, long position,
71
boolean directIO, boolean async, int alignment,
72
NativeDispatcher nd)
73
throws IOException
74
{
75
if (src instanceof DirectBuffer) {
76
return writeFromNativeBuffer(fd, src, position, directIO, async, alignment, nd);
77
}
78
79
// Substitute a native buffer
80
int pos = src.position();
81
int lim = src.limit();
82
assert (pos <= lim);
83
int rem = (pos <= lim ? lim - pos : 0);
84
ByteBuffer bb;
85
if (directIO) {
86
Util.checkRemainingBufferSizeAligned(rem, alignment);
87
bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
88
} else {
89
bb = Util.getTemporaryDirectBuffer(rem);
90
}
91
try {
92
bb.put(src);
93
bb.flip();
94
// Do not update src until we see how many bytes were written
95
src.position(pos);
96
97
int n = writeFromNativeBuffer(fd, bb, position, directIO, async, alignment, nd);
98
if (n > 0) {
99
// now update src
100
src.position(pos + n);
101
}
102
return n;
103
} finally {
104
Util.offerFirstTemporaryDirectBuffer(bb);
105
}
106
}
107
108
private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
109
long position, boolean directIO,
110
boolean async, int alignment,
111
NativeDispatcher nd)
112
throws IOException
113
{
114
int pos = bb.position();
115
int lim = bb.limit();
116
assert (pos <= lim);
117
int rem = (pos <= lim ? lim - pos : 0);
118
119
if (directIO) {
120
Util.checkBufferPositionAligned(bb, pos, alignment);
121
Util.checkRemainingBufferSizeAligned(rem, alignment);
122
}
123
124
int written = 0;
125
if (rem == 0)
126
return 0;
127
var handle = acquireScope(bb, async);
128
try {
129
if (position != -1) {
130
written = nd.pwrite(fd, bufferAddress(bb) + pos, rem, position);
131
} else {
132
written = nd.write(fd, bufferAddress(bb) + pos, rem);
133
}
134
} finally {
135
releaseScope(handle);
136
}
137
if (written > 0)
138
bb.position(pos + written);
139
return written;
140
}
141
142
static long write(FileDescriptor fd, ByteBuffer[] bufs, boolean async,
143
NativeDispatcher nd)
144
throws IOException
145
{
146
return write(fd, bufs, 0, bufs.length, false, async, -1, nd);
147
}
148
149
static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
150
NativeDispatcher nd)
151
throws IOException
152
{
153
return write(fd, bufs, offset, length, false, false, -1, nd);
154
}
155
156
static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
157
boolean direct, int alignment, NativeDispatcher nd)
158
throws IOException
159
{
160
return write(fd, bufs, offset, length, direct, false, alignment, nd);
161
}
162
163
static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
164
boolean directIO, boolean async,
165
int alignment, NativeDispatcher nd)
166
throws IOException
167
{
168
IOVecWrapper vec = IOVecWrapper.get(length);
169
170
boolean completed = false;
171
int iov_len = 0;
172
Runnable handleReleasers = null;
173
try {
174
// Iterate over buffers to populate native iovec array.
175
int count = offset + length;
176
int i = offset;
177
while (i < count && iov_len < IOV_MAX) {
178
ByteBuffer buf = bufs[i];
179
var h = acquireScope(buf, async);
180
if (h != null) {
181
handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers);
182
}
183
int pos = buf.position();
184
int lim = buf.limit();
185
assert (pos <= lim);
186
int rem = (pos <= lim ? lim - pos : 0);
187
if (directIO)
188
Util.checkRemainingBufferSizeAligned(rem, alignment);
189
190
if (rem > 0) {
191
vec.setBuffer(iov_len, buf, pos, rem);
192
193
// allocate shadow buffer to ensure I/O is done with direct buffer
194
if (!(buf instanceof DirectBuffer)) {
195
ByteBuffer shadow;
196
if (directIO)
197
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
198
else
199
shadow = Util.getTemporaryDirectBuffer(rem);
200
shadow.put(buf);
201
shadow.flip();
202
vec.setShadow(iov_len, shadow);
203
buf.position(pos); // temporarily restore position in user buffer
204
buf = shadow;
205
pos = shadow.position();
206
}
207
208
vec.putBase(iov_len, bufferAddress(buf) + pos);
209
vec.putLen(iov_len, rem);
210
iov_len++;
211
}
212
i++;
213
}
214
if (iov_len == 0)
215
return 0L;
216
217
long bytesWritten = nd.writev(fd, vec.address, iov_len);
218
219
// Notify the buffers how many bytes were taken
220
long left = bytesWritten;
221
for (int j=0; j<iov_len; j++) {
222
if (left > 0) {
223
ByteBuffer buf = vec.getBuffer(j);
224
int pos = vec.getPosition(j);
225
int rem = vec.getRemaining(j);
226
int n = (left > rem) ? rem : (int)left;
227
buf.position(pos + n);
228
left -= n;
229
}
230
// return shadow buffers to buffer pool
231
ByteBuffer shadow = vec.getShadow(j);
232
if (shadow != null)
233
Util.offerLastTemporaryDirectBuffer(shadow);
234
vec.clearRefs(j);
235
}
236
237
completed = true;
238
return bytesWritten;
239
240
} finally {
241
releaseScopes(handleReleasers);
242
// if an error occurred then clear refs to buffers and return any shadow
243
// buffers to cache
244
if (!completed) {
245
for (int j=0; j<iov_len; j++) {
246
ByteBuffer shadow = vec.getShadow(j);
247
if (shadow != null)
248
Util.offerLastTemporaryDirectBuffer(shadow);
249
vec.clearRefs(j);
250
}
251
}
252
}
253
}
254
255
static int read(FileDescriptor fd, ByteBuffer dst, long position,
256
NativeDispatcher nd)
257
throws IOException
258
{
259
return read(fd, dst, position, false, false, -1, nd);
260
}
261
262
static int read(FileDescriptor fd, ByteBuffer dst, long position,
263
boolean async, NativeDispatcher nd)
264
throws IOException
265
{
266
return read(fd, dst, position, false, async, -1, nd);
267
}
268
269
static int read(FileDescriptor fd, ByteBuffer dst, long position,
270
boolean directIO, int alignment, NativeDispatcher nd)
271
throws IOException
272
{
273
return read(fd, dst, position, directIO, false, alignment, nd);
274
}
275
276
static int read(FileDescriptor fd, ByteBuffer dst, long position,
277
boolean directIO, boolean async,
278
int alignment, NativeDispatcher nd)
279
throws IOException
280
{
281
if (dst.isReadOnly())
282
throw new IllegalArgumentException("Read-only buffer");
283
if (dst instanceof DirectBuffer)
284
return readIntoNativeBuffer(fd, dst, position, directIO, async, alignment, nd);
285
286
// Substitute a native buffer
287
ByteBuffer bb;
288
int rem = dst.remaining();
289
if (directIO) {
290
Util.checkRemainingBufferSizeAligned(rem, alignment);
291
bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
292
} else {
293
bb = Util.getTemporaryDirectBuffer(rem);
294
}
295
try {
296
int n = readIntoNativeBuffer(fd, bb, position, directIO, async, alignment, nd);
297
bb.flip();
298
if (n > 0)
299
dst.put(bb);
300
return n;
301
} finally {
302
Util.offerFirstTemporaryDirectBuffer(bb);
303
}
304
}
305
306
private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
307
long position, boolean directIO,
308
boolean async, int alignment,
309
NativeDispatcher nd)
310
throws IOException
311
{
312
int pos = bb.position();
313
int lim = bb.limit();
314
assert (pos <= lim);
315
int rem = (pos <= lim ? lim - pos : 0);
316
317
if (directIO) {
318
Util.checkBufferPositionAligned(bb, pos, alignment);
319
Util.checkRemainingBufferSizeAligned(rem, alignment);
320
}
321
322
if (rem == 0)
323
return 0;
324
int n = 0;
325
var handle = acquireScope(bb, async);
326
try {
327
if (position != -1) {
328
n = nd.pread(fd, bufferAddress(bb) + pos, rem, position);
329
} else {
330
n = nd.read(fd, bufferAddress(bb) + pos, rem);
331
}
332
} finally {
333
releaseScope(handle);
334
}
335
if (n > 0)
336
bb.position(pos + n);
337
return n;
338
}
339
340
static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
341
throws IOException
342
{
343
return read(fd, bufs, 0, bufs.length, false, false, -1, nd);
344
}
345
346
static long read(FileDescriptor fd, ByteBuffer[] bufs, boolean async,
347
NativeDispatcher nd)
348
throws IOException
349
{
350
return read(fd, bufs, 0, bufs.length, false, async, -1, nd);
351
}
352
353
static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
354
NativeDispatcher nd)
355
throws IOException
356
{
357
return read(fd, bufs, offset, length, false, false, -1, nd);
358
}
359
360
static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
361
boolean directIO, int alignment, NativeDispatcher nd)
362
363
throws IOException
364
{
365
return read(fd, bufs, offset, length, directIO, false, alignment, nd);
366
}
367
368
static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
369
boolean directIO, boolean async,
370
int alignment, NativeDispatcher nd)
371
372
throws IOException
373
{
374
IOVecWrapper vec = IOVecWrapper.get(length);
375
376
boolean completed = false;
377
int iov_len = 0;
378
Runnable handleReleasers = null;
379
try {
380
// Iterate over buffers to populate native iovec array.
381
int count = offset + length;
382
int i = offset;
383
while (i < count && iov_len < IOV_MAX) {
384
ByteBuffer buf = bufs[i];
385
if (buf.isReadOnly())
386
throw new IllegalArgumentException("Read-only buffer");
387
var h = acquireScope(buf, async);
388
if (h != null) {
389
handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers);
390
}
391
int pos = buf.position();
392
int lim = buf.limit();
393
assert (pos <= lim);
394
int rem = (pos <= lim ? lim - pos : 0);
395
396
if (directIO)
397
Util.checkRemainingBufferSizeAligned(rem, alignment);
398
399
if (rem > 0) {
400
vec.setBuffer(iov_len, buf, pos, rem);
401
402
// allocate shadow buffer to ensure I/O is done with direct buffer
403
if (!(buf instanceof DirectBuffer)) {
404
ByteBuffer shadow;
405
if (directIO) {
406
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
407
} else {
408
shadow = Util.getTemporaryDirectBuffer(rem);
409
}
410
vec.setShadow(iov_len, shadow);
411
buf = shadow;
412
pos = shadow.position();
413
}
414
415
vec.putBase(iov_len, bufferAddress(buf) + pos);
416
vec.putLen(iov_len, rem);
417
iov_len++;
418
}
419
i++;
420
}
421
if (iov_len == 0)
422
return 0L;
423
424
long bytesRead = nd.readv(fd, vec.address, iov_len);
425
426
// Notify the buffers how many bytes were read
427
long left = bytesRead;
428
for (int j=0; j<iov_len; j++) {
429
ByteBuffer shadow = vec.getShadow(j);
430
if (left > 0) {
431
ByteBuffer buf = vec.getBuffer(j);
432
int rem = vec.getRemaining(j);
433
int n = (left > rem) ? rem : (int)left;
434
if (shadow == null) {
435
int pos = vec.getPosition(j);
436
buf.position(pos + n);
437
} else {
438
shadow.limit(shadow.position() + n);
439
buf.put(shadow);
440
}
441
left -= n;
442
}
443
if (shadow != null)
444
Util.offerLastTemporaryDirectBuffer(shadow);
445
vec.clearRefs(j);
446
}
447
448
completed = true;
449
return bytesRead;
450
451
} finally {
452
releaseScopes(handleReleasers);
453
// if an error occurred then clear refs to buffers and return any shadow
454
// buffers to cache
455
if (!completed) {
456
for (int j=0; j<iov_len; j++) {
457
ByteBuffer shadow = vec.getShadow(j);
458
if (shadow != null)
459
Util.offerLastTemporaryDirectBuffer(shadow);
460
vec.clearRefs(j);
461
}
462
}
463
}
464
}
465
466
private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess();
467
468
static Scope.Handle acquireScope(ByteBuffer bb, boolean async) {
469
return NIO_ACCESS.acquireScope(bb, async);
470
}
471
472
private static void releaseScope(Scope.Handle handle) {
473
if (handle == null)
474
return;
475
try {
476
handle.scope().release(handle);
477
} catch (Exception e) {
478
throw new IllegalStateException(e);
479
}
480
}
481
482
static Runnable acquireScopes(ByteBuffer[] buffers) {
483
return acquireScopes(null, buffers);
484
}
485
486
static Runnable acquireScopes(ByteBuffer buf, ByteBuffer[] buffers) {
487
if (buffers == null) {
488
assert buf != null;
489
return IOUtil.Releaser.ofNullable(IOUtil.acquireScope(buf, true));
490
} else {
491
assert buf == null;
492
Runnable handleReleasers = null;
493
for (var b : buffers) {
494
var h = IOUtil.acquireScope(b, true);
495
if (h != null) {
496
handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(h), handleReleasers);
497
}
498
}
499
return handleReleasers;
500
}
501
}
502
503
static void releaseScopes(Runnable releasers) {
504
if (releasers != null)
505
releasers.run();
506
}
507
508
static record LinkedRunnable(Runnable node, Runnable next)
509
implements Runnable
510
{
511
LinkedRunnable {
512
Objects.requireNonNull(node);
513
}
514
@Override
515
public void run() {
516
try {
517
node.run();
518
} finally {
519
if (next != null)
520
next.run();
521
}
522
}
523
static LinkedRunnable of(Runnable first, Runnable second) {
524
return new LinkedRunnable(first, second);
525
}
526
}
527
528
static record Releaser(Scope.Handle handle) implements Runnable {
529
Releaser { Objects.requireNonNull(handle) ; }
530
@Override public void run() { releaseScope(handle); }
531
static Runnable of(Scope.Handle handle) { return new Releaser(handle); }
532
static Runnable ofNullable(Scope.Handle handle) {
533
if (handle == null)
534
return () -> { };
535
return new Releaser(handle);
536
}
537
}
538
539
static long bufferAddress(ByteBuffer buf) {
540
return NIO_ACCESS.getBufferAddress(buf);
541
}
542
543
public static FileDescriptor newFD(int i) {
544
FileDescriptor fd = new FileDescriptor();
545
setfdVal(fd, i);
546
return fd;
547
}
548
549
static native boolean randomBytes(byte[] someBytes);
550
551
/**
552
* Returns two file descriptors for a pipe encoded in a long.
553
* The read end of the pipe is returned in the high 32 bits,
554
* while the write end is returned in the low 32 bits.
555
*/
556
static native long makePipe(boolean blocking) throws IOException;
557
558
static native int write1(int fd, byte b) throws IOException;
559
560
/**
561
* Read and discard all bytes.
562
*/
563
static native boolean drain(int fd) throws IOException;
564
565
/**
566
* Read and discard at most one byte
567
* @return the number of bytes read or IOS_INTERRUPTED
568
*/
569
static native int drain1(int fd) throws IOException;
570
571
public static native void configureBlocking(FileDescriptor fd,
572
boolean blocking)
573
throws IOException;
574
575
public static native int fdVal(FileDescriptor fd);
576
577
static native void setfdVal(FileDescriptor fd, int value);
578
579
static native int fdLimit();
580
581
static native int iovMax();
582
583
static native void initIDs();
584
585
/**
586
* Used to trigger loading of native libraries
587
*/
588
public static void load() { }
589
590
static {
591
jdk.internal.loader.BootLoader.loadLibrary("net");
592
jdk.internal.loader.BootLoader.loadLibrary("nio");
593
initIDs();
594
595
IOV_MAX = iovMax();
596
}
597
598
}
599
600