mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8345181: (ch) Windows asynchronous channels may return temporary direct buffers to the buffer cache twice (win)
Reviewed-by: alanb, michaelm
This commit is contained in:
parent
ee0f88c901
commit
ea73e05852
@ -25,6 +25,8 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.channels.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -34,6 +36,7 @@ import java.io.FileDescriptor;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.access.JavaIOFileDescriptorAccess;
|
||||
import jdk.internal.event.FileForceEvent;
|
||||
import jdk.internal.invoke.MhUtil;
|
||||
|
||||
/**
|
||||
* Windows implementation of AsynchronousFileChannel using overlapped I/O.
|
||||
@ -383,10 +386,13 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
* Task that initiates read operation and handles completion result.
|
||||
*/
|
||||
private class ReadTask<A> implements Runnable, Iocp.ResultHandler {
|
||||
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
|
||||
"released", boolean.class);
|
||||
private final ByteBuffer dst;
|
||||
private final int pos, rem; // buffer position/remaining
|
||||
private final long position; // file position
|
||||
private final PendingFuture<Integer,A> result;
|
||||
private volatile boolean released;
|
||||
|
||||
// set to dst if direct; otherwise set to substituted direct buffer
|
||||
private volatile ByteBuffer buf;
|
||||
@ -405,8 +411,9 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
void releaseBufferIfSubstituted() {
|
||||
if (buf != dst)
|
||||
if (buf != dst && RELEASED.compareAndSet(this, false, true)) {
|
||||
Util.releaseTemporaryDirectBuffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePosition(int bytesTransferred) {
|
||||
@ -569,10 +576,13 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
* Task that initiates write operation and handles completion result.
|
||||
*/
|
||||
private class WriteTask<A> implements Runnable, Iocp.ResultHandler {
|
||||
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
|
||||
"released", boolean.class);
|
||||
private final ByteBuffer src;
|
||||
private final int pos, rem; // buffer position/remaining
|
||||
private final long position; // file position
|
||||
private final PendingFuture<Integer,A> result;
|
||||
private volatile boolean released;
|
||||
|
||||
// set to src if direct; otherwise set to substituted direct buffer
|
||||
private volatile ByteBuffer buf;
|
||||
@ -591,8 +601,9 @@ public class WindowsAsynchronousFileChannelImpl
|
||||
}
|
||||
|
||||
void releaseBufferIfSubstituted() {
|
||||
if (buf != src)
|
||||
if (buf != src && RELEASED.compareAndSet(this, false, true)) {
|
||||
Util.releaseTemporaryDirectBuffer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePosition(int bytesTransferred) {
|
||||
|
||||
@ -25,12 +25,15 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.net.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.io.IOException;
|
||||
import jdk.internal.invoke.MhUtil;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import sun.net.util.SocketExceptions;
|
||||
|
||||
@ -367,10 +370,13 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
* result when the read completes.
|
||||
*/
|
||||
private class ReadTask<V,A> implements Runnable, Iocp.ResultHandler {
|
||||
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
|
||||
"released", boolean.class);
|
||||
private final ByteBuffer[] bufs;
|
||||
private final int numBufs;
|
||||
private final boolean scatteringRead;
|
||||
private final PendingFuture<V,A> result;
|
||||
private volatile boolean released;
|
||||
|
||||
// set by run method
|
||||
private ByteBuffer[] shadow;
|
||||
@ -461,12 +467,14 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
void releaseBuffers() {
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
Util.releaseTemporaryDirectBuffer(shadow[i]);
|
||||
if (RELEASED.compareAndSet(this, false, true)) {
|
||||
for (int i = 0; i < numBufs; i++) {
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
Util.releaseTemporaryDirectBuffer(shadow[i]);
|
||||
}
|
||||
}
|
||||
IOUtil.releaseScopes(scopeHandleReleasers);
|
||||
}
|
||||
IOUtil.releaseScopes(scopeHandleReleasers);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -641,10 +649,13 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
* result when the write completes.
|
||||
*/
|
||||
private class WriteTask<V,A> implements Runnable, Iocp.ResultHandler {
|
||||
private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(),
|
||||
"released", boolean.class);
|
||||
private final ByteBuffer[] bufs;
|
||||
private final int numBufs;
|
||||
private final boolean gatheringWrite;
|
||||
private final PendingFuture<V,A> result;
|
||||
private volatile boolean released;
|
||||
|
||||
// set by run method
|
||||
private ByteBuffer[] shadow;
|
||||
@ -728,12 +739,14 @@ class WindowsAsynchronousSocketChannelImpl
|
||||
}
|
||||
|
||||
void releaseBuffers() {
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
Util.releaseTemporaryDirectBuffer(shadow[i]);
|
||||
if (RELEASED.compareAndSet(this, false, true)) {
|
||||
for (int i = 0; i < numBufs; i++) {
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
Util.releaseTemporaryDirectBuffer(shadow[i]);
|
||||
}
|
||||
}
|
||||
IOUtil.releaseScopes(scopeHandleReleasers);
|
||||
}
|
||||
IOUtil.releaseScopes(scopeHandleReleasers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user