github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/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  	"runtime"
    11  	"sync"
    12  	"syscall"
    13  	"time"
    14  )
    15  
    16  // runtimeNano returns the current value of the runtime clock in nanoseconds.
    17  func runtimeNano() int64
    18  
    19  func runtime_pollServerInit()
    20  func runtime_pollOpen(fd uintptr) (uintptr, int)
    21  func runtime_pollClose(ctx uintptr)
    22  func runtime_pollWait(ctx uintptr, mode int) int
    23  func runtime_pollWaitCanceled(ctx uintptr, mode int) int
    24  func runtime_pollReset(ctx uintptr, mode int) int
    25  func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
    26  func runtime_pollUnblock(ctx uintptr)
    27  
    28  type pollDesc struct {
    29  	runtimeCtx uintptr
    30  }
    31  
    32  var serverInit sync.Once
    33  
    34  func (pd *pollDesc) init(fd *netFD) error {
    35  	serverInit.Do(runtime_pollServerInit)
    36  	ctx, errno := runtime_pollOpen(uintptr(fd.sysfd))
    37  	runtime.KeepAlive(fd)
    38  	if errno != 0 {
    39  		return syscall.Errno(errno)
    40  	}
    41  	pd.runtimeCtx = ctx
    42  	return nil
    43  }
    44  
    45  func (pd *pollDesc) close() {
    46  	if pd.runtimeCtx == 0 {
    47  		return
    48  	}
    49  	runtime_pollClose(pd.runtimeCtx)
    50  	pd.runtimeCtx = 0
    51  }
    52  
    53  // Evict evicts fd from the pending list, unblocking any I/O running on fd.
    54  func (pd *pollDesc) evict() {
    55  	if pd.runtimeCtx == 0 {
    56  		return
    57  	}
    58  	runtime_pollUnblock(pd.runtimeCtx)
    59  }
    60  
    61  func (pd *pollDesc) prepare(mode int) error {
    62  	res := runtime_pollReset(pd.runtimeCtx, mode)
    63  	return convertErr(res)
    64  }
    65  
    66  func (pd *pollDesc) prepareRead() error {
    67  	return pd.prepare('r')
    68  }
    69  
    70  func (pd *pollDesc) prepareWrite() error {
    71  	return pd.prepare('w')
    72  }
    73  
    74  func (pd *pollDesc) wait(mode int) error {
    75  	res := runtime_pollWait(pd.runtimeCtx, mode)
    76  	return convertErr(res)
    77  }
    78  
    79  func (pd *pollDesc) waitRead() error {
    80  	return pd.wait('r')
    81  }
    82  
    83  func (pd *pollDesc) waitWrite() error {
    84  	return pd.wait('w')
    85  }
    86  
    87  func (pd *pollDesc) waitCanceled(mode int) {
    88  	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
    89  }
    90  
    91  func (pd *pollDesc) waitCanceledRead() {
    92  	pd.waitCanceled('r')
    93  }
    94  
    95  func (pd *pollDesc) waitCanceledWrite() {
    96  	pd.waitCanceled('w')
    97  }
    98  
    99  func convertErr(res int) error {
   100  	switch res {
   101  	case 0:
   102  		return nil
   103  	case 1:
   104  		return errClosing
   105  	case 2:
   106  		return errTimeout
   107  	}
   108  	println("unreachable: ", res)
   109  	panic("unreachable")
   110  }
   111  
   112  func (fd *netFD) setDeadline(t time.Time) error {
   113  	return setDeadlineImpl(fd, t, 'r'+'w')
   114  }
   115  
   116  func (fd *netFD) setReadDeadline(t time.Time) error {
   117  	return setDeadlineImpl(fd, t, 'r')
   118  }
   119  
   120  func (fd *netFD) setWriteDeadline(t time.Time) error {
   121  	return setDeadlineImpl(fd, t, 'w')
   122  }
   123  
   124  func setDeadlineImpl(fd *netFD, t time.Time, mode int) error {
   125  	diff := int64(time.Until(t))
   126  	d := runtimeNano() + diff
   127  	if d <= 0 && diff > 0 {
   128  		// If the user has a deadline in the future, but the delay calculation
   129  		// overflows, then set the deadline to the maximum possible value.
   130  		d = 1<<63 - 1
   131  	}
   132  	if t.IsZero() {
   133  		d = 0
   134  	}
   135  	if err := fd.incref(); err != nil {
   136  		return err
   137  	}
   138  	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
   139  	fd.decref()
   140  	return nil
   141  }