...
Run Format

Source file src/runtime/netpoll_windows.go

Documentation: runtime

  // Copyright 2013 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 runtime
  
  import (
  	"unsafe"
  )
  
  const _DWORD_MAX = 0xffffffff
  
  const _INVALID_HANDLE_VALUE = ^uintptr(0)
  
  // net_op must be the same as beginning of internal/poll.operation.
  // Keep these in sync.
  type net_op struct {
  	// used by windows
  	o overlapped
  	// used by netpoll
  	pd    *pollDesc
  	mode  int32
  	errno int32
  	qty   uint32
  }
  
  type overlappedEntry struct {
  	key      uintptr
  	op       *net_op // In reality it's *overlapped, but we cast it to *net_op anyway.
  	internal uintptr
  	qty      uint32
  }
  
  var iocphandle uintptr = _INVALID_HANDLE_VALUE // completion port io handle
  
  func netpollinit() {
  	iocphandle = stdcall4(_CreateIoCompletionPort, _INVALID_HANDLE_VALUE, 0, 0, _DWORD_MAX)
  	if iocphandle == 0 {
  		println("runtime: CreateIoCompletionPort failed (errno=", getlasterror(), ")")
  		throw("runtime: netpollinit failed")
  	}
  }
  
  func netpolldescriptor() uintptr {
  	return iocphandle
  }
  
  func netpollopen(fd uintptr, pd *pollDesc) int32 {
  	if stdcall4(_CreateIoCompletionPort, fd, iocphandle, 0, 0) == 0 {
  		return -int32(getlasterror())
  	}
  	return 0
  }
  
  func netpollclose(fd uintptr) int32 {
  	// nothing to do
  	return 0
  }
  
  func netpollarm(pd *pollDesc, mode int) {
  	throw("runtime: unused")
  }
  
  // Polls for completed network IO.
  // Returns list of goroutines that become runnable.
  func netpoll(block bool) *g {
  	var entries [64]overlappedEntry
  	var wait, qty, key, flags, n, i uint32
  	var errno int32
  	var op *net_op
  	var gp guintptr
  
  	mp := getg().m
  
  	if iocphandle == _INVALID_HANDLE_VALUE {
  		return nil
  	}
  	wait = 0
  	if block {
  		wait = _INFINITE
  	}
  retry:
  	if _GetQueuedCompletionStatusEx != nil {
  		n = uint32(len(entries) / int(gomaxprocs))
  		if n < 8 {
  			n = 8
  		}
  		if block {
  			mp.blocked = true
  		}
  		if stdcall6(_GetQueuedCompletionStatusEx, iocphandle, uintptr(unsafe.Pointer(&entries[0])), uintptr(n), uintptr(unsafe.Pointer(&n)), uintptr(wait), 0) == 0 {
  			mp.blocked = false
  			errno = int32(getlasterror())
  			if !block && errno == _WAIT_TIMEOUT {
  				return nil
  			}
  			println("runtime: GetQueuedCompletionStatusEx failed (errno=", errno, ")")
  			throw("runtime: netpoll failed")
  		}
  		mp.blocked = false
  		for i = 0; i < n; i++ {
  			op = entries[i].op
  			errno = 0
  			qty = 0
  			if stdcall5(_WSAGetOverlappedResult, op.pd.fd, uintptr(unsafe.Pointer(op)), uintptr(unsafe.Pointer(&qty)), 0, uintptr(unsafe.Pointer(&flags))) == 0 {
  				errno = int32(getlasterror())
  			}
  			handlecompletion(&gp, op, errno, qty)
  		}
  	} else {
  		op = nil
  		errno = 0
  		qty = 0
  		if block {
  			mp.blocked = true
  		}
  		if stdcall5(_GetQueuedCompletionStatus, iocphandle, uintptr(unsafe.Pointer(&qty)), uintptr(unsafe.Pointer(&key)), uintptr(unsafe.Pointer(&op)), uintptr(wait)) == 0 {
  			mp.blocked = false
  			errno = int32(getlasterror())
  			if !block && errno == _WAIT_TIMEOUT {
  				return nil
  			}
  			if op == nil {
  				println("runtime: GetQueuedCompletionStatus failed (errno=", errno, ")")
  				throw("runtime: netpoll failed")
  			}
  			// dequeued failed IO packet, so report that
  		}
  		mp.blocked = false
  		handlecompletion(&gp, op, errno, qty)
  	}
  	if block && gp == 0 {
  		goto retry
  	}
  	return gp.ptr()
  }
  
  func handlecompletion(gpp *guintptr, op *net_op, errno int32, qty uint32) {
  	if op == nil {
  		println("runtime: GetQueuedCompletionStatus returned op == nil")
  		throw("runtime: netpoll failed")
  	}
  	mode := op.mode
  	if mode != 'r' && mode != 'w' {
  		println("runtime: GetQueuedCompletionStatus returned invalid mode=", mode)
  		throw("runtime: netpoll failed")
  	}
  	op.errno = errno
  	op.qty = qty
  	netpollready(gpp, op.pd, mode)
  }
  

View as plain text