github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/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  // Evict evicts fd from the pending list, unblocking any I/O running on fd.
    52  func (pd *pollDesc) Evict() {
    53  	if pd.runtimeCtx == 0 {
    54  		return
    55  	}
    56  	runtime_pollUnblock(pd.runtimeCtx)
    57  }
    58  
    59  func (pd *pollDesc) Prepare(mode int) error {
    60  	res := runtime_pollReset(pd.runtimeCtx, mode)
    61  	return convertErr(res)
    62  }
    63  
    64  func (pd *pollDesc) PrepareRead() error {
    65  	return pd.Prepare('r')
    66  }
    67  
    68  func (pd *pollDesc) PrepareWrite() error {
    69  	return pd.Prepare('w')
    70  }
    71  
    72  func (pd *pollDesc) Wait(mode int) error {
    73  	res := runtime_pollWait(pd.runtimeCtx, mode)
    74  	return convertErr(res)
    75  }
    76  
    77  func (pd *pollDesc) WaitRead() error {
    78  	return pd.Wait('r')
    79  }
    80  
    81  func (pd *pollDesc) WaitWrite() error {
    82  	return pd.Wait('w')
    83  }
    84  
    85  func (pd *pollDesc) WaitCanceled(mode int) {
    86  	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
    87  }
    88  
    89  func (pd *pollDesc) WaitCanceledRead() {
    90  	pd.WaitCanceled('r')
    91  }
    92  
    93  func (pd *pollDesc) WaitCanceledWrite() {
    94  	pd.WaitCanceled('w')
    95  }
    96  
    97  func convertErr(res int) error {
    98  	switch res {
    99  	case 0:
   100  		return nil
   101  	case 1:
   102  		return errClosing
   103  	case 2:
   104  		return errTimeout
   105  	}
   106  	println("unreachable: ", res)
   107  	panic("unreachable")
   108  }
   109  
   110  func (fd *netFD) setDeadline(t time.Time) error {
   111  	return setDeadlineImpl(fd, t, 'r'+'w')
   112  }
   113  
   114  func (fd *netFD) setReadDeadline(t time.Time) error {
   115  	return setDeadlineImpl(fd, t, 'r')
   116  }
   117  
   118  func (fd *netFD) setWriteDeadline(t time.Time) error {
   119  	return setDeadlineImpl(fd, t, 'w')
   120  }
   121  
   122  func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
   123  	d := runtimeNano() + int64(t.Sub(time.Now()))
   124  	if t.IsZero() {
   125  		d = 0
   126  	}
   127  	if err := fd.incref(); err != nil {
   128  		return err
   129  	}
   130  	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
   131  	fd.decref()
   132  	return nil
   133  }