diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/internal/poll/fd_windows.go | 140 | ||||
| -rw-r--r-- | src/internal/poll/sendfile_windows.go | 2 |
2 files changed, 57 insertions, 85 deletions
diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index ef8050daf4..699239c57b 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -232,27 +232,10 @@ func (fd *FD) waitIO(o *operation) error { 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 { @@ -268,21 +251,37 @@ func (fd *FD) execIO(mode int, submit func(o *operation) (uint32, error)) (int, 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. @@ -544,10 +543,6 @@ func (fd *FD) Read(buf []byte) (int, error) { defer fd.readUnlock() } - if len(buf) > 0 { - fd.pin('r', &buf[0]) - } - if len(buf) > maxRW { buf = buf[:maxRW] } @@ -561,7 +556,7 @@ func (fd *FD) Read(buf []byte) (int, error) { 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: @@ -577,7 +572,7 @@ func (fd *FD) Read(buf []byte) (int, error) { 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)) } @@ -674,10 +669,6 @@ func (fd *FD) Pread(buf []byte, off int64) (int, error) { } defer fd.readWriteUnlock() - if len(buf) > 0 { - fd.pin('r', &buf[0]) - } - if len(buf) > maxRW { buf = buf[:maxRW] } @@ -702,7 +693,7 @@ func (fd *FD) Pread(buf []byte, off int64) (int, error) { 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 } @@ -725,8 +716,6 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { } 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) { @@ -734,7 +723,7 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, 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 @@ -756,8 +745,6 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) } 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) { @@ -765,7 +752,7 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, 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 @@ -787,8 +774,6 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) } 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) { @@ -796,7 +781,7 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, 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 @@ -819,9 +804,6 @@ func (fd *FD) Write(buf []byte) (int, error) { defer fd.writeUnlock() } - if len(buf) > 0 { - fd.pin('w', &buf[0]) - } var ntotal int for { max := len(buf) @@ -838,7 +820,7 @@ func (fd *FD) Write(buf []byte) (int, error) { 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 { @@ -847,7 +829,7 @@ func (fd *FD) Write(buf []byte) (int, error) { 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 { @@ -914,10 +896,6 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) { } 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 { @@ -945,7 +923,7 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) { 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 } @@ -975,7 +953,7 @@ func (fd *FD) Writev(buf *[][]byte) (int64, error) { 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 @@ -993,12 +971,10 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 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 @@ -1008,7 +984,7 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 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 @@ -1030,12 +1006,10 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) 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 @@ -1045,7 +1019,7 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) 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 @@ -1067,12 +1041,10 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) 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 @@ -1082,7 +1054,7 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) 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 @@ -1098,7 +1070,7 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) 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 } @@ -1109,7 +1081,7 @@ func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny) (strin 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 @@ -1275,7 +1247,7 @@ func (fd *FD) RawRead(f func(uintptr) bool) error { } 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 { @@ -1366,7 +1338,7 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S 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 { @@ -1391,7 +1363,7 @@ func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.Sockadd 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) @@ -1415,7 +1387,7 @@ func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.Sockadd 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) @@ -1446,7 +1418,7 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, 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 } @@ -1469,7 +1441,7 @@ func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (in 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 } @@ -1492,7 +1464,7 @@ func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (in 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 } diff --git a/src/internal/poll/sendfile_windows.go b/src/internal/poll/sendfile_windows.go index 2bdfecf013..0a5a8897dd 100644 --- a/src/internal/poll/sendfile_windows.go +++ b/src/internal/poll/sendfile_windows.go @@ -75,7 +75,7 @@ func SendFile(fd *FD, src uintptr, size int64) (written int64, err error, handle return 0, err } return uint32(chunkSize), nil - }) + }, nil) if err != nil { return written, err, written > 0 } |
