github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/runtime/netpoll_windows.c (about) 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. 4 5 #include "runtime.h" 6 #include "defs_GOOS_GOARCH.h" 7 #include "os_GOOS.h" 8 9 #define DWORD_MAX 0xffffffff 10 11 #pragma dynimport runtime·CreateIoCompletionPort CreateIoCompletionPort "kernel32.dll" 12 #pragma dynimport runtime·GetQueuedCompletionStatus GetQueuedCompletionStatus "kernel32.dll" 13 #pragma dynimport runtime·WSAGetOverlappedResult WSAGetOverlappedResult "ws2_32.dll" 14 15 extern void *runtime·CreateIoCompletionPort; 16 extern void *runtime·GetQueuedCompletionStatus; 17 extern void *runtime·WSAGetOverlappedResult; 18 19 #define INVALID_HANDLE_VALUE ((uintptr)-1) 20 21 // net_op must be the same as beginning of net.operation. Keep these in sync. 22 typedef struct net_op net_op; 23 struct net_op 24 { 25 // used by windows 26 Overlapped o; 27 // used by netpoll 28 PollDesc* pd; 29 int32 mode; 30 int32 errno; 31 uint32 qty; 32 }; 33 34 typedef struct OverlappedEntry OverlappedEntry; 35 struct OverlappedEntry 36 { 37 uintptr key; 38 net_op* op; // In reality it's Overlapped*, but we cast it to net_op* anyway. 39 uintptr internal; 40 uint32 qty; 41 }; 42 43 static void handlecompletion(G **gpp, net_op *o, int32 errno, uint32 qty); 44 45 static uintptr iocphandle = INVALID_HANDLE_VALUE; // completion port io handle 46 47 void 48 runtime·netpollinit(void) 49 { 50 iocphandle = (uintptr)runtime·stdcall(runtime·CreateIoCompletionPort, 4, INVALID_HANDLE_VALUE, (uintptr)0, (uintptr)0, (uintptr)DWORD_MAX); 51 if(iocphandle == 0) { 52 runtime·printf("netpoll: failed to create iocp handle (errno=%d)\n", runtime·getlasterror()); 53 runtime·throw("netpoll: failed to create iocp handle"); 54 } 55 return; 56 } 57 58 int32 59 runtime·netpollopen(uintptr fd, PollDesc *pd) 60 { 61 USED(pd); 62 if(runtime·stdcall(runtime·CreateIoCompletionPort, 4, fd, iocphandle, (uintptr)0, (uintptr)0) == 0) 63 return -runtime·getlasterror(); 64 return 0; 65 } 66 67 int32 68 runtime·netpollclose(uintptr fd) 69 { 70 // nothing to do 71 USED(fd); 72 return 0; 73 } 74 75 // Polls for completed network IO. 76 // Returns list of goroutines that become runnable. 77 G* 78 runtime·netpoll(bool block) 79 { 80 OverlappedEntry entries[64]; 81 uint32 wait, qty, key, flags, n, i; 82 int32 errno; 83 net_op *op; 84 G *gp; 85 86 if(iocphandle == INVALID_HANDLE_VALUE) 87 return nil; 88 gp = nil; 89 wait = 0; 90 if(block) 91 wait = INFINITE; 92 retry: 93 if(runtime·GetQueuedCompletionStatusEx != nil) { 94 n = nelem(entries) / runtime·gomaxprocs; 95 if(n < 8) 96 n = 8; 97 if(runtime·stdcall(runtime·GetQueuedCompletionStatusEx, 6, iocphandle, entries, (uintptr)n, &n, (uintptr)wait, (uintptr)0) == 0) { 98 errno = runtime·getlasterror(); 99 if(!block && errno == WAIT_TIMEOUT) 100 return nil; 101 runtime·printf("netpoll: GetQueuedCompletionStatusEx failed (errno=%d)\n", errno); 102 runtime·throw("netpoll: GetQueuedCompletionStatusEx failed"); 103 } 104 for(i = 0; i < n; i++) { 105 op = entries[i].op; 106 errno = 0; 107 qty = 0; 108 if(runtime·stdcall(runtime·WSAGetOverlappedResult, 5, runtime·netpollfd(op->pd), op, &qty, (uintptr)0, (uintptr)&flags) == 0) 109 errno = runtime·getlasterror(); 110 handlecompletion(&gp, op, errno, qty); 111 } 112 } else { 113 op = nil; 114 errno = 0; 115 qty = 0; 116 if(runtime·stdcall(runtime·GetQueuedCompletionStatus, 5, iocphandle, &qty, &key, &op, (uintptr)wait) == 0) { 117 errno = runtime·getlasterror(); 118 if(!block && errno == WAIT_TIMEOUT) 119 return nil; 120 if(op == nil) { 121 runtime·printf("netpoll: GetQueuedCompletionStatus failed (errno=%d)\n", errno); 122 runtime·throw("netpoll: GetQueuedCompletionStatus failed"); 123 } 124 // dequeued failed IO packet, so report that 125 } 126 handlecompletion(&gp, op, errno, qty); 127 } 128 if(block && gp == nil) 129 goto retry; 130 return gp; 131 } 132 133 static void 134 handlecompletion(G **gpp, net_op *op, int32 errno, uint32 qty) 135 { 136 int32 mode; 137 138 if(op == nil) 139 runtime·throw("netpoll: GetQueuedCompletionStatus returned op == nil"); 140 mode = op->mode; 141 if(mode != 'r' && mode != 'w') { 142 runtime·printf("netpoll: GetQueuedCompletionStatus returned invalid mode=%d\n", mode); 143 runtime·throw("netpoll: GetQueuedCompletionStatus returned invalid mode"); 144 } 145 op->errno = errno; 146 op->qty = qty; 147 runtime·netpollready(gpp, op->pd, mode); 148 }