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