Merge from branches/gcc-4_8-branch up to rev 201477
[official-gcc.git] / gcc-4_8-branch / libgo / go / net / fd_windows.go
blobfefd174bafa0b7fd7083bc523ec784dd963083bb
1 // Copyright 2010 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 net
7 import (
8 "errors"
9 "io"
10 "os"
11 "runtime"
12 "sync"
13 "syscall"
14 "time"
15 "unsafe"
18 var initErr error
20 // CancelIo Windows API cancels all outstanding IO for a particular
21 // socket on current thread. To overcome that limitation, we run
22 // special goroutine, locked to OS single thread, that both starts
23 // and cancels IO. It means, there are 2 unavoidable thread switches
24 // for every IO.
25 // Some newer versions of Windows has new CancelIoEx API, that does
26 // not have that limitation and can be used from any thread. This
27 // package uses CancelIoEx API, if present, otherwise it fallback
28 // to CancelIo.
30 var canCancelIO bool // determines if CancelIoEx API is present
32 func sysInit() {
33 var d syscall.WSAData
34 e := syscall.WSAStartup(uint32(0x202), &d)
35 if e != nil {
36 initErr = os.NewSyscallError("WSAStartup", e)
38 canCancelIO = syscall.LoadCancelIoEx() == nil
39 if syscall.LoadGetAddrInfo() == nil {
40 lookupPort = newLookupPort
41 lookupIP = newLookupIP
45 func closesocket(s syscall.Handle) error {
46 return syscall.Closesocket(s)
49 func canUseConnectEx(net string) bool {
50 if net == "udp" || net == "udp4" || net == "udp6" {
51 // ConnectEx windows API does not support connectionless sockets.
52 return false
54 return syscall.LoadConnectEx() == nil
57 func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn, error) {
58 if !canUseConnectEx(net) {
59 // Use the relatively inefficient goroutine-racing
60 // implementation of DialTimeout.
61 return resolveAndDialChannel(net, addr, localAddr, deadline)
63 ra, err := resolveAddr("dial", net, addr, deadline)
64 if err != nil {
65 return nil, err
67 return dial(net, addr, localAddr, ra, deadline)
70 // Interface for all IO operations.
71 type anOpIface interface {
72 Op() *anOp
73 Name() string
74 Submit() error
77 // IO completion result parameters.
78 type ioResult struct {
79 qty uint32
80 err error
83 // anOp implements functionality common to all IO operations.
84 type anOp struct {
85 // Used by IOCP interface, it must be first field
86 // of the struct, as our code rely on it.
87 o syscall.Overlapped
89 resultc chan ioResult
90 errnoc chan error
91 fd *netFD
94 func (o *anOp) Init(fd *netFD, mode int) {
95 o.fd = fd
96 var i int
97 if mode == 'r' {
98 i = 0
99 } else {
100 i = 1
102 if fd.resultc[i] == nil {
103 fd.resultc[i] = make(chan ioResult, 1)
105 o.resultc = fd.resultc[i]
106 if fd.errnoc[i] == nil {
107 fd.errnoc[i] = make(chan error)
109 o.errnoc = fd.errnoc[i]
112 func (o *anOp) Op() *anOp {
113 return o
116 // bufOp is used by IO operations that read / write
117 // data from / to client buffer.
118 type bufOp struct {
119 anOp
120 buf syscall.WSABuf
123 func (o *bufOp) Init(fd *netFD, buf []byte, mode int) {
124 o.anOp.Init(fd, mode)
125 o.buf.Len = uint32(len(buf))
126 if len(buf) == 0 {
127 o.buf.Buf = nil
128 } else {
129 o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0]))
133 // resultSrv will retrieve all IO completion results from
134 // iocp and send them to the correspondent waiting client
135 // goroutine via channel supplied in the request.
136 type resultSrv struct {
137 iocp syscall.Handle
140 func runtime_blockingSyscallHint()
142 func (s *resultSrv) Run() {
143 var o *syscall.Overlapped
144 var key uint32
145 var r ioResult
146 for {
147 r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, 0)
148 if r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil {
149 runtime_blockingSyscallHint()
150 r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
152 switch {
153 case r.err == nil:
154 // Dequeued successfully completed IO packet.
155 case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil:
156 // Wait has timed out (should not happen now, but might be used in the future).
157 panic("GetQueuedCompletionStatus timed out")
158 case o == nil:
159 // Failed to dequeue anything -> report the error.
160 panic("GetQueuedCompletionStatus failed " + r.err.Error())
161 default:
162 // Dequeued failed IO packet.
164 (*anOp)(unsafe.Pointer(o)).resultc <- r
168 // ioSrv executes net IO requests.
169 type ioSrv struct {
170 submchan chan anOpIface // submit IO requests
171 canchan chan anOpIface // cancel IO requests
174 // ProcessRemoteIO will execute submit IO requests on behalf
175 // of other goroutines, all on a single os thread, so it can
176 // cancel them later. Results of all operations will be sent
177 // back to their requesters via channel supplied in request.
178 // It is used only when the CancelIoEx API is unavailable.
179 func (s *ioSrv) ProcessRemoteIO() {
180 runtime.LockOSThread()
181 defer runtime.UnlockOSThread()
182 for {
183 select {
184 case o := <-s.submchan:
185 o.Op().errnoc <- o.Submit()
186 case o := <-s.canchan:
187 o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().fd.sysfd))
192 // ExecIO executes a single IO operation oi. It submits and cancels
193 // IO in the current thread for systems where Windows CancelIoEx API
194 // is available. Alternatively, it passes the request onto
195 // a special goroutine and waits for completion or cancels request.
196 // deadline is unix nanos.
197 func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) {
198 var err error
199 o := oi.Op()
200 // Calculate timeout delta.
201 var delta int64
202 if deadline != 0 {
203 delta = deadline - time.Now().UnixNano()
204 if delta <= 0 {
205 return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, errTimeout}
208 // Start IO.
209 if canCancelIO {
210 err = oi.Submit()
211 } else {
212 // Send request to a special dedicated thread,
213 // so it can stop the IO with CancelIO later.
214 s.submchan <- oi
215 err = <-o.errnoc
217 switch err {
218 case nil:
219 // IO completed immediately, but we need to get our completion message anyway.
220 case syscall.ERROR_IO_PENDING:
221 // IO started, and we have to wait for its completion.
222 err = nil
223 default:
224 return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err}
226 // Setup timer, if deadline is given.
227 var timer <-chan time.Time
228 if delta > 0 {
229 t := time.NewTimer(time.Duration(delta) * time.Nanosecond)
230 defer t.Stop()
231 timer = t.C
233 // Wait for our request to complete.
234 var r ioResult
235 var cancelled, timeout bool
236 select {
237 case r = <-o.resultc:
238 case <-timer:
239 cancelled = true
240 timeout = true
241 case <-o.fd.closec:
242 cancelled = true
244 if cancelled {
245 // Cancel it.
246 if canCancelIO {
247 err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o)
248 // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
249 if err != nil && err != syscall.ERROR_NOT_FOUND {
250 // TODO(brainman): maybe do something else, but panic.
251 panic(err)
253 } else {
254 s.canchan <- oi
255 <-o.errnoc
257 // Wait for IO to be canceled or complete successfully.
258 r = <-o.resultc
259 if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
260 if timeout {
261 r.err = errTimeout
262 } else {
263 r.err = errClosing
267 if r.err != nil {
268 err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err}
270 return int(r.qty), err
273 // Start helper goroutines.
274 var resultsrv *resultSrv
275 var iosrv *ioSrv
276 var onceStartServer sync.Once
278 func startServer() {
279 resultsrv = new(resultSrv)
280 var err error
281 resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
282 if err != nil {
283 panic("CreateIoCompletionPort: " + err.Error())
285 go resultsrv.Run()
287 iosrv = new(ioSrv)
288 if !canCancelIO {
289 // Only CancelIo API is available. Lets start special goroutine
290 // locked to an OS thread, that both starts and cancels IO.
291 iosrv.submchan = make(chan anOpIface)
292 iosrv.canchan = make(chan anOpIface)
293 go iosrv.ProcessRemoteIO()
297 // Network file descriptor.
298 type netFD struct {
299 // locking/lifetime of sysfd
300 sysmu sync.Mutex
301 sysref int
302 closing bool
304 // immutable until Close
305 sysfd syscall.Handle
306 family int
307 sotype int
308 isConnected bool
309 net string
310 laddr Addr
311 raddr Addr
312 resultc [2]chan ioResult // read/write completion results
313 errnoc [2]chan error // read/write submit or cancel operation errors
314 closec chan bool // used by Close to cancel pending IO
316 // serialize access to Read and Write methods
317 rio, wio sync.Mutex
319 // read and write deadlines
320 rdeadline, wdeadline deadline
323 func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD {
324 netfd := &netFD{
325 sysfd: fd,
326 family: family,
327 sotype: sotype,
328 net: net,
329 closec: make(chan bool),
331 return netfd
334 func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) {
335 if initErr != nil {
336 return nil, initErr
338 onceStartServer.Do(startServer)
339 // Associate our socket with resultsrv.iocp.
340 if _, err := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); err != nil {
341 return nil, err
343 return allocFD(fd, family, proto, net), nil
346 func (fd *netFD) setAddr(laddr, raddr Addr) {
347 fd.laddr = laddr
348 fd.raddr = raddr
349 runtime.SetFinalizer(fd, (*netFD).closesocket)
352 // Make new connection.
354 type connectOp struct {
355 anOp
356 ra syscall.Sockaddr
359 func (o *connectOp) Submit() error {
360 return syscall.ConnectEx(o.fd.sysfd, o.ra, nil, 0, nil, &o.o)
363 func (o *connectOp) Name() string {
364 return "ConnectEx"
367 func (fd *netFD) connect(la, ra syscall.Sockaddr) error {
368 if !canUseConnectEx(fd.net) {
369 return syscall.Connect(fd.sysfd, ra)
371 // ConnectEx windows API requires an unconnected, previously bound socket.
372 if la == nil {
373 switch ra.(type) {
374 case *syscall.SockaddrInet4:
375 la = &syscall.SockaddrInet4{}
376 case *syscall.SockaddrInet6:
377 la = &syscall.SockaddrInet6{}
378 default:
379 panic("unexpected type in connect")
381 if err := syscall.Bind(fd.sysfd, la); err != nil {
382 return err
385 // Call ConnectEx API.
386 var o connectOp
387 o.Init(fd, 'w')
388 o.ra = ra
389 _, err := iosrv.ExecIO(&o, fd.wdeadline.value())
390 if err != nil {
391 return err
393 // Refresh socket properties.
394 return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
397 // Add a reference to this fd.
398 // If closing==true, mark the fd as closing.
399 // Returns an error if the fd cannot be used.
400 func (fd *netFD) incref(closing bool) error {
401 if fd == nil {
402 return errClosing
404 fd.sysmu.Lock()
405 if fd.closing {
406 fd.sysmu.Unlock()
407 return errClosing
409 fd.sysref++
410 if closing {
411 fd.closing = true
413 closing = fd.closing
414 fd.sysmu.Unlock()
415 return nil
418 // Remove a reference to this FD and close if we've been asked to do so (and
419 // there are no references left.
420 func (fd *netFD) decref() {
421 if fd == nil {
422 return
424 fd.sysmu.Lock()
425 fd.sysref--
426 if fd.closing && fd.sysref == 0 && fd.sysfd != syscall.InvalidHandle {
427 closesocket(fd.sysfd)
428 fd.sysfd = syscall.InvalidHandle
429 // no need for a finalizer anymore
430 runtime.SetFinalizer(fd, nil)
432 fd.sysmu.Unlock()
435 func (fd *netFD) Close() error {
436 if err := fd.incref(true); err != nil {
437 return err
439 defer fd.decref()
440 // unblock pending reader and writer
441 close(fd.closec)
442 // wait for both reader and writer to exit
443 fd.rio.Lock()
444 defer fd.rio.Unlock()
445 fd.wio.Lock()
446 defer fd.wio.Unlock()
447 return nil
450 func (fd *netFD) shutdown(how int) error {
451 if err := fd.incref(false); err != nil {
452 return err
454 defer fd.decref()
455 err := syscall.Shutdown(fd.sysfd, how)
456 if err != nil {
457 return &OpError{"shutdown", fd.net, fd.laddr, err}
459 return nil
462 func (fd *netFD) CloseRead() error {
463 return fd.shutdown(syscall.SHUT_RD)
466 func (fd *netFD) CloseWrite() error {
467 return fd.shutdown(syscall.SHUT_WR)
470 func (fd *netFD) closesocket() error {
471 return closesocket(fd.sysfd)
474 // Read from network.
476 type readOp struct {
477 bufOp
480 func (o *readOp) Submit() error {
481 var d, f uint32
482 return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
485 func (o *readOp) Name() string {
486 return "WSARecv"
489 func (fd *netFD) Read(buf []byte) (int, error) {
490 if err := fd.incref(false); err != nil {
491 return 0, err
493 defer fd.decref()
494 fd.rio.Lock()
495 defer fd.rio.Unlock()
496 var o readOp
497 o.Init(fd, buf, 'r')
498 n, err := iosrv.ExecIO(&o, fd.rdeadline.value())
499 if err == nil && n == 0 {
500 err = io.EOF
502 return n, err
505 // ReadFrom from network.
507 type readFromOp struct {
508 bufOp
509 rsa syscall.RawSockaddrAny
510 rsan int32
513 func (o *readFromOp) Submit() error {
514 var d, f uint32
515 return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsan, &o.o, nil)
518 func (o *readFromOp) Name() string {
519 return "WSARecvFrom"
522 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
523 if len(buf) == 0 {
524 return 0, nil, nil
526 if err := fd.incref(false); err != nil {
527 return 0, nil, err
529 defer fd.decref()
530 fd.rio.Lock()
531 defer fd.rio.Unlock()
532 var o readFromOp
533 o.Init(fd, buf, 'r')
534 o.rsan = int32(unsafe.Sizeof(o.rsa))
535 n, err = iosrv.ExecIO(&o, fd.rdeadline.value())
536 if err != nil {
537 return 0, nil, err
539 sa, _ = o.rsa.Sockaddr()
540 return
543 // Write to network.
545 type writeOp struct {
546 bufOp
549 func (o *writeOp) Submit() error {
550 var d uint32
551 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil)
554 func (o *writeOp) Name() string {
555 return "WSASend"
558 func (fd *netFD) Write(buf []byte) (int, error) {
559 if err := fd.incref(false); err != nil {
560 return 0, err
562 defer fd.decref()
563 fd.wio.Lock()
564 defer fd.wio.Unlock()
565 var o writeOp
566 o.Init(fd, buf, 'w')
567 return iosrv.ExecIO(&o, fd.wdeadline.value())
570 // WriteTo to network.
572 type writeToOp struct {
573 bufOp
574 sa syscall.Sockaddr
577 func (o *writeToOp) Submit() error {
578 var d uint32
579 return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil)
582 func (o *writeToOp) Name() string {
583 return "WSASendto"
586 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
587 if len(buf) == 0 {
588 return 0, nil
590 if err := fd.incref(false); err != nil {
591 return 0, err
593 defer fd.decref()
594 fd.wio.Lock()
595 defer fd.wio.Unlock()
596 var o writeToOp
597 o.Init(fd, buf, 'w')
598 o.sa = sa
599 return iosrv.ExecIO(&o, fd.wdeadline.value())
602 // Accept new network connections.
604 type acceptOp struct {
605 anOp
606 newsock syscall.Handle
607 attrs [2]syscall.RawSockaddrAny // space for local and remote address only
610 func (o *acceptOp) Submit() error {
611 var d uint32
612 l := uint32(unsafe.Sizeof(o.attrs[0]))
613 return syscall.AcceptEx(o.fd.sysfd, o.newsock,
614 (*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &d, &o.o)
617 func (o *acceptOp) Name() string {
618 return "AcceptEx"
621 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
622 if err := fd.incref(false); err != nil {
623 return nil, err
625 defer fd.decref()
627 // Get new socket.
628 s, err := sysSocket(fd.family, fd.sotype, 0)
629 if err != nil {
630 return nil, &OpError{"socket", fd.net, fd.laddr, err}
633 // Associate our new socket with IOCP.
634 onceStartServer.Do(startServer)
635 if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil {
636 closesocket(s)
637 return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err}
640 // Submit accept request.
641 var o acceptOp
642 o.Init(fd, 'r')
643 o.newsock = s
644 _, err = iosrv.ExecIO(&o, fd.rdeadline.value())
645 if err != nil {
646 closesocket(s)
647 return nil, err
650 // Inherit properties of the listening socket.
651 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
652 if err != nil {
653 closesocket(s)
654 return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
657 // Get local and peer addr out of AcceptEx buffer.
658 var lrsa, rrsa *syscall.RawSockaddrAny
659 var llen, rlen int32
660 l := uint32(unsafe.Sizeof(*lrsa))
661 syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])),
662 0, l, l, &lrsa, &llen, &rrsa, &rlen)
663 lsa, _ := lrsa.Sockaddr()
664 rsa, _ := rrsa.Sockaddr()
666 netfd := allocFD(s, fd.family, fd.sotype, fd.net)
667 netfd.setAddr(toAddr(lsa), toAddr(rsa))
668 return netfd, nil
671 // Unimplemented functions.
673 func (fd *netFD) dup() (*os.File, error) {
674 // TODO: Implement this
675 return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
678 var errNoSupport = errors.New("address family not supported")
680 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
681 return 0, 0, 0, nil, errNoSupport
684 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
685 return 0, 0, errNoSupport