github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/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 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 return errnoErr(syscall.Errno(errno)) 42 } 43 pd.runtimeCtx = ctx 44 return nil 45 } 46 47 func (pd *pollDesc) close() { 48 if pd.runtimeCtx == 0 { 49 return 50 } 51 runtime_pollClose(pd.runtimeCtx) 52 pd.runtimeCtx = 0 53 } 54 55 // Evict evicts fd from the pending list, unblocking any I/O running on fd. 56 func (pd *pollDesc) evict() { 57 if pd.runtimeCtx == 0 { 58 return 59 } 60 runtime_pollUnblock(pd.runtimeCtx) 61 } 62 63 func (pd *pollDesc) prepare(mode int, isFile bool) error { 64 if pd.runtimeCtx == 0 { 65 return nil 66 } 67 res := runtime_pollReset(pd.runtimeCtx, mode) 68 return convertErr(res, isFile) 69 } 70 71 func (pd *pollDesc) prepareRead(isFile bool) error { 72 return pd.prepare('r', isFile) 73 } 74 75 func (pd *pollDesc) prepareWrite(isFile bool) error { 76 return pd.prepare('w', isFile) 77 } 78 79 func (pd *pollDesc) wait(mode int, isFile bool) error { 80 if pd.runtimeCtx == 0 { 81 return errors.New("waiting for unsupported file type") 82 } 83 res := runtime_pollWait(pd.runtimeCtx, mode) 84 return convertErr(res, isFile) 85 } 86 87 func (pd *pollDesc) waitRead(isFile bool) error { 88 return pd.wait('r', isFile) 89 } 90 91 func (pd *pollDesc) waitWrite(isFile bool) error { 92 return pd.wait('w', isFile) 93 } 94 95 func (pd *pollDesc) waitCanceled(mode int) { 96 if pd.runtimeCtx == 0 { 97 return 98 } 99 runtime_pollWaitCanceled(pd.runtimeCtx, mode) 100 } 101 102 func (pd *pollDesc) pollable() bool { 103 return pd.runtimeCtx != 0 104 } 105 106 // Error values returned by runtime_pollReset and runtime_pollWait. 107 // These must match the values in runtime/netpoll.go. 108 const ( 109 pollNoError = 0 110 pollErrClosing = 1 111 pollErrTimeout = 2 112 pollErrNotPollable = 3 113 ) 114 115 func convertErr(res int, isFile bool) error { 116 switch res { 117 case pollNoError: 118 return nil 119 case pollErrClosing: 120 return errClosing(isFile) 121 case pollErrTimeout: 122 return ErrDeadlineExceeded 123 case pollErrNotPollable: 124 return ErrNotPollable 125 } 126 println("unreachable: ", res) 127 panic("unreachable") 128 } 129 130 // SetDeadline sets the read and write deadlines associated with fd. 131 func (fd *FD) SetDeadline(t time.Time) error { 132 return setDeadlineImpl(fd, t, 'r'+'w') 133 } 134 135 // SetReadDeadline sets the read deadline associated with fd. 136 func (fd *FD) SetReadDeadline(t time.Time) error { 137 return setDeadlineImpl(fd, t, 'r') 138 } 139 140 // SetWriteDeadline sets the write deadline associated with fd. 141 func (fd *FD) SetWriteDeadline(t time.Time) error { 142 return setDeadlineImpl(fd, t, 'w') 143 } 144 145 func setDeadlineImpl(fd *FD, t time.Time, mode int) error { 146 var d int64 147 if !t.IsZero() { 148 d = int64(time.Until(t)) 149 if d == 0 { 150 d = -1 // don't confuse deadline right now with no deadline 151 } 152 } 153 if err := fd.incref(); err != nil { 154 return err 155 } 156 defer fd.decref() 157 if fd.pd.runtimeCtx == 0 { 158 return ErrNoDeadline 159 } 160 runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode) 161 return nil 162 } 163 164 // IsPollDescriptor reports whether fd is the descriptor being used by the poller. 165 // This is only used for testing. 166 func IsPollDescriptor(fd uintptr) bool { 167 return runtime_isPollServerDescriptor(fd) 168 }