LEFT | RIGHT |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package net | 5 package net |
6 | 6 |
7 import ( | 7 import ( |
8 "errors" | 8 "errors" |
9 "io" | 9 "io" |
10 "os" | 10 "os" |
11 "runtime" | 11 "runtime" |
12 "sync" | 12 "sync" |
13 "syscall" | 13 "syscall" |
14 "time" | 14 "time" |
15 "unsafe" | 15 "unsafe" |
16 ) | 16 ) |
17 | 17 |
18 var initErr error | 18 var ( |
| 19 » initErr error |
| 20 » ioSync uint64 |
| 21 ) |
19 | 22 |
20 // CancelIo Windows API cancels all outstanding IO for a particular | 23 // CancelIo Windows API cancels all outstanding IO for a particular |
21 // socket on current thread. To overcome that limitation, we run | 24 // socket on current thread. To overcome that limitation, we run |
22 // special goroutine, locked to OS single thread, that both starts | 25 // special goroutine, locked to OS single thread, that both starts |
23 // and cancels IO. It means, there are 2 unavoidable thread switches | 26 // and cancels IO. It means, there are 2 unavoidable thread switches |
24 // for every IO. | 27 // for every IO. |
25 // Some newer versions of Windows has new CancelIoEx API, that does | 28 // Some newer versions of Windows has new CancelIoEx API, that does |
26 // not have that limitation and can be used from any thread. This | 29 // not have that limitation and can be used from any thread. This |
27 // package uses CancelIoEx API, if present, otherwise it fallback | 30 // package uses CancelIoEx API, if present, otherwise it fallback |
28 // to CancelIo. | 31 // to CancelIo. |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 } | 84 } |
82 | 85 |
83 func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn,
error) { | 86 func resolveAndDial(net, addr string, localAddr Addr, deadline time.Time) (Conn,
error) { |
84 if !canUseConnectEx(net) { | 87 if !canUseConnectEx(net) { |
85 // Use the relatively inefficient goroutine-racing | 88 // Use the relatively inefficient goroutine-racing |
86 // implementation of DialTimeout. | 89 // implementation of DialTimeout. |
87 return resolveAndDialChannel(net, addr, localAddr, deadline) | 90 return resolveAndDialChannel(net, addr, localAddr, deadline) |
88 } | 91 } |
89 ra, err := resolveAddr("dial", net, addr, deadline) | 92 ra, err := resolveAddr("dial", net, addr, deadline) |
90 if err != nil { | 93 if err != nil { |
91 » » return nil, err | 94 » » return nil, &OpError{Op: "dial", Net: net, Addr: nil, Err: err} |
92 } | 95 } |
93 return dial(net, addr, localAddr, ra, deadline) | 96 return dial(net, addr, localAddr, ra, deadline) |
94 } | 97 } |
95 | 98 |
96 // operation contains superset of data necessary to perform all async IO. | 99 // operation contains superset of data necessary to perform all async IO. |
97 type operation struct { | 100 type operation struct { |
98 // Used by IOCP interface, it must be first field | 101 // Used by IOCP interface, it must be first field |
99 // of the struct, as our code rely on it. | 102 // of the struct, as our code rely on it. |
100 o syscall.Overlapped | 103 o syscall.Overlapped |
101 | 104 |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 } | 445 } |
443 defer fd.readUnlock() | 446 defer fd.readUnlock() |
444 o := &fd.rop | 447 o := &fd.rop |
445 o.InitBuf(buf) | 448 o.InitBuf(buf) |
446 n, err := iosrv.ExecIO(o, "WSARecv", func(o *operation) error { | 449 n, err := iosrv.ExecIO(o, "WSARecv", func(o *operation) error { |
447 return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags,
&o.o, nil) | 450 return syscall.WSARecv(o.fd.sysfd, &o.buf, 1, &o.qty, &o.flags,
&o.o, nil) |
448 }) | 451 }) |
449 if err == nil && n == 0 { | 452 if err == nil && n == 0 { |
450 err = io.EOF | 453 err = io.EOF |
451 } | 454 } |
| 455 if raceenabled { |
| 456 raceAcquire(unsafe.Pointer(&ioSync)) |
| 457 } |
452 return n, err | 458 return n, err |
453 } | 459 } |
454 | 460 |
455 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { | 461 func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) { |
456 if len(buf) == 0 { | 462 if len(buf) == 0 { |
457 return 0, nil, nil | 463 return 0, nil, nil |
458 } | 464 } |
459 if err := fd.readLock(); err != nil { | 465 if err := fd.readLock(); err != nil { |
460 return 0, nil, err | 466 return 0, nil, err |
461 } | 467 } |
(...skipping 12 matching lines...) Expand all Loading... |
474 } | 480 } |
475 sa, _ = o.rsa.Sockaddr() | 481 sa, _ = o.rsa.Sockaddr() |
476 return | 482 return |
477 } | 483 } |
478 | 484 |
479 func (fd *netFD) Write(buf []byte) (int, error) { | 485 func (fd *netFD) Write(buf []byte) (int, error) { |
480 if err := fd.writeLock(); err != nil { | 486 if err := fd.writeLock(); err != nil { |
481 return 0, err | 487 return 0, err |
482 } | 488 } |
483 defer fd.writeUnlock() | 489 defer fd.writeUnlock() |
| 490 if raceenabled { |
| 491 raceReleaseMerge(unsafe.Pointer(&ioSync)) |
| 492 } |
484 o := &fd.wop | 493 o := &fd.wop |
485 o.InitBuf(buf) | 494 o.InitBuf(buf) |
486 return iosrv.ExecIO(o, "WSASend", func(o *operation) error { | 495 return iosrv.ExecIO(o, "WSASend", func(o *operation) error { |
487 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, n
il) | 496 return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &o.qty, 0, &o.o, n
il) |
488 }) | 497 }) |
489 } | 498 } |
490 | 499 |
491 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { | 500 func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { |
492 if len(buf) == 0 { | 501 if len(buf) == 0 { |
493 return 0, nil | 502 return 0, nil |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 | 577 |
569 var errNoSupport = errors.New("address family not supported") | 578 var errNoSupport = errors.New("address family not supported") |
570 | 579 |
571 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
ockaddr, err error) { | 580 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
ockaddr, err error) { |
572 return 0, 0, 0, nil, errNoSupport | 581 return 0, 0, 0, nil, errNoSupport |
573 } | 582 } |
574 | 583 |
575 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
n int, err error) { | 584 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
n int, err error) { |
576 return 0, 0, errNoSupport | 585 return 0, 0, errNoSupport |
577 } | 586 } |
LEFT | RIGHT |