github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/net/fd_poll_runtime.go (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  // +build darwin dragonfly freebsd linux netbsd openbsd windows solaris
     6  
     7  package net
     8  
     9  import (
    10  	"sync"
    11  	"syscall"
    12  	"time"
    13  )
    14  
    15  // runtimeNano returns the current value of the runtime clock in nanoseconds.
    16  func runtimeNano() int64
    17  
    18  func runtime_pollServerInit()
    19  func runtime_pollOpen(fd uintptr) (uintptr, int)
    20  func runtime_pollClose(ctx uintptr)
    21  func runtime_pollWait(ctx uintptr, mode int) int
    22  func runtime_pollWaitCanceled(ctx uintptr, mode int) int
    23  func runtime_pollReset(ctx uintptr, mode int) int
    24  func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
    25  func runtime_pollUnblock(ctx uintptr)
    26  
    27  type pollDesc struct {
    28  	runtimeCtx uintptr
    29  }
    30  
    31  var serverInit sync.Once
    32  
    33  func (pd *pollDesc) Init(fd *netFD) error {
    34  	serverInit.Do(runtime_pollServerInit)
    35  	ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
    36  	if errno != 0 {
    37  		return syscall.Errno(errno)
    38  	}
    39  	pd.runtimeCtx = ctx
    40  	return nil
    41  }
    42  
    43  func (pd *pollDesc) Close() {
    44  	if pd.runtimeCtx == 0 {
    45  		return
    46  	}
    47  	runtime_pollClose(pd.runtimeCtx)
    48  	pd.runtimeCtx = 0
    49  }
    50  
    51  func (pd *pollDesc) Lock() {
    52  }
    53  
    54  func (pd *pollDesc) Unlock() {
    55  }
    56  
    57  func (pd *pollDesc) Wakeup() {
    58  }
    59  
    60  // Evict evicts fd from the pending list, unblocking any I/O running on fd.
    61  // Return value is whether the pollServer should be woken up.
    62  func (pd *pollDesc) Evict() bool {
    63  	if pd.runtimeCtx == 0 {
    64  		return false
    65  	}
    66  	runtime_pollUnblock(pd.runtimeCtx)
    67  	return false
    68  }
    69  
    70  func (pd *pollDesc) Prepare(mode int) error {
    71  	res := runtime_pollReset(pd.runtimeCtx, mode)
    72  	return convertErr(res)
    73  }
    74  
    75  func (pd *pollDesc) PrepareRead() error {
    76  	return pd.Prepare('r')
    77  }
    78  
    79  func (pd *pollDesc) PrepareWrite() error {
    80  	return pd.Prepare('w')
    81  }
    82  
    83  func (pd *pollDesc) Wait(mode int) error {
    84  	res := runtime_pollWait(pd.runtimeCtx, mode)
    85  	return convertErr(res)
    86  }
    87  
    88  func (pd *pollDesc) WaitRead() error {
    89  	return pd.Wait('r')
    90  }
    91  
    92  func (pd *pollDesc) WaitWrite() error {
    93  	return pd.Wait('w')
    94  }
    95  
    96  func (pd *pollDesc) WaitCanceled(mode int) {
    97  	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
    98  }
    99  
   100  func (pd *pollDesc) WaitCanceledRead() {
   101  	pd.WaitCanceled('r')
   102  }
   103  
   104  func (pd *pollDesc) WaitCanceledWrite() {
   105  	pd.WaitCanceled('w')
   106  }
   107  
   108  func convertErr(res int) error {
   109  	switch res {
   110  	case 0:
   111  		return nil
   112  	case 1:
   113  		return errClosing
   114  	case 2:
   115  		return errTimeout
   116  	}
   117  	println("unreachable: ", res)
   118  	panic("unreachable")
   119  }
   120  
   121  func (fd *netFD) setDeadline(t time.Time) error {
   122  	return setDeadlineImpl(fd, t, 'r'+'w')
   123  }
   124  
   125  func (fd *netFD) setReadDeadline(t time.Time) error {
   126  	return setDeadlineImpl(fd, t, 'r')
   127  }
   128  
   129  func (fd *netFD) setWriteDeadline(t time.Time) error {
   130  	return setDeadlineImpl(fd, t, 'w')
   131  }
   132  
   133  func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
   134  	d := runtimeNano() + int64(t.Sub(time.Now()))
   135  	if t.IsZero() {
   136  		d = 0
   137  	}
   138  	if err := fd.incref(); err != nil {
   139  		return err
   140  	}
   141  	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
   142  	fd.decref()
   143  	return nil
   144  }