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 }