aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libgo/go/net/fd_windows.go
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libgo/go/net/fd_windows.go')
-rw-r--r--gcc-4.8.1/libgo/go/net/fd_windows.go684
1 files changed, 0 insertions, 684 deletions
diff --git a/gcc-4.8.1/libgo/go/net/fd_windows.go b/gcc-4.8.1/libgo/go/net/fd_windows.go
deleted file mode 100644
index ea6ef10ec..000000000
--- a/gcc-4.8.1/libgo/go/net/fd_windows.go
+++ /dev/null
@@ -1,684 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package net
-
-import (
- "errors"
- "io"
- "os"
- "runtime"
- "sync"
- "syscall"
- "time"
- "unsafe"
-)
-
-var initErr error
-
-// CancelIo Windows API cancels all outstanding IO for a particular
-// socket on current thread. To overcome that limitation, we run
-// special goroutine, locked to OS single thread, that both starts
-// and cancels IO. It means, there are 2 unavoidable thread switches
-// for every IO.
-// Some newer versions of Windows has new CancelIoEx API, that does
-// not have that limitation and can be used from any thread. This
-// package uses CancelIoEx API, if present, otherwise it fallback
-// to CancelIo.
-
-var canCancelIO bool // determines if CancelIoEx API is present
-
-func sysInit() {
- var d syscall.WSAData
- e := syscall.WSAStartup(uint32(0x202), &d)
- if e != nil {
- initErr = os.NewSyscallError("WSAStartup", e)
- }
- canCancelIO = syscall.LoadCancelIoEx() == nil
- if syscall.LoadGetAddrInfo() == nil {
- lookupIP = newLookupIP
- }
-}
-
-func closesocket(s syscall.Handle) error {
- return syscall.Closesocket(s)
-}
-
-func canUseConnectEx(net string) bool {
- if net == "udp" || net == "udp4" || net == "udp6" {
- // ConnectEx windows API does not support connectionless sockets.
- return false
- }
- return syscall.LoadConnectEx() == nil
-}
-
-func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
- if !canUseConnectEx(net) {
- // Use the relatively inefficient goroutine-racing
- // implementation of DialTimeout.
- return dialTimeoutRace(net, addr, timeout)
- }
- deadline := time.Now().Add(timeout)
- _, addri, err := resolveNetAddr("dial", net, addr, deadline)
- if err != nil {
- return nil, err
- }
- return dialAddr(net, addr, addri, deadline)
-}
-
-// Interface for all IO operations.
-type anOpIface interface {
- Op() *anOp
- Name() string
- Submit() error
-}
-
-// IO completion result parameters.
-type ioResult struct {
- qty uint32
- err error
-}
-
-// anOp implements functionality common to all IO operations.
-type anOp struct {
- // Used by IOCP interface, it must be first field
- // of the struct, as our code rely on it.
- o syscall.Overlapped
-
- resultc chan ioResult
- errnoc chan error
- fd *netFD
-}
-
-func (o *anOp) Init(fd *netFD, mode int) {
- o.fd = fd
- var i int
- if mode == 'r' {
- i = 0
- } else {
- i = 1
- }
- if fd.resultc[i] == nil {
- fd.resultc[i] = make(chan ioResult, 1)
- }
- o.resultc = fd.resultc[i]
- if fd.errnoc[i] == nil {
- fd.errnoc[i] = make(chan error)
- }
- o.errnoc = fd.errnoc[i]
-}
-
-func (o *anOp) Op() *anOp {
- return o
-}
-
-// bufOp is used by IO operations that read / write
-// data from / to client buffer.
-type bufOp struct {
- anOp
- buf syscall.WSABuf
-}
-
-func (o *bufOp) Init(fd *netFD, buf []byte, mode int) {
- o.anOp.Init(fd, mode)
- o.buf.Len = uint32(len(buf))
- if len(buf) == 0 {
- o.buf.Buf = nil
- } else {
- o.buf.Buf = (*byte)(unsafe.Pointer(&buf[0]))
- }
-}
-
-// resultSrv will retrieve all IO completion results from
-// iocp and send them to the correspondent waiting client
-// goroutine via channel supplied in the request.
-type resultSrv struct {
- iocp syscall.Handle
-}
-
-func (s *resultSrv) Run() {
- var o *syscall.Overlapped
- var key uint32
- var r ioResult
- for {
- r.err = syscall.GetQueuedCompletionStatus(s.iocp, &(r.qty), &key, &o, syscall.INFINITE)
- switch {
- case r.err == nil:
- // Dequeued successfully completed IO packet.
- case r.err == syscall.Errno(syscall.WAIT_TIMEOUT) && o == nil:
- // Wait has timed out (should not happen now, but might be used in the future).
- panic("GetQueuedCompletionStatus timed out")
- case o == nil:
- // Failed to dequeue anything -> report the error.
- panic("GetQueuedCompletionStatus failed " + r.err.Error())
- default:
- // Dequeued failed IO packet.
- }
- (*anOp)(unsafe.Pointer(o)).resultc <- r
- }
-}
-
-// ioSrv executes net IO requests.
-type ioSrv struct {
- submchan chan anOpIface // submit IO requests
- canchan chan anOpIface // cancel IO requests
-}
-
-// ProcessRemoteIO will execute submit IO requests on behalf
-// of other goroutines, all on a single os thread, so it can
-// cancel them later. Results of all operations will be sent
-// back to their requesters via channel supplied in request.
-// It is used only when the CancelIoEx API is unavailable.
-func (s *ioSrv) ProcessRemoteIO() {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
- for {
- select {
- case o := <-s.submchan:
- o.Op().errnoc <- o.Submit()
- case o := <-s.canchan:
- o.Op().errnoc <- syscall.CancelIo(syscall.Handle(o.Op().fd.sysfd))
- }
- }
-}
-
-// ExecIO executes a single IO operation oi. It submits and cancels
-// IO in the current thread for systems where Windows CancelIoEx API
-// is available. Alternatively, it passes the request onto
-// a special goroutine and waits for completion or cancels request.
-// deadline is unix nanos.
-func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (int, error) {
- var err error
- o := oi.Op()
- // Calculate timeout delta.
- var delta int64
- if deadline != 0 {
- delta = deadline - time.Now().UnixNano()
- if delta <= 0 {
- return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, errTimeout}
- }
- }
- // Start IO.
- if canCancelIO {
- err = oi.Submit()
- } else {
- // Send request to a special dedicated thread,
- // so it can stop the IO with CancelIO later.
- s.submchan <- oi
- err = <-o.errnoc
- }
- switch err {
- case nil:
- // IO completed immediately, but we need to get our completion message anyway.
- case syscall.ERROR_IO_PENDING:
- // IO started, and we have to wait for its completion.
- err = nil
- default:
- return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, err}
- }
- // Setup timer, if deadline is given.
- var timer <-chan time.Time
- if delta > 0 {
- t := time.NewTimer(time.Duration(delta) * time.Nanosecond)
- defer t.Stop()
- timer = t.C
- }
- // Wait for our request to complete.
- var r ioResult
- var cancelled, timeout bool
- select {
- case r = <-o.resultc:
- case <-timer:
- cancelled = true
- timeout = true
- case <-o.fd.closec:
- cancelled = true
- }
- if cancelled {
- // Cancel it.
- if canCancelIO {
- err := syscall.CancelIoEx(syscall.Handle(o.Op().fd.sysfd), &o.o)
- // Assuming ERROR_NOT_FOUND is returned, if IO is completed.
- if err != nil && err != syscall.ERROR_NOT_FOUND {
- // TODO(brainman): maybe do something else, but panic.
- panic(err)
- }
- } else {
- s.canchan <- oi
- <-o.errnoc
- }
- // Wait for IO to be canceled or complete successfully.
- r = <-o.resultc
- if r.err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled
- if timeout {
- r.err = errTimeout
- } else {
- r.err = errClosing
- }
- }
- }
- if r.err != nil {
- err = &OpError{oi.Name(), o.fd.net, o.fd.laddr, r.err}
- }
- return int(r.qty), err
-}
-
-// Start helper goroutines.
-var resultsrv *resultSrv
-var iosrv *ioSrv
-var onceStartServer sync.Once
-
-func startServer() {
- resultsrv = new(resultSrv)
- var err error
- resultsrv.iocp, err = syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 1)
- if err != nil {
- panic("CreateIoCompletionPort: " + err.Error())
- }
- go resultsrv.Run()
-
- iosrv = new(ioSrv)
- if !canCancelIO {
- // Only CancelIo API is available. Lets start special goroutine
- // locked to an OS thread, that both starts and cancels IO.
- iosrv.submchan = make(chan anOpIface)
- iosrv.canchan = make(chan anOpIface)
- go iosrv.ProcessRemoteIO()
- }
-}
-
-// Network file descriptor.
-type netFD struct {
- // locking/lifetime of sysfd
- sysmu sync.Mutex
- sysref int
- closing bool
-
- // immutable until Close
- sysfd syscall.Handle
- family int
- sotype int
- isConnected bool
- net string
- laddr Addr
- raddr Addr
- resultc [2]chan ioResult // read/write completion results
- errnoc [2]chan error // read/write submit or cancel operation errors
- closec chan bool // used by Close to cancel pending IO
-
- // serialize access to Read and Write methods
- rio, wio sync.Mutex
-
- // read and write deadlines
- rdeadline, wdeadline deadline
-}
-
-func allocFD(fd syscall.Handle, family, sotype int, net string) *netFD {
- netfd := &netFD{
- sysfd: fd,
- family: family,
- sotype: sotype,
- net: net,
- closec: make(chan bool),
- }
- return netfd
-}
-
-func newFD(fd syscall.Handle, family, proto int, net string) (*netFD, error) {
- if initErr != nil {
- return nil, initErr
- }
- onceStartServer.Do(startServer)
- // Associate our socket with resultsrv.iocp.
- if _, err := syscall.CreateIoCompletionPort(syscall.Handle(fd), resultsrv.iocp, 0, 0); err != nil {
- return nil, err
- }
- return allocFD(fd, family, proto, net), nil
-}
-
-func (fd *netFD) setAddr(laddr, raddr Addr) {
- fd.laddr = laddr
- fd.raddr = raddr
- runtime.SetFinalizer(fd, (*netFD).closesocket)
-}
-
-// Make new connection.
-
-type connectOp struct {
- anOp
- ra syscall.Sockaddr
-}
-
-func (o *connectOp) Submit() error {
- return syscall.ConnectEx(o.fd.sysfd, o.ra, nil, 0, nil, &o.o)
-}
-
-func (o *connectOp) Name() string {
- return "ConnectEx"
-}
-
-func (fd *netFD) connect(ra syscall.Sockaddr) error {
- if !canUseConnectEx(fd.net) {
- return syscall.Connect(fd.sysfd, ra)
- }
- // ConnectEx windows API requires an unconnected, previously bound socket.
- var la syscall.Sockaddr
- switch ra.(type) {
- case *syscall.SockaddrInet4:
- la = &syscall.SockaddrInet4{}
- case *syscall.SockaddrInet6:
- la = &syscall.SockaddrInet6{}
- default:
- panic("unexpected type in connect")
- }
- if err := syscall.Bind(fd.sysfd, la); err != nil {
- return err
- }
- // Call ConnectEx API.
- var o connectOp
- o.Init(fd, 'w')
- o.ra = ra
- _, err := iosrv.ExecIO(&o, fd.wdeadline.value())
- if err != nil {
- return err
- }
- // Refresh socket properties.
- return syscall.Setsockopt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_UPDATE_CONNECT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
-}
-
-// Add a reference to this fd.
-// If closing==true, mark the fd as closing.
-// Returns an error if the fd cannot be used.
-func (fd *netFD) incref(closing bool) error {
- if fd == nil {
- return errClosing
- }
- fd.sysmu.Lock()
- if fd.closing {
- fd.sysmu.Unlock()
- return errClosing
- }
- fd.sysref++
- if closing {
- fd.closing = true
- }
- closing = fd.closing
- fd.sysmu.Unlock()
- return nil
-}
-
-// Remove a reference to this FD and close if we've been asked to do so (and
-// there are no references left.
-func (fd *netFD) decref() {
- if fd == nil {
- return
- }
- fd.sysmu.Lock()
- fd.sysref--
- if fd.closing && fd.sysref == 0 && fd.sysfd != syscall.InvalidHandle {
- closesocket(fd.sysfd)
- fd.sysfd = syscall.InvalidHandle
- // no need for a finalizer anymore
- runtime.SetFinalizer(fd, nil)
- }
- fd.sysmu.Unlock()
-}
-
-func (fd *netFD) Close() error {
- if err := fd.incref(true); err != nil {
- return err
- }
- defer fd.decref()
- // unblock pending reader and writer
- close(fd.closec)
- // wait for both reader and writer to exit
- fd.rio.Lock()
- defer fd.rio.Unlock()
- fd.wio.Lock()
- defer fd.wio.Unlock()
- return nil
-}
-
-func (fd *netFD) shutdown(how int) error {
- if err := fd.incref(false); err != nil {
- return err
- }
- defer fd.decref()
- err := syscall.Shutdown(fd.sysfd, how)
- if err != nil {
- return &OpError{"shutdown", fd.net, fd.laddr, err}
- }
- return nil
-}
-
-func (fd *netFD) CloseRead() error {
- return fd.shutdown(syscall.SHUT_RD)
-}
-
-func (fd *netFD) CloseWrite() error {
- return fd.shutdown(syscall.SHUT_WR)
-}
-
-func (fd *netFD) closesocket() error {
- return closesocket(fd.sysfd)
-}
-
-// Read from network.
-
-type readOp struct {
- bufOp
-}
-
-func (o *readOp) Submit() error {
- var d, f uint32
- return syscall.WSARecv(syscall.Handle(o.fd.sysfd), &o.buf, 1, &d, &f, &o.o, nil)
-}
-
-func (o *readOp) Name() string {
- return "WSARecv"
-}
-
-func (fd *netFD) Read(buf []byte) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- fd.rio.Lock()
- defer fd.rio.Unlock()
- var o readOp
- o.Init(fd, buf, 'r')
- n, err := iosrv.ExecIO(&o, fd.rdeadline.value())
- if err == nil && n == 0 {
- err = io.EOF
- }
- return n, err
-}
-
-// ReadFrom from network.
-
-type readFromOp struct {
- bufOp
- rsa syscall.RawSockaddrAny
- rsan int32
-}
-
-func (o *readFromOp) Submit() error {
- var d, f uint32
- return syscall.WSARecvFrom(o.fd.sysfd, &o.buf, 1, &d, &f, &o.rsa, &o.rsan, &o.o, nil)
-}
-
-func (o *readFromOp) Name() string {
- return "WSARecvFrom"
-}
-
-func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
- if len(buf) == 0 {
- return 0, nil, nil
- }
- if err := fd.incref(false); err != nil {
- return 0, nil, err
- }
- defer fd.decref()
- fd.rio.Lock()
- defer fd.rio.Unlock()
- var o readFromOp
- o.Init(fd, buf, 'r')
- o.rsan = int32(unsafe.Sizeof(o.rsa))
- n, err = iosrv.ExecIO(&o, fd.rdeadline.value())
- if err != nil {
- return 0, nil, err
- }
- sa, _ = o.rsa.Sockaddr()
- return
-}
-
-// Write to network.
-
-type writeOp struct {
- bufOp
-}
-
-func (o *writeOp) Submit() error {
- var d uint32
- return syscall.WSASend(o.fd.sysfd, &o.buf, 1, &d, 0, &o.o, nil)
-}
-
-func (o *writeOp) Name() string {
- return "WSASend"
-}
-
-func (fd *netFD) Write(buf []byte) (int, error) {
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- fd.wio.Lock()
- defer fd.wio.Unlock()
- var o writeOp
- o.Init(fd, buf, 'w')
- return iosrv.ExecIO(&o, fd.wdeadline.value())
-}
-
-// WriteTo to network.
-
-type writeToOp struct {
- bufOp
- sa syscall.Sockaddr
-}
-
-func (o *writeToOp) Submit() error {
- var d uint32
- return syscall.WSASendto(o.fd.sysfd, &o.buf, 1, &d, 0, o.sa, &o.o, nil)
-}
-
-func (o *writeToOp) Name() string {
- return "WSASendto"
-}
-
-func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
- if len(buf) == 0 {
- return 0, nil
- }
- if err := fd.incref(false); err != nil {
- return 0, err
- }
- defer fd.decref()
- fd.wio.Lock()
- defer fd.wio.Unlock()
- var o writeToOp
- o.Init(fd, buf, 'w')
- o.sa = sa
- return iosrv.ExecIO(&o, fd.wdeadline.value())
-}
-
-// Accept new network connections.
-
-type acceptOp struct {
- anOp
- newsock syscall.Handle
- attrs [2]syscall.RawSockaddrAny // space for local and remote address only
-}
-
-func (o *acceptOp) Submit() error {
- var d uint32
- l := uint32(unsafe.Sizeof(o.attrs[0]))
- return syscall.AcceptEx(o.fd.sysfd, o.newsock,
- (*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &d, &o.o)
-}
-
-func (o *acceptOp) Name() string {
- return "AcceptEx"
-}
-
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
- if err := fd.incref(false); err != nil {
- return nil, err
- }
- defer fd.decref()
-
- // Get new socket.
- // See ../syscall/exec_unix.go for description of ForkLock.
- syscall.ForkLock.RLock()
- s, err := syscall.Socket(fd.family, fd.sotype, 0)
- if err != nil {
- syscall.ForkLock.RUnlock()
- return nil, &OpError{"socket", fd.net, fd.laddr, err}
- }
- syscall.CloseOnExec(s)
- syscall.ForkLock.RUnlock()
-
- // Associate our new socket with IOCP.
- onceStartServer.Do(startServer)
- if _, err := syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); err != nil {
- closesocket(s)
- return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, err}
- }
-
- // Submit accept request.
- var o acceptOp
- o.Init(fd, 'r')
- o.newsock = s
- _, err = iosrv.ExecIO(&o, fd.rdeadline.value())
- if err != nil {
- closesocket(s)
- return nil, err
- }
-
- // Inherit properties of the listening socket.
- err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd)))
- if err != nil {
- closesocket(s)
- return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
- }
-
- // Get local and peer addr out of AcceptEx buffer.
- var lrsa, rrsa *syscall.RawSockaddrAny
- var llen, rlen int32
- l := uint32(unsafe.Sizeof(*lrsa))
- syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])),
- 0, l, l, &lrsa, &llen, &rrsa, &rlen)
- lsa, _ := lrsa.Sockaddr()
- rsa, _ := rrsa.Sockaddr()
-
- netfd := allocFD(s, fd.family, fd.sotype, fd.net)
- netfd.setAddr(toAddr(lsa), toAddr(rsa))
- return netfd, nil
-}
-
-// Unimplemented functions.
-
-func (fd *netFD) dup() (*os.File, error) {
- // TODO: Implement this
- return nil, os.NewSyscallError("dup", syscall.EWINDOWS)
-}
-
-var errNoSupport = errors.New("address family not supported")
-
-func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
- return 0, 0, 0, nil, errNoSupport
-}
-
-func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
- return 0, 0, errNoSupport
-}