diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-04-02 20:27:35 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2019-10-15 20:29:56 +0000 |
commit | 831e3cfaa594ceb70c3cbeff2d31fddcd9a25a5e (patch) | |
tree | 6a5203ae8e7b24bce6e2c76986aecf17e039e4a7 /src/runtime/netpoll_windows.go | |
parent | 6da300b196df5fc3b33dd3bc87c477d46473abde (diff) | |
download | go-831e3cfaa594ceb70c3cbeff2d31fddcd9a25a5e.tar.gz go-831e3cfaa594ceb70c3cbeff2d31fddcd9a25a5e.zip |
runtime: change netpoll to take an amount of time to block
This new facility will be used by future CLs in this series.
Change the only blocking call to netpoll to do the right thing when
netpoll returns an empty list.
Updates #6239
Updates #27707
Change-Id: I58b3c2903eda61a3698b1a4729ed0e81382bb1ed
Reviewed-on: https://go-review.googlesource.com/c/go/+/171821
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Diffstat (limited to 'src/runtime/netpoll_windows.go')
-rw-r--r-- | src/runtime/netpoll_windows.go | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/src/runtime/netpoll_windows.go b/src/runtime/netpoll_windows.go index 07ef15ce2f..fde413677a 100644 --- a/src/runtime/netpoll_windows.go +++ b/src/runtime/netpoll_windows.go @@ -61,9 +61,12 @@ func netpollarm(pd *pollDesc, mode int) { throw("runtime: unused") } -// Polls for completed network IO. +// netpoll checks for ready network connections. // Returns list of goroutines that become runnable. -func netpoll(block bool) gList { +// delay < 0: blocks indefinitely +// delay == 0: does not block, just polls +// 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 errno int32 @@ -75,23 +78,32 @@ func netpoll(block bool) gList { if iocphandle == _INVALID_HANDLE_VALUE { return gList{} } - wait = 0 - if block { + if delay < 0 { wait = _INFINITE + } else if delay == 0 { + wait = 0 + } else if delay < 1e6 { + wait = 1 + } else if delay < 1e15 { + wait = uint32(delay / 1e6) + } else { + // An arbitrary cap on how long to wait for a timer. + // 1e9 ms == ~11.5 days. + wait = 1e9 } -retry: + if _GetQueuedCompletionStatusEx != nil { n = uint32(len(entries) / int(gomaxprocs)) if n < 8 { n = 8 } - if block { + 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 !block && errno == _WAIT_TIMEOUT { + if errno == _WAIT_TIMEOUT { return gList{} } println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")") @@ -111,13 +123,13 @@ retry: op = nil errno = 0 qty = 0 - if block { + 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 !block && errno == _WAIT_TIMEOUT { + if errno == _WAIT_TIMEOUT { return gList{} } if op == nil { @@ -129,9 +141,6 @@ retry: mp.blocked = false handlecompletion(&toRun, op, errno, qty) } - if block && toRun.empty() { - goto retry - } return toRun } |