1
0
mirror of https://github.com/golang/go synced 2024-11-17 06:54:48 -07:00

runtime: always use GetQueuedCompletionStatusEx on Windows

We used to fall back to GetQueuedCompletionStatus if
GetQueuedCompletionStatus was not available, but as of Go 1.11 we
require Windows 7 or later, so GetQueuedCompletionStatusEx is always
available.

Fixes #37957

Change-Id: I7d8d49a92ab7b1f5afdc54a442f696aaf4a5168e
Reviewed-on: https://go-review.googlesource.com/c/go/+/225059
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
This commit is contained in:
Ian Lance Taylor 2020-03-23 20:42:29 -07:00
parent 355f53f0a0
commit e3cf0525b0
2 changed files with 28 additions and 65 deletions

View File

@ -75,7 +75,7 @@ func netpollBreak() {
// delay > 0: block for up to that many nanoseconds
func netpoll(delay int64) gList {
var entries [64]overlappedEntry
var wait, qty, key, flags, n, i uint32
var wait, qty, flags, n, i uint32
var errno int32
var op *net_op
var toRun gList
@ -99,82 +99,47 @@ func netpoll(delay int64) gList {
wait = 1e9
}
if _GetQueuedCompletionStatusEx != nil {
n = uint32(len(entries) / int(gomaxprocs))
if n < 8 {
n = 8
}
if delay != 0 {
mp.blocked = true
}
if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
mp.blocked = false
errno = int32(getlasterror())
if errno == _WAIT_TIMEOUT {
return gList{}
}
println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
throw("runtime: netpoll failed")
}
n = uint32(len(entries) / int(gomaxprocs))
if n < 8 {
n = 8
}
if delay != 0 {
mp.blocked = true
}
if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
mp.blocked = false
for i = 0; i < n; i++ {
op = entries[i].op
if op != nil {
errno = 0
qty = 0
if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
errno = int32(getlasterror())
}
handlecompletion(&toRun, op, errno, qty)
} else {
if delay == 0 {
// Forward the notification to the
// blocked poller.
netpollBreak()
}
}
errno = int32(getlasterror())
if errno == _WAIT_TIMEOUT {
return gList{}
}
} else {
op = nil
errno = 0
qty = 0
if delay != 0 {
mp.blocked = true
}
if stdcall5(_GetQueuedCompletionStatus, iocphandle, uintptr(unsafe.Pointer(&qty)), uintptr(unsafe.Pointer(&key)), uintptr(unsafe.Pointer(&op)), uintptr(wait)) == 0 {
mp.blocked = false
errno = int32(getlasterror())
if errno == _WAIT_TIMEOUT {
return gList{}
println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
throw("runtime: netpoll failed")
}
mp.blocked = false
for i = 0; i < n; i++ {
op = entries[i].op
if op != nil {
errno = 0
qty = 0
if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
errno = int32(getlasterror())
}
if op == nil {
println("runtime: GetQueuedCompletionStatus failed (errno=", errno, ")")
throw("runtime: netpoll failed")
}
// dequeued failed IO packet, so report that
}
mp.blocked = false
if op == nil {
handlecompletion(&toRun, op, errno, qty)
} else {
if delay == 0 {
// Forward the notification to the
// blocked poller.
netpollBreak()
}
return gList{}
}
handlecompletion(&toRun, op, errno, qty)
}
return toRun
}
func handlecompletion(toRun *gList, op *net_op, errno int32, qty uint32) {
if op == nil {
println("runtime: GetQueuedCompletionStatus returned op == nil")
throw("runtime: netpoll failed")
}
mode := op.mode
if mode != 'r' && mode != 'w' {
println("runtime: GetQueuedCompletionStatus returned invalid mode=", mode)
println("runtime: GetQueuedCompletionStatusEx returned invalid mode=", mode)
throw("runtime: netpoll failed")
}
op.errno = errno

View File

@ -28,7 +28,7 @@ const (
//go:cgo_import_dynamic runtime._GetEnvironmentStringsW GetEnvironmentStringsW%0 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetProcAddress GetProcAddress%2 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetProcessAffinityMask GetProcessAffinityMask%3 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetQueuedCompletionStatus GetQueuedCompletionStatus%5 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetQueuedCompletionStatusEx GetQueuedCompletionStatusEx%6 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetStdHandle GetStdHandle%1 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetSystemDirectoryA GetSystemDirectoryA%2 "kernel32.dll"
//go:cgo_import_dynamic runtime._GetSystemInfo GetSystemInfo%1 "kernel32.dll"
@ -75,7 +75,7 @@ var (
_GetEnvironmentStringsW,
_GetProcAddress,
_GetProcessAffinityMask,
_GetQueuedCompletionStatus,
_GetQueuedCompletionStatusEx,
_GetStdHandle,
_GetSystemDirectoryA,
_GetSystemInfo,
@ -111,7 +111,6 @@ var (
// We will load syscalls, if available, before using them.
_AddDllDirectory,
_AddVectoredContinueHandler,
_GetQueuedCompletionStatusEx,
_LoadLibraryExA,
_LoadLibraryExW,
_ stdFunction
@ -239,7 +238,6 @@ func loadOptionalSyscalls() {
}
_AddDllDirectory = windowsFindfunc(k32, []byte("AddDllDirectory\000"))
_AddVectoredContinueHandler = windowsFindfunc(k32, []byte("AddVectoredContinueHandler\000"))
_GetQueuedCompletionStatusEx = windowsFindfunc(k32, []byte("GetQueuedCompletionStatusEx\000"))
_LoadLibraryExA = windowsFindfunc(k32, []byte("LoadLibraryExA\000"))
_LoadLibraryExW = windowsFindfunc(k32, []byte("LoadLibraryExW\000"))
useLoadLibraryEx = (_LoadLibraryExW != nil && _LoadLibraryExA != nil && _AddDllDirectory != nil)