return err
}
-// pin pins ptr for the duration of the IO operation.
-// If fd is in blocking mode, pin does nothing.
-func (fd *FD) pin(mode int, ptr any) {
- if fd.isBlocking {
- return
- }
- if mode == 'r' {
- fd.readPinner.Pin(ptr)
- } else {
- fd.writePinner.Pin(ptr)
- }
-}
-
// execIO executes a single IO operation o.
// It supports both synchronous and asynchronous IO.
-func (fd *FD) execIO(mode int, submit func(o *operation) (uint32, error)) (int, error) {
- if mode == 'r' {
- defer fd.readPinner.Unpin()
- } else {
- defer fd.writePinner.Unpin()
- }
+// buf, if not nil, will be pinned during the lifetime of the operation.
+func (fd *FD) execIO(mode int, submit func(o *operation) (uint32, error), buf []byte) (int, error) {
// Notify runtime netpoll about starting IO.
err := fd.pd.prepare(mode, fd.isFile)
if err != nil {
runtimeCtx: fd.pd.runtimeCtx,
mode: int32(mode),
}
- // Start IO.
- if !fd.isBlocking && !fd.pollable() {
- // If the handle is opened for overlapped IO but we can't
- // use the runtime poller, then we need to use an
- // event to wait for the IO to complete.
- h, err := windows.CreateEvent(nil, 0, 0, nil)
- if err != nil {
- // This shouldn't happen when all CreateEvent arguments are zero.
- panic(err)
+ if !fd.isBlocking {
+ if len(buf) > 0 {
+ ptr := unsafe.SliceData(buf)
+ if mode == 'r' {
+ fd.readPinner.Pin(ptr)
+ } else {
+ fd.writePinner.Pin(ptr)
+ }
+ defer func() {
+ if mode == 'r' {
+ fd.readPinner.Unpin()
+ } else {
+ fd.writePinner.Unpin()
+ }
+ }()
+ }
+ if !fd.pollable() {
+ // If the handle is opened for overlapped IO but we can't
+ // use the runtime poller, then we need to use an
+ // event to wait for the IO to complete.
+ h, err := windows.CreateEvent(nil, 0, 0, nil)
+ if err != nil {
+ // This shouldn't happen when all CreateEvent arguments are zero.
+ panic(err)
+ }
+ // Set the low bit so that the external IOCP doesn't receive the completion packet.
+ o.o.HEvent = h | 1
+ defer syscall.CloseHandle(h)
}
- // Set the low bit so that the external IOCP doesn't receive the completion packet.
- o.o.HEvent = h | 1
- defer syscall.CloseHandle(h)
}
- fd.pin(mode, o)
+ // Start IO.
qty, err := submit(o)
var waitErr error
// Blocking operations shouldn't return ERROR_IO_PENDING.
defer fd.readUnlock()
}
- if len(buf) > 0 {
- fd.pin('r', &buf[0])
- }
-
if len(buf) > maxRW {
buf = buf[:maxRW]
}
n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) {
err = syscall.ReadFile(fd.Sysfd, buf, &qty, fd.overlapped(o))
return qty, err
- })
+ }, buf)
fd.addOffset(n)
switch err {
case syscall.ERROR_HANDLE_EOF:
var flags uint32
err = syscall.WSARecv(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &o.o, nil)
return qty, err
- })
+ }, buf)
if race.Enabled {
race.Acquire(unsafe.Pointer(&ioSync))
}
}
defer fd.readWriteUnlock()
- if len(buf) > 0 {
- fd.pin('r', &buf[0])
- }
-
if len(buf) > maxRW {
buf = buf[:maxRW]
}
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
err = syscall.ReadFile(fd.Sysfd, buf, &qty, &o.o)
return qty, err
- })
+ }, buf)
if err == syscall.ERROR_HANDLE_EOF {
err = io.EOF
}
}
defer fd.readUnlock()
- fd.pin('r', &buf[0])
-
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
defer wsaRsaPool.Put(rsa)
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
var flags uint32
err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
return qty, err
- })
+ }, buf)
err = fd.eofError(n, err)
if err != nil {
return n, nil, err
}
defer fd.readUnlock()
- fd.pin('r', &buf[0])
-
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
defer wsaRsaPool.Put(rsa)
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
var flags uint32
err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
return qty, err
- })
+ }, buf)
err = fd.eofError(n, err)
if err != nil {
return n, err
}
defer fd.readUnlock()
- fd.pin('r', &buf[0])
-
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
defer wsaRsaPool.Put(rsa)
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
var flags uint32
err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil)
return qty, err
- })
+ }, buf)
err = fd.eofError(n, err)
if err != nil {
return n, err
defer fd.writeUnlock()
}
- if len(buf) > 0 {
- fd.pin('w', &buf[0])
- }
var ntotal int
for {
max := len(buf)
n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = syscall.WriteFile(fd.Sysfd, b, &qty, fd.overlapped(o))
return qty, err
- })
+ }, b)
fd.addOffset(n)
case kindNet:
if race.Enabled {
n, err = fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = syscall.WSASend(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, &o.o, nil)
return qty, err
- })
+ }, b)
}
ntotal += n
if ntotal == len(buf) || err != nil {
}
defer fd.readWriteUnlock()
- if len(buf) > 0 {
- fd.pin('w', &buf[0])
- }
-
if fd.isBlocking {
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
if err != nil {
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = syscall.WriteFile(fd.Sysfd, buf[ntotal:max], &qty, &o.o)
return qty, err
- })
+ }, buf[ntotal:max])
if n > 0 {
ntotal += n
}
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = syscall.WSASend(fd.Sysfd, &(*bufs)[0], uint32(len(*bufs)), &qty, 0, &o.o, nil)
return qty, err
- })
+ }, nil)
TestHookDidWritev(n)
consume(buf, int64(n))
return int64(n), err
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = syscall.WSASendto(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa, &o.o, nil)
return qty, err
- })
+ }, nil)
return n, err
}
- fd.pin('w', &buf[0])
-
ntotal := 0
for len(buf) > 0 {
b := buf
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = syscall.WSASendto(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa, &o.o, nil)
return qty, err
- })
+ }, b)
ntotal += int(n)
if err != nil {
return ntotal, err
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendtoInet4(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa4, &o.o, nil)
return qty, err
- })
+ }, nil)
return n, err
}
- fd.pin('w', &buf[0])
-
ntotal := 0
for len(buf) > 0 {
b := buf
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendtoInet4(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa4, &o.o, nil)
return qty, err
- })
+ }, b)
ntotal += int(n)
if err != nil {
return ntotal, err
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendtoInet6(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, 0, sa6, &o.o, nil)
return qty, err
- })
+ }, nil)
return n, err
}
- fd.pin('w', &buf[0])
-
ntotal := 0
for len(buf) > 0 {
b := buf
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendtoInet6(fd.Sysfd, newWsaBuf(b), 1, &qty, 0, sa6, &o.o, nil)
return qty, err
- })
+ }, b)
ntotal += int(n)
if err != nil {
return ntotal, err
func (fd *FD) ConnectEx(ra syscall.Sockaddr) error {
_, err := fd.execIO('w', func(o *operation) (uint32, error) {
return 0, ConnectExFunc(fd.Sysfd, ra, nil, 0, nil, &o.o)
- })
+ }, nil)
return err
}
err = AcceptFunc(fd.Sysfd, s, (*byte)(unsafe.Pointer(&rawsa[0])), 0, rsan, rsan, &qty, &o.o)
return qty, err
- })
+ }, nil)
if err != nil {
CloseFunc(s)
return "acceptex", err
}
err = syscall.WSARecv(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, &flags, &o.o, nil)
return qty, err
- })
+ }, nil)
if err == windows.WSAEMSGSIZE {
// expected with a 0-byte peek, ignore.
} else if err != nil {
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
return qty, err
- })
+ }, nil)
err = fd.eofError(n, err)
var sa syscall.Sockaddr
if err == nil {
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
return qty, err
- })
+ }, nil)
err = fd.eofError(n, err)
if err == nil {
rawToSockaddrInet4(msg.Name, sa4)
n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) {
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
return qty, err
- })
+ }, nil)
err = fd.eofError(n, err)
if err == nil {
rawToSockaddrInet6(msg.Name, sa6)
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
return qty, err
- })
+ }, nil)
return n, int(msg.Control.Len), err
}
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
return qty, err
- })
+ }, nil)
return n, int(msg.Control.Len), err
}
n, err := fd.execIO('w', func(o *operation) (qty uint32, err error) {
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
return qty, err
- })
+ }, nil)
return n, int(msg.Control.Len), err
}