libgo: update to Go1.10beta1
[official-gcc.git] / libgo / go / runtime / netpoll_windows.go
blob134071f5e3ca178728d8ec9314c98f1509872552
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 "unsafe"
11 const _DWORD_MAX = 0xffffffff
13 const _INVALID_HANDLE_VALUE = ^uintptr(0)
15 // net_op must be the same as beginning of internal/poll.operation.
16 // Keep these in sync.
17 type net_op struct {
18 // used by windows
19 o overlapped
20 // used by netpoll
21 pd *pollDesc
22 mode int32
23 errno int32
24 qty uint32
27 type overlappedEntry struct {
28 key uintptr
29 op *net_op // In reality it's *overlapped, but we cast it to *net_op anyway.
30 internal uintptr
31 qty uint32
34 var iocphandle uintptr = _INVALID_HANDLE_VALUE // completion port io handle
36 func netpollinit() {
37 iocphandle = stdcall4(_CreateIoCompletionPort, _INVALID_HANDLE_VALUE, 0, 0, _DWORD_MAX)
38 if iocphandle == 0 {
39 println("runtime: CreateIoCompletionPort failed (errno=", getlasterror(), ")")
40 throw("runtime: netpollinit failed")
44 func netpolldescriptor() uintptr {
45 return iocphandle
48 func netpollopen(fd uintptr, pd *pollDesc) int32 {
49 if stdcall4(_CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0 {
50 return int32(getlasterror())
52 return 0
55 func netpollclose(fd uintptr) int32 {
56 // nothing to do
57 return 0
60 func netpollarm(pd *pollDesc, mode int) {
61 throw("runtime: unused")
64 // Polls for completed network IO.
65 // Returns list of goroutines that become runnable.
66 func netpoll(block bool) *g {
67 var entries [64]overlappedEntry
68 var wait, qty, key, flags, n, i uint32
69 var errno int32
70 var op *net_op
71 var gp guintptr
73 mp := getg().m
75 if iocphandle == _INVALID_HANDLE_VALUE {
76 return nil
78 wait = 0
79 if block {
80 wait = _INFINITE
82 retry:
83 if _GetQueuedCompletionStatusEx != nil {
84 n = uint32(len(entries) / int(gomaxprocs))
85 if n < 8 {
86 n = 8
88 if block {
89 mp.blocked = true
91 if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
92 mp.blocked = false
93 errno = int32(getlasterror())
94 if !block && errno == _WAIT_TIMEOUT {
95 return nil
97 println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
98 throw("runtime: netpoll failed")
100 mp.blocked = false
101 for i = 0; i < n; i++ {
102 op = entries[i].op
103 errno = 0
104 qty = 0
105 if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
106 errno = int32(getlasterror())
108 handlecompletion(&gp, op, errno, qty)
110 } else {
111 op = nil
112 errno = 0
113 qty = 0
114 if block {
115 mp.blocked = true
117 if stdcall5(_GetQueuedCompletionStatus, iocphandle, uintptr(unsafe.Pointer(&qty)), uintptr(unsafe.Pointer(&key)), uintptr(unsafe.Pointer(&op)), uintptr(wait)) == 0 {
118 mp.blocked = false
119 errno = int32(getlasterror())
120 if !block && errno == _WAIT_TIMEOUT {
121 return nil
123 if op == nil {
124 println("runtime: GetQueuedCompletionStatus failed (errno=", errno, ")")
125 throw("runtime: netpoll failed")
127 // dequeued failed IO packet, so report that
129 mp.blocked = false
130 handlecompletion(&gp, op, errno, qty)
132 if block && gp == 0 {
133 goto retry
135 return gp.ptr()
138 func handlecompletion(gpp *guintptr, op *net_op, errno int32, qty uint32) {
139 if op == nil {
140 println("runtime: GetQueuedCompletionStatus returned op == nil")
141 throw("runtime: netpoll failed")
143 mode := op.mode
144 if mode != 'r' && mode != 'w' {
145 println("runtime: GetQueuedCompletionStatus returned invalid mode=", mode)
146 throw("runtime: netpoll failed")
148 op.errno = errno
149 op.qty = qty
150 netpollready(gpp, op.pd, mode)