github.com/bir3/gocompiler@v0.9.2202/src/internal/poll/fd_plan9.go (about) 1 // Copyright 2009 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 package poll 6 7 import ( 8 "errors" 9 "io" 10 "sync" 11 "time" 12 ) 13 14 type FD struct { 15 // Lock sysfd and serialize access to Read and Write methods. 16 fdmu fdMutex 17 18 Destroy func() 19 20 // deadlines 21 rmu sync.Mutex 22 wmu sync.Mutex 23 raio *asyncIO 24 waio *asyncIO 25 rtimer *time.Timer 26 wtimer *time.Timer 27 rtimedout bool // set true when read deadline has been reached 28 wtimedout bool // set true when write deadline has been reached 29 30 // Whether this is a normal file. 31 // On Plan 9 we do not use this package for ordinary files, 32 // so this is always false, but the field is present because 33 // shared code in fd_mutex.go checks it. 34 isFile bool 35 } 36 37 // We need this to close out a file descriptor when it is unlocked, 38 // but the real implementation has to live in the net package because 39 // it uses os.File's. 40 func (fd *FD) destroy() error { 41 if fd.Destroy != nil { 42 fd.Destroy() 43 } 44 return nil 45 } 46 47 // Close handles the locking for closing an FD. The real operation 48 // is in the net package. 49 func (fd *FD) Close() error { 50 if !fd.fdmu.increfAndClose() { 51 return errClosing(fd.isFile) 52 } 53 return nil 54 } 55 56 // Read implements io.Reader. 57 func (fd *FD) Read(fn func([]byte) (int, error), b []byte) (int, error) { 58 if err := fd.readLock(); err != nil { 59 return 0, err 60 } 61 defer fd.readUnlock() 62 if len(b) == 0 { 63 return 0, nil 64 } 65 fd.rmu.Lock() 66 if fd.rtimedout { 67 fd.rmu.Unlock() 68 return 0, ErrDeadlineExceeded 69 } 70 fd.raio = newAsyncIO(fn, b) 71 fd.rmu.Unlock() 72 n, err := fd.raio.Wait() 73 fd.raio = nil 74 if isHangup(err) { 75 err = io.EOF 76 } 77 if isInterrupted(err) { 78 err = ErrDeadlineExceeded 79 } 80 return n, err 81 } 82 83 // Write implements io.Writer. 84 func (fd *FD) Write(fn func([]byte) (int, error), b []byte) (int, error) { 85 if err := fd.writeLock(); err != nil { 86 return 0, err 87 } 88 defer fd.writeUnlock() 89 fd.wmu.Lock() 90 if fd.wtimedout { 91 fd.wmu.Unlock() 92 return 0, ErrDeadlineExceeded 93 } 94 fd.waio = newAsyncIO(fn, b) 95 fd.wmu.Unlock() 96 n, err := fd.waio.Wait() 97 fd.waio = nil 98 if isInterrupted(err) { 99 err = ErrDeadlineExceeded 100 } 101 return n, err 102 } 103 104 // SetDeadline sets the read and write deadlines associated with fd. 105 func (fd *FD) SetDeadline(t time.Time) error { 106 return setDeadlineImpl(fd, t, 'r'+'w') 107 } 108 109 // SetReadDeadline sets the read deadline associated with fd. 110 func (fd *FD) SetReadDeadline(t time.Time) error { 111 return setDeadlineImpl(fd, t, 'r') 112 } 113 114 // SetWriteDeadline sets the write deadline associated with fd. 115 func (fd *FD) SetWriteDeadline(t time.Time) error { 116 return setDeadlineImpl(fd, t, 'w') 117 } 118 119 func setDeadlineImpl(fd *FD, t time.Time, mode int) error { 120 d := t.Sub(time.Now()) 121 if mode == 'r' || mode == 'r'+'w' { 122 fd.rmu.Lock() 123 defer fd.rmu.Unlock() 124 if fd.rtimer != nil { 125 fd.rtimer.Stop() 126 fd.rtimer = nil 127 } 128 fd.rtimedout = false 129 } 130 if mode == 'w' || mode == 'r'+'w' { 131 fd.wmu.Lock() 132 defer fd.wmu.Unlock() 133 if fd.wtimer != nil { 134 fd.wtimer.Stop() 135 fd.wtimer = nil 136 } 137 fd.wtimedout = false 138 } 139 if !t.IsZero() && d > 0 { 140 // Interrupt I/O operation once timer has expired 141 if mode == 'r' || mode == 'r'+'w' { 142 var timer *time.Timer 143 timer = time.AfterFunc(d, func() { 144 fd.rmu.Lock() 145 defer fd.rmu.Unlock() 146 if fd.rtimer != timer { 147 // deadline was changed 148 return 149 } 150 fd.rtimedout = true 151 if fd.raio != nil { 152 fd.raio.Cancel() 153 } 154 }) 155 fd.rtimer = timer 156 } 157 if mode == 'w' || mode == 'r'+'w' { 158 var timer *time.Timer 159 timer = time.AfterFunc(d, func() { 160 fd.wmu.Lock() 161 defer fd.wmu.Unlock() 162 if fd.wtimer != timer { 163 // deadline was changed 164 return 165 } 166 fd.wtimedout = true 167 if fd.waio != nil { 168 fd.waio.Cancel() 169 } 170 }) 171 fd.wtimer = timer 172 } 173 } 174 if !t.IsZero() && d <= 0 { 175 // Interrupt current I/O operation 176 if mode == 'r' || mode == 'r'+'w' { 177 fd.rtimedout = true 178 if fd.raio != nil { 179 fd.raio.Cancel() 180 } 181 } 182 if mode == 'w' || mode == 'r'+'w' { 183 fd.wtimedout = true 184 if fd.waio != nil { 185 fd.waio.Cancel() 186 } 187 } 188 } 189 return nil 190 } 191 192 // On Plan 9 only, expose the locking for the net code. 193 194 // ReadLock wraps FD.readLock. 195 func (fd *FD) ReadLock() error { 196 return fd.readLock() 197 } 198 199 // ReadUnlock wraps FD.readUnlock. 200 func (fd *FD) ReadUnlock() { 201 fd.readUnlock() 202 } 203 204 func isHangup(err error) bool { 205 return err != nil && stringsHasSuffix(err.Error(), "Hangup") 206 } 207 208 func isInterrupted(err error) bool { 209 return err != nil && stringsHasSuffix(err.Error(), "interrupted") 210 } 211 212 // IsPollDescriptor reports whether fd is the descriptor being used by the poller. 213 // This is only used for testing. 214 func IsPollDescriptor(fd uintptr) bool { 215 return false 216 } 217 218 // RawControl invokes the user-defined function f for a non-IO 219 // operation. 220 func (fd *FD) RawControl(f func(uintptr)) error { 221 return errors.New("not implemented") 222 } 223 224 // RawRead invokes the user-defined function f for a read operation. 225 func (fd *FD) RawRead(f func(uintptr) bool) error { 226 return errors.New("not implemented") 227 } 228 229 // RawWrite invokes the user-defined function f for a write operation. 230 func (fd *FD) RawWrite(f func(uintptr) bool) error { 231 return errors.New("not implemented") 232 }