rust: Do not link with libdl and libpthread unconditionally
[official-gcc.git] / libgo / go / runtime / netpoll_windows.go
blob4c1cd2633a86ba1bbdb99b25d27446df2e800b33
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package runtime
7 import (
8 "runtime/internal/atomic"
9 "unsafe"
12 const _DWORD_MAX = 0xffffffff
14 const _INVALID_HANDLE_VALUE = ^uintptr(0)
16 // net_op must be the same as beginning of internal/poll.operation.
17 // Keep these in sync.
18 type net_op struct {
19 // used by windows
20 o overlapped
21 // used by netpoll
22 pd *pollDesc
23 mode int32
24 errno int32
25 qty uint32
28 type overlappedEntry struct {
29 key uintptr
30 op *net_op // In reality it's *overlapped, but we cast it to *net_op anyway.
31 internal uintptr
32 qty uint32
35 var (
36 iocphandle uintptr = _INVALID_HANDLE_VALUE // completion port io handle
38 netpollWakeSig uint32 // used to avoid duplicate calls of netpollBreak
41 func netpollinit() {
42 iocphandle = stdcall4(_CreateIoCompletionPort, _INVALID_HANDLE_VALUE, 0, 0, _DWORD_MAX)
43 if iocphandle == 0 {
44 println("runtime: CreateIoCompletionPort failed (errno=", getlasterror(), ")")
45 throw("runtime: netpollinit failed")
49 func netpollIsPollDescriptor(fd uintptr) bool {
50 return fd == iocphandle
53 func netpollopen(fd uintptr, pd *pollDesc) int32 {
54 if stdcall4(_CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0 {
55 return int32(getlasterror())
57 return 0
60 func netpollclose(fd uintptr) int32 {
61 // nothing to do
62 return 0
65 func netpollarm(pd *pollDesc, mode int) {
66 throw("runtime: unused")
69 func netpollBreak() {
70 if atomic.Cas(&netpollWakeSig, 0, 1) {
71 if stdcall4(_PostQueuedCompletionStatus, iocphandle, 0, 0, 0) == 0 {
72 println("runtime: netpoll: PostQueuedCompletionStatus failed (errno=", getlasterror(), ")")
73 throw("runtime: netpoll: PostQueuedCompletionStatus failed")
78 // netpoll checks for ready network connections.
79 // Returns list of goroutines that become runnable.
80 // delay < 0: blocks indefinitely
81 // delay == 0: does not block, just polls
82 // delay > 0: block for up to that many nanoseconds
83 func netpoll(delay int64) gList {
84 var entries [64]overlappedEntry
85 var wait, qty, flags, n, i uint32
86 var errno int32
87 var op *net_op
88 var toRun gList
90 mp := getg().m
92 if iocphandle == _INVALID_HANDLE_VALUE {
93 return gList{}
95 if delay < 0 {
96 wait = _INFINITE
97 } else if delay == 0 {
98 wait = 0
99 } else if delay < 1e6 {
100 wait = 1
101 } else if delay < 1e15 {
102 wait = uint32(delay / 1e6)
103 } else {
104 // An arbitrary cap on how long to wait for a timer.
105 // 1e9 ms == ~11.5 days.
106 wait = 1e9
109 n = uint32(len(entries) / int(gomaxprocs))
110 if n < 8 {
111 n = 8
113 if delay != 0 {
114 mp.blocked = true
116 if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
117 mp.blocked = false
118 errno = int32(getlasterror())
119 if errno == _WAIT_TIMEOUT {
120 return gList{}
122 println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
123 throw("runtime: netpoll failed")
125 mp.blocked = false
126 for i = 0; i < n; i++ {
127 op = entries[i].op
128 if op != nil {
129 errno = 0
130 qty = 0
131 if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
132 errno = int32(getlasterror())
134 handlecompletion(&toRun, op, errno, qty)
135 } else {
136 atomic.Store(&netpollWakeSig, 0)
137 if delay == 0 {
138 // Forward the notification to the
139 // blocked poller.
140 netpollBreak()
144 return toRun
147 func handlecompletion(toRun *gList, op *net_op, errno int32, qty uint32) {
148 mode := op.mode
149 if mode != 'r' && mode != 'w' {
150 println("runtime: GetQueuedCompletionStatusEx returned invalid mode=", mode)
151 throw("runtime: netpoll failed")
153 op.errno = errno
154 op.qty = qty
155 netpollready(toRun, op.pd, mode)