github.com/s1s1ty/go@v0.0.0-20180207192209-104445e3140f/src/internal/poll/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 poll
     8  
     9  import (
    10  	"errors"
    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_pollServerDescriptor() uintptr
    21  func runtime_pollOpen(fd uintptr) (uintptr, int)
    22  func runtime_pollClose(ctx uintptr)
    23  func runtime_pollWait(ctx uintptr, mode int) int
    24  func runtime_pollWaitCanceled(ctx uintptr, mode int) int
    25  func runtime_pollReset(ctx uintptr, mode int) int
    26  func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
    27  func runtime_pollUnblock(ctx uintptr)
    28  
    29  type pollDesc struct {
    30  	runtimeCtx uintptr
    31  }
    32  
    33  var serverInit sync.Once
    34  
    35  func (pd *pollDesc) init(fd *FD) error {
    36  	serverInit.Do(runtime_pollServerInit)
    37  	ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
    38  	if errno != 0 {
    39  		if ctx != 0 {
    40  			runtime_pollUnblock(ctx)
    41  			runtime_pollClose(ctx)
    42  		}
    43  		return syscall.Errno(errno)
    44  	}
    45  	pd.runtimeCtx = ctx
    46  	return nil
    47  }
    48  
    49  func (pd *pollDesc) close() {
    50  	if pd.runtimeCtx == 0 {
    51  		return
    52  	}
    53  	runtime_pollClose(pd.runtimeCtx)
    54  	pd.runtimeCtx = 0
    55  }
    56  
    57  // Evict evicts fd from the pending list, unblocking any I/O running on fd.
    58  func (pd *pollDesc) evict() {
    59  	if pd.runtimeCtx == 0 {
    60  		return
    61  	}
    62  	runtime_pollUnblock(pd.runtimeCtx)
    63  }
    64  
    65  func (pd *pollDesc) prepare(mode int, isFile bool) error {
    66  	if pd.runtimeCtx == 0 {
    67  		return nil
    68  	}
    69  	res := runtime_pollReset(pd.runtimeCtx, mode)
    70  	return convertErr(res, isFile)
    71  }
    72  
    73  func (pd *pollDesc) prepareRead(isFile bool) error {
    74  	return pd.prepare('r', isFile)
    75  }
    76  
    77  func (pd *pollDesc) prepareWrite(isFile bool) error {
    78  	return pd.prepare('w', isFile)
    79  }
    80  
    81  func (pd *pollDesc) wait(mode int, isFile bool) error {
    82  	if pd.runtimeCtx == 0 {
    83  		return errors.New("waiting for unsupported file type")
    84  	}
    85  	res := runtime_pollWait(pd.runtimeCtx, mode)
    86  	return convertErr(res, isFile)
    87  }
    88  
    89  func (pd *pollDesc) waitRead(isFile bool) error {
    90  	return pd.wait('r', isFile)
    91  }
    92  
    93  func (pd *pollDesc) waitWrite(isFile bool) error {
    94  	return pd.wait('w', isFile)
    95  }
    96  
    97  func (pd *pollDesc) waitCanceled(mode int) {
    98  	if pd.runtimeCtx == 0 {
    99  		return
   100  	}
   101  	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
   102  }
   103  
   104  func (pd *pollDesc) pollable() bool {
   105  	return pd.runtimeCtx != 0
   106  }
   107  
   108  func convertErr(res int, isFile bool) error {
   109  	switch res {
   110  	case 0:
   111  		return nil
   112  	case 1:
   113  		return errClosing(isFile)
   114  	case 2:
   115  		return ErrTimeout
   116  	}
   117  	println("unreachable: ", res)
   118  	panic("unreachable")
   119  }
   120  
   121  // SetDeadline sets the read and write deadlines associated with fd.
   122  func (fd *FD) SetDeadline(t time.Time) error {
   123  	return setDeadlineImpl(fd, t, 'r'+'w')
   124  }
   125  
   126  // SetReadDeadline sets the read deadline associated with fd.
   127  func (fd *FD) SetReadDeadline(t time.Time) error {
   128  	return setDeadlineImpl(fd, t, 'r')
   129  }
   130  
   131  // SetWriteDeadline sets the write deadline associated with fd.
   132  func (fd *FD) SetWriteDeadline(t time.Time) error {
   133  	return setDeadlineImpl(fd, t, 'w')
   134  }
   135  
   136  func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
   137  	diff := int64(time.Until(t))
   138  	d := runtimeNano() + diff
   139  	if d <= 0 && diff > 0 {
   140  		// If the user has a deadline in the future, but the delay calculation
   141  		// overflows, then set the deadline to the maximum possible value.
   142  		d = 1<<63 - 1
   143  	}
   144  	if t.IsZero() {
   145  		d = 0
   146  	}
   147  	if err := fd.incref(); err != nil {
   148  		return err
   149  	}
   150  	defer fd.decref()
   151  	if fd.pd.runtimeCtx == 0 {
   152  		return ErrNoDeadline
   153  	}
   154  	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
   155  	return nil
   156  }
   157  
   158  // PollDescriptor returns the descriptor being used by the poller,
   159  // or ^uintptr(0) if there isn't one. This is only used for testing.
   160  func PollDescriptor() uintptr {
   161  	return runtime_pollServerDescriptor()
   162  }