]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: always use GetQueuedCompletionStatusEx on Windows
authorIan Lance Taylor <iant@golang.org>
Tue, 24 Mar 2020 03:42:29 +0000 (20:42 -0700)
committerIan Lance Taylor <iant@golang.org>
Tue, 24 Mar 2020 19:57:49 +0000 (19:57 +0000)
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>
src/runtime/netpoll_windows.go
src/runtime/os_windows.go

index ced52cbd3a3aa9c76bd1806294209c5709f073f3..28b2f6ef3b1780c5ca5b6f1334b539682c57045b 100644 (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()
-                               }
-                       }
-               }
-       } else {
-               op = nil
-               errno = 0
-               qty = 0
-               if delay != 0 {
-                       mp.blocked = true
+               errno = int32(getlasterror())
+               if errno == _WAIT_TIMEOUT {
+                       return gList{}
                }
-               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{}
-                       }
-                       if op == nil {
-                               println("runtime: GetQueuedCompletionStatus failed (errno=", errno, ")")
-                               throw("runtime: netpoll failed")
+               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())
                        }
-                       // 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
index 26da169be86c25e62e8dc55d152eaea11bb93a5a..1298a140179b83dea599f8e6fea621d42fb9350f 100644 (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)