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 hurd linux netbsd openbsd windows solaris 6 7package poll 8 9import ( 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 19func runtimeNano() int64 20 21func runtime_pollServerInit() 22func runtime_pollOpen(fd uintptr) (uintptr, int) 23func runtime_pollClose(ctx uintptr) 24func runtime_pollWait(ctx uintptr, mode int) int 25func runtime_pollWaitCanceled(ctx uintptr, mode int) int 26func runtime_pollReset(ctx uintptr, mode int) int 27func runtime_pollSetDeadline(ctx uintptr, d int64, mode int) 28func runtime_pollUnblock(ctx uintptr) 29func runtime_isPollServerDescriptor(fd uintptr) bool 30 31type pollDesc struct { 32 runtimeCtx uintptr 33} 34 35var serverInit sync.Once 36 37func (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 51func (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. 60func (pd *pollDesc) evict() { 61 if pd.runtimeCtx == 0 { 62 return 63 } 64 runtime_pollUnblock(pd.runtimeCtx) 65} 66 67func (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 75func (pd *pollDesc) prepareRead(isFile bool) error { 76 return pd.prepare('r', isFile) 77} 78 79func (pd *pollDesc) prepareWrite(isFile bool) error { 80 return pd.prepare('w', isFile) 81} 82 83func (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 91func (pd *pollDesc) waitRead(isFile bool) error { 92 return pd.wait('r', isFile) 93} 94 95func (pd *pollDesc) waitWrite(isFile bool) error { 96 return pd.wait('w', isFile) 97} 98 99func (pd *pollDesc) waitCanceled(mode int) { 100 if pd.runtimeCtx == 0 { 101 return 102 } 103 runtime_pollWaitCanceled(pd.runtimeCtx, mode) 104} 105 106func (pd *pollDesc) pollable() bool { 107 return pd.runtimeCtx != 0 108} 109 110func 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 case 3: 119 return ErrNotPollable 120 } 121 println("unreachable: ", res) 122 panic("unreachable") 123} 124 125// SetDeadline sets the read and write deadlines associated with fd. 126func (fd *FD) SetDeadline(t time.Time) error { 127 return setDeadlineImpl(fd, t, 'r'+'w') 128} 129 130// SetReadDeadline sets the read deadline associated with fd. 131func (fd *FD) SetReadDeadline(t time.Time) error { 132 return setDeadlineImpl(fd, t, 'r') 133} 134 135// SetWriteDeadline sets the write deadline associated with fd. 136func (fd *FD) SetWriteDeadline(t time.Time) error { 137 return setDeadlineImpl(fd, t, 'w') 138} 139 140func setDeadlineImpl(fd *FD, t time.Time, mode int) error { 141 var d int64 142 if !t.IsZero() { 143 d = int64(time.Until(t)) 144 if d == 0 { 145 d = -1 // don't confuse deadline right now with no deadline 146 } 147 } 148 if err := fd.incref(); err != nil { 149 return err 150 } 151 defer fd.decref() 152 if fd.pd.runtimeCtx == 0 { 153 return ErrNoDeadline 154 } 155 runtime_pollSetDeadline(fd.pd.runtimeCtx, d, mode) 156 return nil 157} 158 159// IsPollDescriptor reports whether fd is the descriptor being used by the poller. 160// This is only used for testing. 161func IsPollDescriptor(fd uintptr) bool { 162 return runtime_isPollServerDescriptor(fd) 163} 164