diff options
| author | Cherry Mui <cherryyz@google.com> | 2025-10-03 10:11:20 -0400 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2025-10-03 10:11:21 -0400 |
| commit | fb1749a3fe6ac40c56127d8fcea2e8b13db820e8 (patch) | |
| tree | 72dd38fc84286bf88311850a99e6becf2cbd99bf /src/internal | |
| parent | 703a5fbaad81f1285776bf6f2900506d3c751ea1 (diff) | |
| parent | adce7f196e6ac6d22e9bc851efea5f3ab650947c (diff) | |
| download | go-fb1749a3fe6ac40c56127d8fcea2e8b13db820e8.tar.xz | |
[dev.simd] all: merge master (adce7f1) into dev.simd
Conflicts:
- src/internal/goexperiment/flags.go
- src/runtime/export_test.go
Merge List:
+ 2025-10-03 adce7f196e cmd/link: support .def file with MSVC clang toolchain
+ 2025-10-03 d5b950399d cmd/cgo: fix unaligned arguments typedmemmove crash on iOS
+ 2025-10-02 53845004d6 net/http/httputil: deprecate ReverseProxy.Director
+ 2025-10-02 bbdff9e8e1 net/http: update bundled x/net/http2 and delete obsolete http2inTests
+ 2025-10-02 4008e07080 io/fs: move path name documentation up to the package doc comment
+ 2025-10-02 0e4e2e6832 runtime: skip TestGoroutineLeakProfile under mayMoreStackPreempt
+ 2025-10-02 f03c392295 runtime: fix aix/ppc64 library initialization
+ 2025-10-02 707454b41f cmd/go: update `go help mod edit` with the tool and ignore sections
+ 2025-10-02 8c68a1c1ab runtime,net/http/pprof: goroutine leak detection by using the garbage collector
+ 2025-10-02 84db201ae1 cmd/compile: propagate len([]T{}) to make builtin to allow stack allocation
+ 2025-10-02 5799c139a7 crypto/tls: rm marshalEncryptedClientHelloConfigList dead code
+ 2025-10-01 633dd1d475 encoding/json: fix Decoder.InputOffset regression in goexperiment.jsonv2
+ 2025-10-01 8ad27fb656 doc/go_spec.html: update date
+ 2025-10-01 3f451f2c54 testing/synctest: fix inverted test failure message in TestContextAfterFunc
+ 2025-10-01 be0fed8a5f cmd/go/testdata/script/test_fuzz_fuzztime.txt: disable
+ 2025-09-30 eb1c7f6e69 runtime: move loong64 library entry point to os-agnostic file
+ 2025-09-30 c9257151e5 runtime: unify ppc64/ppc64le library entry point
+ 2025-09-30 4ff8a457db test/codegen: codify handling of floating point constants on arm64
+ 2025-09-30 fcb893fc4b cmd/compile/internal/ssa: remove redundant "type:" prefix check
+ 2025-09-30 19cc1022ba mime: reduce allocs incurred by ParseMediaType
+ 2025-09-30 08afc50bea mime: extend "builtinTypes" to include a more complete list of common types
+ 2025-09-30 97da068774 cmd/compile: eliminate nil checks on .dict arg
+ 2025-09-30 300d9d2714 runtime: initialise debug settings much earlier in startup process
+ 2025-09-30 a846bb0aa5 errors: add AsType
+ 2025-09-30 7c8166d02d cmd/link/internal/arm64: support Mach-O ARM64_RELOC_SUBTRACTOR in internal linking
+ 2025-09-30 6e95748335 cmd/link/internal/arm64: support Mach-O ARM64_RELOC_POINTER_TO_GOT in internal linking
+ 2025-09-30 742f92063e cmd/compile, runtime: always enable Wasm signext and satconv features
+ 2025-09-30 db10db6be3 internal/poll: remove operation fields from FD
+ 2025-09-29 75c87df58e internal/poll: pass the I/O mode instead of an overlapped object in execIO
+ 2025-09-29 fc88e18b4a crypto/internal/fips140/entropy: add CPU jitter-based entropy source
+ 2025-09-29 db4fade759 crypto/internal/fips140/mlkem: make CAST conditional
+ 2025-09-29 db3cb3fd9a runtime: correct reference to getStackMap in comment
+ 2025-09-29 690fc2fb05 internal/poll: remove buf field from operation
+ 2025-09-29 eaf2345256 cmd/link: use a .def file to mark exported symbols on Windows
+ 2025-09-29 4b77733565 internal/syscall/windows: regenerate GetFileSizeEx
+ 2025-09-29 4e9006a716 crypto/tls: quote protocols in ALPN error message
+ 2025-09-29 047c2ab841 cmd/link: don't pass -Wl,-S on Solaris
+ 2025-09-29 ae8eba071b cmd/link: use correct length for pcln.cutab
+ 2025-09-29 fe3ba74b9e cmd/link: skip TestFlagW on platforms without DWARF symbol table
+ 2025-09-29 d42d56b764 encoding/xml: make use of reflect.TypeAssert
+ 2025-09-29 6d51f93257 runtime: jump instead of branch in netbsd/arm64 entry point
+ 2025-09-28 5500cbf0e4 debug/elf: prevent offset overflow
+ 2025-09-27 34e67623a8 all: fix typos
+ 2025-09-27 af6999e60d cmd/compile: implement jump table on loong64
+ 2025-09-26 63cd912083 os/user: simplify go:build
+ 2025-09-26 53009b26dd runtime: use a smaller arena size on Wasm
+ 2025-09-26 3a5df9d2b2 net/http: add HTTP2Config.StrictMaxConcurrentRequests
+ 2025-09-26 16be34df02 net/http: add more tests of transport connection pool
+ 2025-09-26 3e4540b49d os/user: use getgrouplist on illumos && cgo
+ 2025-09-26 15fbe3480b internal/poll: simplify WriteMsg and ReadMsg on Windows
+ 2025-09-26 16ae11a9e1 runtime: move TestReadMetricsSched to testprog
+ 2025-09-26 459f3a3adc cmd/link: don't pass -Wl,-S on AIX
+ 2025-09-26 4631a2d3c6 cmd/link: skip TestFlagW on AIX
+ 2025-09-26 0f31d742cd cmd/compile: fix ICE with new(<untyped expr>)
+ 2025-09-26 7d7cd6e07b internal/poll: don't call SetFilePointerEx in Seek for overlapped handles
+ 2025-09-26 41cba31e66 mime/multipart: percent-encode CR and LF in header values to avoid CRLF injection
+ 2025-09-26 dd1d597c3a Revert "cmd/internal/obj/loong64: use the MOVVP instruction to optimize prologue"
+ 2025-09-26 45d6bc76af runtime: unify arm64 entry point code
+ 2025-09-25 fdea7da3e6 runtime: use common library entry point on windows amd64/386
+ 2025-09-25 e8a4f508d1 lib/fips140: re-seal v1.0.0
+ 2025-09-25 9b7a328089 crypto/internal/fips140: remove key import PCTs, make keygen PCTs fatal
+ 2025-09-25 7f9ab7203f crypto/internal/fips140: update frozen module version to "v1.0.0"
+ 2025-09-25 fb5719cbda crypto/internal/fips140/ecdsa: make TestingOnlyNewDRBG generic
+ 2025-09-25 56067e31f2 std: remove unused declarations
Change-Id: Iecb28fd62c69fbed59da557f46d31bae55889e2c
Diffstat (limited to 'src/internal')
| -rw-r--r-- | src/internal/buildcfg/cfg.go | 30 | ||||
| -rw-r--r-- | src/internal/goexperiment/exp_goroutineleakprofile_off.go | 8 | ||||
| -rw-r--r-- | src/internal/goexperiment/exp_goroutineleakprofile_on.go | 8 | ||||
| -rw-r--r-- | src/internal/goexperiment/flags.go | 3 | ||||
| -rw-r--r-- | src/internal/poll/fd_windows.go | 343 | ||||
| -rw-r--r-- | src/internal/poll/sendfile_windows.go | 8 | ||||
| -rw-r--r-- | src/internal/runtime/gc/scan.go | 2 | ||||
| -rw-r--r-- | src/internal/runtime/gc/scan/expand_reference.go | 2 | ||||
| -rw-r--r-- | src/internal/syscall/windows/syscall_windows.go | 4 | ||||
| -rw-r--r-- | src/internal/syscall/windows/zsyscall_windows.go | 9 |
10 files changed, 223 insertions, 194 deletions
diff --git a/src/internal/buildcfg/cfg.go b/src/internal/buildcfg/cfg.go index 52d1c45afa..a75960b8e6 100644 --- a/src/internal/buildcfg/cfg.go +++ b/src/internal/buildcfg/cfg.go @@ -85,7 +85,7 @@ func gofips140() string { } // isFIPSVersion reports whether v is a valid FIPS version, -// of the form vX.Y.Z. +// of the form vX.Y.Z or vX.Y.Z-hash. func isFIPSVersion(v string) bool { if !strings.HasPrefix(v, "v") { return false @@ -99,7 +99,8 @@ func isFIPSVersion(v string) bool { return false } v, ok = skipNum(v[len("."):]) - return ok && v == "" + hasHash := strings.HasPrefix(v, "-") && len(v) == len("-")+8 + return ok && (v == "" || hasHash) } // skipNum skips the leading text matching [0-9]+ @@ -320,18 +321,13 @@ func goriscv64() int { } type gowasmFeatures struct { - SatConv bool - SignExt bool + // Legacy features, now always enabled + //SatConv bool + //SignExt bool } func (f gowasmFeatures) String() string { var flags []string - if f.SatConv { - flags = append(flags, "satconv") - } - if f.SignExt { - flags = append(flags, "signext") - } return strings.Join(flags, ",") } @@ -339,9 +335,9 @@ func gowasm() (f gowasmFeatures) { for opt := range strings.SplitSeq(envOr("GOWASM", ""), ",") { switch opt { case "satconv": - f.SatConv = true + // ignore, always enabled case "signext": - f.SignExt = true + // ignore, always enabled case "": // ignore default: @@ -451,12 +447,10 @@ func gogoarchTags() []string { return list case "wasm": var list []string - if GOWASM.SatConv { - list = append(list, GOARCH+".satconv") - } - if GOWASM.SignExt { - list = append(list, GOARCH+".signext") - } + // SatConv is always enabled + list = append(list, GOARCH+".satconv") + // SignExt is always enabled + list = append(list, GOARCH+".signext") return list } return nil diff --git a/src/internal/goexperiment/exp_goroutineleakprofile_off.go b/src/internal/goexperiment/exp_goroutineleakprofile_off.go new file mode 100644 index 0000000000..63eafe9e6c --- /dev/null +++ b/src/internal/goexperiment/exp_goroutineleakprofile_off.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.goroutineleakprofile + +package goexperiment + +const GoroutineLeakProfile = false +const GoroutineLeakProfileInt = 0 diff --git a/src/internal/goexperiment/exp_goroutineleakprofile_on.go b/src/internal/goexperiment/exp_goroutineleakprofile_on.go new file mode 100644 index 0000000000..28a662eceb --- /dev/null +++ b/src/internal/goexperiment/exp_goroutineleakprofile_on.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.goroutineleakprofile + +package goexperiment + +const GoroutineLeakProfile = true +const GoroutineLeakProfileInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index f9155568a9..f8c9b637f3 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -119,6 +119,9 @@ type Flags struct { // SizeSpecializedMalloc enables malloc implementations that are specialized per size class. SizeSpecializedMalloc bool + // GoroutineLeakProfile enables the collection of goroutine leak profiles. + GoroutineLeakProfile bool + // SIMD enables the simd package and the compiler's handling // of SIMD intrinsics. SIMD bool diff --git a/src/internal/poll/fd_windows.go b/src/internal/poll/fd_windows.go index 23500d3e39..6443f6eb30 100644 --- a/src/internal/poll/fd_windows.go +++ b/src/internal/poll/fd_windows.go @@ -9,6 +9,7 @@ import ( "internal/race" "internal/syscall/windows" "io" + "runtime" "sync" "sync/atomic" "syscall" @@ -75,25 +76,6 @@ type operation struct { // fields used by runtime.netpoll runtimeCtx uintptr mode int32 - - // fields used only by net package - buf syscall.WSABuf -} - -func (o *operation) setEvent() { - 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 -} - -func (o *operation) close() { - if o.o.HEvent != 0 { - syscall.CloseHandle(o.o.HEvent) - } } func (fd *FD) overlapped(o *operation) *syscall.Overlapped { @@ -107,9 +89,8 @@ func (fd *FD) overlapped(o *operation) *syscall.Overlapped { return &o.o } -func (o *operation) InitBuf(buf []byte) { - o.buf.Len = uint32(len(buf)) - o.buf.Buf = unsafe.SliceData(buf) +func newWsaBuf(b []byte) *syscall.WSABuf { + return &syscall.WSABuf{Buf: unsafe.SliceData(b), Len: uint32(len(b))} } var wsaBufsPool = sync.Pool{ @@ -168,7 +149,7 @@ var wsaMsgPool = sync.Pool{ // newWSAMsg creates a new WSAMsg with the provided parameters. // Use [freeWSAMsg] to free it. -func newWSAMsg(p []byte, oob []byte, flags int, rsa *syscall.RawSockaddrAny) *windows.WSAMsg { +func newWSAMsg(p []byte, oob []byte, flags int, unconnected bool) *windows.WSAMsg { // The returned object can't be allocated in the stack because it is accessed asynchronously // by Windows in between several system calls. If the stack frame is moved while that happens, // then Windows may access invalid memory. @@ -183,11 +164,9 @@ func newWSAMsg(p []byte, oob []byte, flags int, rsa *syscall.RawSockaddrAny) *wi Buf: unsafe.SliceData(oob), } msg.Flags = uint32(flags) - msg.Name = syscall.Pointer(unsafe.Pointer(rsa)) - if rsa != nil { - msg.Namelen = int32(unsafe.Sizeof(*rsa)) - } else { - msg.Namelen = 0 + if unconnected { + msg.Name = wsaRsaPool.Get().(*syscall.RawSockaddrAny) + msg.Namelen = int32(unsafe.Sizeof(syscall.RawSockaddrAny{})) } return msg } @@ -198,6 +177,12 @@ func freeWSAMsg(msg *windows.WSAMsg) { msg.Buffers.Buf = nil msg.Control.Len = 0 msg.Control.Buf = nil + if msg.Name != nil { + *msg.Name = syscall.RawSockaddrAny{} + wsaRsaPool.Put(msg.Name) + msg.Name = nil + msg.Namelen = 0 + } wsaMsgPool.Put(msg) } @@ -207,6 +192,12 @@ var wsaRsaPool = sync.Pool{ }, } +var operationPool = sync.Pool{ + New: func() any { + return new(operation) + }, +} + // waitIO waits for the IO operation o to complete. func (fd *FD) waitIO(o *operation) error { if fd.isBlocking { @@ -245,23 +236,57 @@ func (fd *FD) cancelIO(o *operation) { fd.pd.waitCanceled(int(o.mode)) } +// 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. -// o.qty and o.flags are set to zero before calling submit -// to avoid reusing the values from a previous call. -func (fd *FD) execIO(o *operation, submit func(o *operation) (uint32, error)) (int, error) { +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() + } // Notify runtime netpoll about starting IO. - err := fd.pd.prepare(int(o.mode), fd.isFile) + err := fd.pd.prepare(mode, fd.isFile) if err != nil { return 0, err } + o := operationPool.Get().(*operation) + defer operationPool.Put(o) + *o = operation{ + o: syscall.Overlapped{ + OffsetHigh: uint32(fd.offset >> 32), + Offset: uint32(fd.offset), + }, + runtimeCtx: fd.pd.runtimeCtx, + mode: int32(mode), + } // Start IO. - if !fd.isBlocking && o.o.HEvent == 0 && !fd.pollable() { + 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. - o.setEvent() + 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) } + fd.pin(mode, o) qty, err := submit(o) var waitErr error // Blocking operations shouldn't return ERROR_IO_PENDING. @@ -316,11 +341,6 @@ type FD struct { // System file descriptor. Immutable until Close. Sysfd syscall.Handle - // Read operation. - rop operation - // Write operation. - wop operation - // I/O poller. pd pollDesc @@ -358,6 +378,11 @@ type FD struct { isBlocking bool disassociated atomic.Bool + + // readPinner and writePinner are automatically unpinned + // before execIO returns. + readPinner runtime.Pinner + writePinner runtime.Pinner } // setOffset sets the offset fields of the overlapped object @@ -375,8 +400,6 @@ type FD struct { // using an external mechanism. func (fd *FD) setOffset(off int64) { fd.offset = off - fd.rop.o.OffsetHigh, fd.rop.o.Offset = uint32(off>>32), uint32(off) - fd.wop.o.OffsetHigh, fd.wop.o.Offset = uint32(off>>32), uint32(off) } // addOffset adds the given offset to the current offset. @@ -427,8 +450,6 @@ func (fd *FD) Init(net string, pollable bool) error { } fd.isFile = fd.kind != kindNet fd.isBlocking = !pollable - fd.rop.mode = 'r' - fd.wop.mode = 'w' // It is safe to add overlapped handles that also perform I/O // outside of the runtime poller. The runtime poller will ignore @@ -437,8 +458,6 @@ func (fd *FD) Init(net string, pollable bool) error { if err != nil { return err } - fd.rop.runtimeCtx = fd.pd.runtimeCtx - fd.wop.runtimeCtx = fd.pd.runtimeCtx if fd.kind != kindNet || socketCanUseSetFileCompletionNotificationModes { // Non-socket handles can use SetFileCompletionNotificationModes without problems. err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, @@ -477,8 +496,6 @@ func (fd *FD) destroy() error { if fd.Sysfd == syscall.InvalidHandle { return syscall.EINVAL } - fd.rop.close() - fd.wop.close() // Poller may want to unregister fd in readiness notification mechanism, // so this must be executed before fd.CloseFunc. fd.pd.close() @@ -533,6 +550,10 @@ 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] } @@ -543,10 +564,8 @@ func (fd *FD) Read(buf []byte) (int, error) { case kindConsole: n, err = fd.readConsole(buf) case kindFile, kindPipe: - o := &fd.rop - o.InitBuf(buf) - n, err = fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.ReadFile(fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &qty, fd.overlapped(o)) + 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 }) fd.addOffset(n) @@ -560,11 +579,9 @@ func (fd *FD) Read(buf []byte) (int, error) { } } case kindNet: - o := &fd.rop - o.InitBuf(buf) - n, err = fd.execIO(o, func(o *operation) (qty uint32, err error) { + n, err = fd.execIO('r', func(o *operation) (qty uint32, err error) { var flags uint32 - err = syscall.WSARecv(fd.Sysfd, &o.buf, 1, &qty, &flags, &o.o, nil) + err = syscall.WSARecv(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, &o.o, nil) return qty, err }) if race.Enabled { @@ -652,7 +669,7 @@ func (fd *FD) readConsole(b []byte) (int, error) { } // Pread emulates the Unix pread system call. -func (fd *FD) Pread(b []byte, off int64) (int, error) { +func (fd *FD) Pread(buf []byte, off int64) (int, error) { if fd.kind == kindPipe { // Pread does not work with pipes return 0, syscall.ESPIPE @@ -663,8 +680,12 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) { } defer fd.readWriteUnlock() - if len(b) > maxRW { - b = b[:maxRW] + if len(buf) > 0 { + fd.pin('r', &buf[0]) + } + + if len(buf) > maxRW { + buf = buf[:maxRW] } if fd.isBlocking { @@ -683,17 +704,15 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) { curoffset := fd.offset defer fd.setOffset(curoffset) } - o := &fd.rop - o.InitBuf(b) fd.setOffset(off) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.ReadFile(fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &qty, &o.o) + n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) { + err = syscall.ReadFile(fd.Sysfd, buf, &qty, &o.o) return qty, err }) if err == syscall.ERROR_HANDLE_EOF { err = io.EOF } - if len(b) != 0 { + if len(buf) != 0 { err = fd.eofError(n, err) } return n, err @@ -711,14 +730,15 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) { return 0, nil, err } defer fd.readUnlock() - o := &fd.rop - o.InitBuf(buf) + + fd.pin('r', &buf[0]) + rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny) defer wsaRsaPool.Put(rsa) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { + n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) { rsan := int32(unsafe.Sizeof(*rsa)) var flags uint32 - err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, rsa, &rsan, &o.o, nil) + err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil) return qty, err }) err = fd.eofError(n, err) @@ -741,14 +761,15 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) return 0, err } defer fd.readUnlock() - o := &fd.rop - o.InitBuf(buf) + + fd.pin('r', &buf[0]) + rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny) defer wsaRsaPool.Put(rsa) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { + n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) { rsan := int32(unsafe.Sizeof(*rsa)) var flags uint32 - err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, rsa, &rsan, &o.o, nil) + err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil) return qty, err }) err = fd.eofError(n, err) @@ -771,14 +792,15 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) return 0, err } defer fd.readUnlock() - o := &fd.rop - o.InitBuf(buf) + + fd.pin('r', &buf[0]) + rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny) defer wsaRsaPool.Put(rsa) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { + n, err := fd.execIO('r', func(o *operation) (qty uint32, err error) { rsan := int32(unsafe.Sizeof(*rsa)) var flags uint32 - err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, rsa, &rsan, &o.o, nil) + err = syscall.WSARecvFrom(fd.Sysfd, newWsaBuf(buf), 1, &qty, &flags, rsa, &rsan, &o.o, nil) return qty, err }) err = fd.eofError(n, err) @@ -803,6 +825,9 @@ 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) @@ -816,10 +841,8 @@ func (fd *FD) Write(buf []byte) (int, error) { case kindConsole: n, err = fd.writeConsole(b) case kindPipe, kindFile: - o := &fd.wop - o.InitBuf(b) - n, err = fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.WriteFile(fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &qty, fd.overlapped(o)) + 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 }) fd.addOffset(n) @@ -827,10 +850,8 @@ func (fd *FD) Write(buf []byte) (int, error) { if race.Enabled { race.ReleaseMerge(unsafe.Pointer(&ioSync)) } - o := &fd.wop - o.InitBuf(b) - n, err = fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.WSASend(fd.Sysfd, &o.buf, 1, &qty, 0, &o.o, nil) + 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 }) } @@ -899,6 +920,10 @@ 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 { @@ -922,12 +947,9 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) { if max-ntotal > maxRW { max = ntotal + maxRW } - b := buf[ntotal:max] - o := &fd.wop - o.InitBuf(b) fd.setOffset(off + int64(ntotal)) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.WriteFile(fd.Sysfd, unsafe.Slice(o.buf.Buf, o.buf.Len), &qty, &o.o) + 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 }) if n > 0 { @@ -956,7 +978,7 @@ func (fd *FD) Writev(buf *[][]byte) (int64, error) { } bufs := newWSABufs(buf) defer freeWSABufs(bufs) - n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err 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 }) @@ -974,25 +996,23 @@ func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { if len(buf) == 0 { // handle zero-byte payload - o := &fd.wop - o.InitBuf(buf) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.WSASendto(fd.Sysfd, &o.buf, 1, &qty, 0, sa, &o.o, nil) + 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 }) return n, err } + fd.pin('w', &buf[0]) + ntotal := 0 for len(buf) > 0 { b := buf if len(b) > maxRW { b = b[:maxRW] } - o := &fd.wop - o.InitBuf(b) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = syscall.WSASendto(fd.Sysfd, &o.buf, 1, &qty, 0, sa, &o.o, nil) + 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 }) ntotal += int(n) @@ -1013,25 +1033,23 @@ func (fd *FD) WriteToInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error) if len(buf) == 0 { // handle zero-byte payload - o := &fd.wop - o.InitBuf(buf) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = windows.WSASendtoInet4(fd.Sysfd, &o.buf, 1, &qty, 0, sa4, &o.o, nil) + 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 }) return n, err } + fd.pin('w', &buf[0]) + ntotal := 0 for len(buf) > 0 { b := buf if len(b) > maxRW { b = b[:maxRW] } - o := &fd.wop - o.InitBuf(b) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = windows.WSASendtoInet4(fd.Sysfd, &o.buf, 1, &qty, 0, sa4, &o.o, nil) + 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 }) ntotal += int(n) @@ -1052,25 +1070,23 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) if len(buf) == 0 { // handle zero-byte payload - o := &fd.wop - o.InitBuf(buf) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = windows.WSASendtoInet6(fd.Sysfd, &o.buf, 1, &qty, 0, sa6, &o.o, nil) + 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 }) return n, err } + fd.pin('w', &buf[0]) + ntotal := 0 for len(buf) > 0 { b := buf if len(b) > maxRW { b = b[:maxRW] } - o := &fd.wop - o.InitBuf(b) - n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { - err = windows.WSASendtoInet6(fd.Sysfd, &o.buf, 1, &qty, 0, sa6, &o.o, nil) + 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 }) ntotal += int(n) @@ -1086,17 +1102,16 @@ func (fd *FD) WriteToInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error) // called when the descriptor is first created. This is here rather // than in the net package so that it can use fd.wop. func (fd *FD) ConnectEx(ra syscall.Sockaddr) error { - o := &fd.wop - _, err := fd.execIO(o, func(o *operation) (uint32, error) { + _, err := fd.execIO('w', func(o *operation) (uint32, error) { return 0, ConnectExFunc(fd.Sysfd, ra, nil, 0, nil, &o.o) }) return err } -func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) { +func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny) (string, error) { // Submit accept request. rsan := uint32(unsafe.Sizeof(rawsa[0])) - _, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { + _, err := fd.execIO('r', func(o *operation) (qty uint32, err error) { err = AcceptFunc(fd.Sysfd, s, (*byte)(unsafe.Pointer(&rawsa[0])), 0, rsan, rsan, &qty, &o.o) return qty, err @@ -1124,7 +1139,6 @@ func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, } defer fd.readUnlock() - o := &fd.rop var rawsa [2]syscall.RawSockaddrAny for { s, err := sysSocket() @@ -1132,7 +1146,7 @@ func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, return syscall.InvalidHandle, nil, 0, "", err } - errcall, err := fd.acceptOne(s, rawsa[:], o) + errcall, err := fd.acceptOne(s, rawsa[:]) if err == nil { return s, rawsa[:], uint32(unsafe.Sizeof(rawsa[0])), "", nil } @@ -1165,11 +1179,29 @@ func (fd *FD) Seek(offset int64, whence int) (int64, error) { } defer fd.readWriteUnlock() - if !fd.isBlocking && whence == io.SeekCurrent { - // Windows doesn't keep the file pointer for overlapped file handles. - // We do it ourselves in case to account for any read or write - // operations that may have occurred. - offset += fd.offset + if !fd.isBlocking { + // Windows doesn't use the file pointer for overlapped file handles, + // there is no point on calling syscall.Seek. + var newOffset int64 + switch whence { + case io.SeekStart: + newOffset = offset + case io.SeekCurrent: + newOffset = fd.offset + offset + case io.SeekEnd: + var size int64 + if err := windows.GetFileSizeEx(fd.Sysfd, &size); err != nil { + return 0, err + } + newOffset = size + offset + default: + return 0, windows.ERROR_INVALID_PARAMETER + } + if newOffset < 0 { + return 0, windows.ERROR_NEGATIVE_SEEK + } + fd.setOffset(newOffset) + return newOffset, nil } n, err := syscall.Seek(fd.Sysfd, offset, whence) fd.setOffset(n) @@ -1242,14 +1274,12 @@ func (fd *FD) RawRead(f func(uintptr) bool) error { // Use a zero-byte read as a way to get notified when this // socket is readable. h/t https://stackoverflow.com/a/42019668/332798 - o := &fd.rop - o.InitBuf(nil) - _, err := fd.execIO(o, func(o *operation) (qty uint32, err error) { + _, err := fd.execIO('r', func(o *operation) (qty uint32, err error) { var flags uint32 if !fd.IsStream { flags |= windows.MSG_PEEK } - err = syscall.WSARecv(fd.Sysfd, &o.buf, 1, &qty, &flags, &o.o, nil) + err = syscall.WSARecv(fd.Sysfd, &syscall.WSABuf{}, 1, &qty, &flags, &o.o, nil) return qty, err }) if err == windows.WSAEMSGSIZE { @@ -1337,18 +1367,16 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S p = p[:maxRW] } - rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny) - defer wsaRsaPool.Put(rsa) - msg := newWSAMsg(p, oob, flags, rsa) + msg := newWSAMsg(p, oob, flags, true) defer freeWSAMsg(msg) - n, err := fd.execIO(&fd.rop, func(o *operation) (qty uint32, err error) { + 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 }) err = fd.eofError(n, err) var sa syscall.Sockaddr if err == nil { - sa, err = rsa.Sockaddr() + sa, err = msg.Name.Sockaddr() } return n, int(msg.Control.Len), int(msg.Flags), sa, err } @@ -1364,17 +1392,15 @@ func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.Sockadd p = p[:maxRW] } - rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny) - defer wsaRsaPool.Put(rsa) - msg := newWSAMsg(p, oob, flags, rsa) + msg := newWSAMsg(p, oob, flags, true) defer freeWSAMsg(msg) - n, err := fd.execIO(&fd.rop, func(o *operation) (qty uint32, err error) { + 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 }) err = fd.eofError(n, err) if err == nil { - rawToSockaddrInet4(rsa, sa4) + rawToSockaddrInet4(msg.Name, sa4) } return n, int(msg.Control.Len), int(msg.Flags), err } @@ -1390,17 +1416,15 @@ func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.Sockadd p = p[:maxRW] } - rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny) - defer wsaRsaPool.Put(rsa) - msg := newWSAMsg(p, oob, flags, rsa) + msg := newWSAMsg(p, oob, flags, true) defer freeWSAMsg(msg) - n, err := fd.execIO(&fd.rop, func(o *operation) (qty uint32, err error) { + 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 }) err = fd.eofError(n, err) if err == nil { - rawToSockaddrInet6(rsa, sa6) + rawToSockaddrInet6(msg.Name, sa6) } return n, int(msg.Control.Len), int(msg.Flags), err } @@ -1416,21 +1440,16 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err } defer fd.writeUnlock() - var rsa *syscall.RawSockaddrAny - if sa != nil { - rsa = wsaRsaPool.Get().(*syscall.RawSockaddrAny) - defer wsaRsaPool.Put(rsa) - } - msg := newWSAMsg(p, oob, 0, rsa) + msg := newWSAMsg(p, oob, 0, sa != nil) defer freeWSAMsg(msg) if sa != nil { var err error - msg.Namelen, err = sockaddrToRaw(rsa, sa) + msg.Namelen, err = sockaddrToRaw(msg.Name, sa) if err != nil { return 0, 0, err } } - n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) { + 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 }) @@ -1448,17 +1467,12 @@ func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (in } defer fd.writeUnlock() - var rsa *syscall.RawSockaddrAny - if sa != nil { - rsa = wsaRsaPool.Get().(*syscall.RawSockaddrAny) - defer wsaRsaPool.Put(rsa) - } - msg := newWSAMsg(p, oob, 0, rsa) + msg := newWSAMsg(p, oob, 0, sa != nil) defer freeWSAMsg(msg) if sa != nil { - msg.Namelen = sockaddrInet4ToRaw(rsa, sa) + msg.Namelen = sockaddrInet4ToRaw(msg.Name, sa) } - n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) { + 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 }) @@ -1476,17 +1490,12 @@ func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (in } defer fd.writeUnlock() - var rsa *syscall.RawSockaddrAny - if sa != nil { - rsa = wsaRsaPool.Get().(*syscall.RawSockaddrAny) - defer wsaRsaPool.Put(rsa) - } - msg := newWSAMsg(p, oob, 0, rsa) + msg := newWSAMsg(p, oob, 0, sa != nil) defer freeWSAMsg(msg) if sa != nil { - msg.Namelen = sockaddrInet6ToRaw(rsa, sa) + msg.Namelen = sockaddrInet6ToRaw(msg.Name, sa) } - n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) { + 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 }) diff --git a/src/internal/poll/sendfile_windows.go b/src/internal/poll/sendfile_windows.go index a052f4a1f8..2bdfecf013 100644 --- a/src/internal/poll/sendfile_windows.go +++ b/src/internal/poll/sendfile_windows.go @@ -62,18 +62,14 @@ func SendFile(fd *FD, src uintptr, size int64) (written int64, err error, handle // See https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-transmitfile const maxChunkSizePerCall = int64(0x7fffffff - 1) - o := &fd.wop for size > 0 { chunkSize := maxChunkSizePerCall if chunkSize > size { chunkSize = size } - off := startpos + written - o.o.Offset = uint32(off) - o.o.OffsetHigh = uint32(off >> 32) - - n, err := fd.execIO(o, func(o *operation) (uint32, error) { + fd.setOffset(startpos + written) + n, err := fd.execIO('w', func(o *operation) (uint32, error) { err := syscall.TransmitFile(fd.Sysfd, hsrc, uint32(chunkSize), 0, &o.o, nil, syscall.TF_WRITE_BEHIND) if err != nil { return 0, err diff --git a/src/internal/runtime/gc/scan.go b/src/internal/runtime/gc/scan.go index 066a32151a..863a4bf0f3 100644 --- a/src/internal/runtime/gc/scan.go +++ b/src/internal/runtime/gc/scan.go @@ -8,7 +8,7 @@ import "internal/goarch" // ObjMask is a bitmap where each bit corresponds to an object in a span. // -// It is sized to accomodate all size classes. +// It is sized to accommodate all size classes. type ObjMask [MaxObjsPerSpan / (goarch.PtrSize * 8)]uintptr // PtrMask is a bitmap where each bit represents a pointer-word in a single runtime page. diff --git a/src/internal/runtime/gc/scan/expand_reference.go b/src/internal/runtime/gc/scan/expand_reference.go index 45446528d7..dd23f4fc10 100644 --- a/src/internal/runtime/gc/scan/expand_reference.go +++ b/src/internal/runtime/gc/scan/expand_reference.go @@ -16,7 +16,7 @@ func ExpandReference(sizeClass int, packed *gc.ObjMask, unpacked *gc.PtrMask) { // Look up the size and derive the number of objects in a span. // We're only concerned with small objects in single-page spans, // and gc.PtrMask enforces this by being statically sized to - // accomodate only such spans. + // accommodate only such spans. size := uintptr(gc.SizeClassToSize[sizeClass]) nObj := uintptr(gc.SizeClassToNPages[sizeClass]) * gc.PageSize / size diff --git a/src/internal/syscall/windows/syscall_windows.go b/src/internal/syscall/windows/syscall_windows.go index 905cabc81e..fb3b66540f 100644 --- a/src/internal/syscall/windows/syscall_windows.go +++ b/src/internal/syscall/windows/syscall_windows.go @@ -39,6 +39,7 @@ const ( ERROR_NOT_SUPPORTED syscall.Errno = 50 ERROR_CALL_NOT_IMPLEMENTED syscall.Errno = 120 ERROR_INVALID_NAME syscall.Errno = 123 + ERROR_NEGATIVE_SEEK syscall.Errno = 131 ERROR_LOCK_FAILED syscall.Errno = 167 ERROR_IO_INCOMPLETE syscall.Errno = 996 ERROR_NO_TOKEN syscall.Errno = 1008 @@ -195,6 +196,7 @@ const ( //sys SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf unsafe.Pointer, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle //sys VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery //sys GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W +//sys GetFileSizeEx(handle syscall.Handle, size *int64) (err error) = kernel32.GetFileSizeEx const ( // flags for CreateToolhelp32Snapshot @@ -259,7 +261,7 @@ var sendRecvMsgFunc struct { } type WSAMsg struct { - Name syscall.Pointer + Name *syscall.RawSockaddrAny Namelen int32 Buffers *syscall.WSABuf BufferCount uint32 diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index 53f456c5cf..70c4d76dff 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -73,6 +73,7 @@ var ( procGetConsoleCP = modkernel32.NewProc("GetConsoleCP") procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetFileSizeEx = modkernel32.NewProc("GetFileSizeEx") procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") procGetModuleHandleW = modkernel32.NewProc("GetModuleHandleW") @@ -326,6 +327,14 @@ func GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byt return } +func GetFileSizeEx(handle syscall.Handle, size *int64) (err error) { + r1, _, e1 := syscall.SyscallN(procGetFileSizeEx.Addr(), uintptr(handle), uintptr(unsafe.Pointer(size))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { r0, _, e1 := syscall.SyscallN(procGetFinalPathNameByHandleW.Addr(), uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags)) n = uint32(r0) |
