github.com/sandwichdev/go-internals@v0.0.0-20210605002614-12311ac6b2c5/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 errnoErr(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 // Error values returned by runtime_pollReset and runtime_pollWait. 111 // These must match the values in runtime/netpoll.go. 112 const ( 113 pollNoError = 0 114 pollErrClosing = 1 115 pollErrTimeout = 2 116 pollErrNotPollable = 3 117 ) 118 119 func convertErr(res int, isFile bool) error { 120 switch res { 121 case pollNoError: 122 return nil 123 case pollErrClosing: 124 return errClosing(isFile) 125 case pollErrTimeout: 126 return ErrDeadlineExceeded 127 case pollErrNotPollable: 128 return ErrNotPollable 129 } 130 println("unreachable: ", res) 131 panic("unreachable") 132 } 133 134 // SetDeadline sets the read and write deadlines associated with fd. 135 func (fd *FD) SetDeadline(t time.Time) error { 136 return setDeadlineImpl(fd, t, 'r'+'w') 137 } 138 139 // SetReadDeadline sets the read deadline associated with fd. 140 func (fd *FD) SetReadDeadline(t time.Time) error { 141 return setDeadlineImpl(fd, t, 'r') 142 } 143 144 // SetWriteDeadline sets the write deadline associated with fd. 145 func (fd *FD) SetWriteDeadline(t time.Time) error { 146 return setDeadlineImpl(fd, t, 'w') 147 } 148 149 func setDeadlineImpl(fd *FD, t time.Time, mode int) error { 150 var d int64 151 if !t.IsZero() { 152 d = int64(time.Until(t)) 153 if d == 0 { 154 d = -1 // don't confuse deadline right now with no deadline 155 } 156 } 157 if err := fd.incref(); err != nil { 158 return err 159 } 160 defer fd.decref() 161 if fd.pd.runtimeCtx == 0 { 162 return ErrNoDeadline 163 } 164 runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode) 165 return nil 166 } 167 168 // IsPollDescriptor reports whether fd is the descriptor being used by the poller. 169 // This is only used for testing. 170 func IsPollDescriptor(fd uintptr) bool { 171 return runtime_isPollServerDescriptor(fd) 172 }