aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2025-10-03 10:11:20 -0400
committerCherry Mui <cherryyz@google.com>2025-10-03 10:11:21 -0400
commitfb1749a3fe6ac40c56127d8fcea2e8b13db820e8 (patch)
tree72dd38fc84286bf88311850a99e6becf2cbd99bf /src/internal
parent703a5fbaad81f1285776bf6f2900506d3c751ea1 (diff)
parentadce7f196e6ac6d22e9bc851efea5f3ab650947c (diff)
downloadgo-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.go30
-rw-r--r--src/internal/goexperiment/exp_goroutineleakprofile_off.go8
-rw-r--r--src/internal/goexperiment/exp_goroutineleakprofile_on.go8
-rw-r--r--src/internal/goexperiment/flags.go3
-rw-r--r--src/internal/poll/fd_windows.go343
-rw-r--r--src/internal/poll/sendfile_windows.go8
-rw-r--r--src/internal/runtime/gc/scan.go2
-rw-r--r--src/internal/runtime/gc/scan/expand_reference.go2
-rw-r--r--src/internal/syscall/windows/syscall_windows.go4
-rw-r--r--src/internal/syscall/windows/zsyscall_windows.go9
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)