github.com/gidoBOSSftw5731/go/src@v0.0.0-20210226122457-d24b0edbf019/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  //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || windows || solaris
     6  // +build aix darwin dragonfly freebsd linux netbsd openbsd windows solaris
     7  
     8  package poll
     9  
    10  import (
    11  	"errors"
    12  	"sync"
    13  	"syscall"
    14  	"time"
    15  	_ "unsafe" // for go:linkname
    16  )
    17  
    18  // runtimeNano returns the current value of the runtime clock in nanoseconds.
    19  //go:linkname runtimeNano runtime.nanotime
    20  func runtimeNano() int64
    21  
    22  func runtime_pollServerInit()
    23  func runtime_pollOpen(fd uintptr) (uintptr, int)
    24  func runtime_pollClose(ctx uintptr)
    25  func runtime_pollWait(ctx uintptr, mode int) int
    26  func runtime_pollWaitCanceled(ctx uintptr, mode int) int
    27  func runtime_pollReset(ctx uintptr, mode int) int
    28  func runtime_pollSetDeadline(ctx uintptr, d int64, mode int)
    29  func runtime_pollUnblock(ctx uintptr)
    30  func runtime_isPollServerDescriptor(fd uintptr) bool
    31  
    32  type pollDesc struct {
    33  	runtimeCtx uintptr
    34  }
    35  
    36  var serverInit sync.Once
    37  
    38  func (pd *pollDesc) init(fd *FD) error {
    39  	serverInit.Do(runtime_pollServerInit)
    40  	ctx, errno := runtime_pollOpen(uintptr(fd.Sysfd))
    41  	if errno != 0 {
    42  		if ctx != 0 {
    43  			runtime_pollUnblock(ctx)
    44  			runtime_pollClose(ctx)
    45  		}
    46  		return errnoErr(syscall.Errno(errno))
    47  	}
    48  	pd.runtimeCtx = ctx
    49  	return nil
    50  }
    51  
    52  func (pd *pollDesc) close() {
    53  	if pd.runtimeCtx == 0 {
    54  		return
    55  	}
    56  	runtime_pollClose(pd.runtimeCtx)
    57  	pd.runtimeCtx = 0
    58  }
    59  
    60  // Evict evicts fd from the pending list, unblocking any I/O running on fd.
    61  func (pd *pollDesc) evict() {
    62  	if pd.runtimeCtx == 0 {
    63  		return
    64  	}
    65  	runtime_pollUnblock(pd.runtimeCtx)
    66  }
    67  
    68  func (pd *pollDesc) prepare(mode int, isFile bool) error {
    69  	if pd.runtimeCtx == 0 {
    70  		return nil
    71  	}
    72  	res := runtime_pollReset(pd.runtimeCtx, mode)
    73  	return convertErr(res, isFile)
    74  }
    75  
    76  func (pd *pollDesc) prepareRead(isFile bool) error {
    77  	return pd.prepare('r', isFile)
    78  }
    79  
    80  func (pd *pollDesc) prepareWrite(isFile bool) error {
    81  	return pd.prepare('w', isFile)
    82  }
    83  
    84  func (pd *pollDesc) wait(mode int, isFile bool) error {
    85  	if pd.runtimeCtx == 0 {
    86  		return errors.New("waiting for unsupported file type")
    87  	}
    88  	res := runtime_pollWait(pd.runtimeCtx, mode)
    89  	return convertErr(res, isFile)
    90  }
    91  
    92  func (pd *pollDesc) waitRead(isFile bool) error {
    93  	return pd.wait('r', isFile)
    94  }
    95  
    96  func (pd *pollDesc) waitWrite(isFile bool) error {
    97  	return pd.wait('w', isFile)
    98  }
    99  
   100  func (pd *pollDesc) waitCanceled(mode int) {
   101  	if pd.runtimeCtx == 0 {
   102  		return
   103  	}
   104  	runtime_pollWaitCanceled(pd.runtimeCtx, mode)
   105  }
   106  
   107  func (pd *pollDesc) pollable() bool {
   108  	return pd.runtimeCtx != 0
   109  }
   110  
   111  // Error values returned by runtime_pollReset and runtime_pollWait.
   112  // These must match the values in runtime/netpoll.go.
   113  const (
   114  	pollNoError        = 0
   115  	pollErrClosing     = 1
   116  	pollErrTimeout     = 2
   117  	pollErrNotPollable = 3
   118  )
   119  
   120  func convertErr(res int, isFile bool) error {
   121  	switch res {
   122  	case pollNoError:
   123  		return nil
   124  	case pollErrClosing:
   125  		return errClosing(isFile)
   126  	case pollErrTimeout:
   127  		return ErrDeadlineExceeded
   128  	case pollErrNotPollable:
   129  		return ErrNotPollable
   130  	}
   131  	println("unreachable: ", res)
   132  	panic("unreachable")
   133  }
   134  
   135  // SetDeadline sets the read and write deadlines associated with fd.
   136  func (fd *FD) SetDeadline(t time.Time) error {
   137  	return setDeadlineImpl(fd, t, 'r'+'w')
   138  }
   139  
   140  // SetReadDeadline sets the read deadline associated with fd.
   141  func (fd *FD) SetReadDeadline(t time.Time) error {
   142  	return setDeadlineImpl(fd, t, 'r')
   143  }
   144  
   145  // SetWriteDeadline sets the write deadline associated with fd.
   146  func (fd *FD) SetWriteDeadline(t time.Time) error {
   147  	return setDeadlineImpl(fd, t, 'w')
   148  }
   149  
   150  func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
   151  	var d int64
   152  	if !t.IsZero() {
   153  		d = int64(time.Until(t))
   154  		if d == 0 {
   155  			d = -1 // don't confuse deadline right now with no deadline
   156  		}
   157  	}
   158  	if err := fd.incref(); err != nil {
   159  		return err
   160  	}
   161  	defer fd.decref()
   162  	if fd.pd.runtimeCtx == 0 {
   163  		return ErrNoDeadline
   164  	}
   165  	runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode)
   166  	return nil
   167  }
   168  
   169  // IsPollDescriptor reports whether fd is the descriptor being used by the poller.
   170  // This is only used for testing.
   171  func IsPollDescriptor(fd uintptr) bool {
   172  	return runtime_isPollServerDescriptor(fd)
   173  }