github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/netpoll_aix.go (about) 1 // Copyright 2018 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 runtime 6 7 import "unsafe" 8 9 // This is based on the former libgo/runtime/netpoll_select.c implementation 10 // except that it uses poll instead of select and is written in Go. 11 // It's also based on Solaris implementation for the arming mechanisms 12 13 //go:cgo_import_dynamic libc_poll poll "libc.a/shr_64.o" 14 //go:linkname libc_poll libc_poll 15 16 var libc_poll libFunc 17 18 //go:nosplit 19 func poll(pfds *pollfd, npfds uintptr, timeout uintptr) (int32, int32) { 20 r, err := syscall3(&libc_poll, uintptr(unsafe.Pointer(pfds)), npfds, timeout) 21 return int32(r), int32(err) 22 } 23 24 //go:nosplit 25 func fcntl(fd, cmd int32, arg uintptr) int32 { 26 r, _ := syscall3(&libc_fcntl, uintptr(fd), uintptr(cmd), arg) 27 return int32(r) 28 } 29 30 // pollfd represents the poll structure for AIX operating system. 31 type pollfd struct { 32 fd int32 33 events int16 34 revents int16 35 } 36 37 const _POLLIN = 0x0001 38 const _POLLOUT = 0x0002 39 const _POLLHUP = 0x2000 40 const _POLLERR = 0x4000 41 const _O_NONBLOCK = 0x4 42 43 var ( 44 pfds []pollfd 45 pds []*pollDesc 46 mtxpoll mutex 47 mtxset mutex 48 rdwake int32 49 wrwake int32 50 pendingUpdates int32 51 ) 52 53 const pollVerbose = false 54 55 func netpollinit() { 56 var p [2]int32 57 58 // Create the pipe we use to wakeup poll. 59 if err := pipe(&p[0]); err < 0 { 60 throw("netpollinit: failed to create pipe") 61 } 62 rdwake = p[0] 63 wrwake = p[1] 64 65 fl := uintptr(fcntl(rdwake, _F_GETFL, 0)) 66 fcntl(rdwake, _F_SETFL, fl|_O_NONBLOCK) 67 fcntl(rdwake, _F_SETFD, _FD_CLOEXEC) 68 69 fl = uintptr(fcntl(wrwake, _F_GETFL, 0)) 70 fcntl(wrwake, _F_SETFL, fl|_O_NONBLOCK) 71 fcntl(wrwake, _F_SETFD, _FD_CLOEXEC) 72 73 // Pre-allocate array of pollfd structures for poll. 74 if pollVerbose { 75 println("*** allocating") 76 } 77 pfds = make([]pollfd, 1, 128) 78 if pollVerbose { 79 println("*** allocating done", &pfds[0]) 80 } 81 82 // Poll the read side of the pipe. 83 pfds[0].fd = rdwake 84 pfds[0].events = _POLLIN 85 86 pds = make([]*pollDesc, 1, 128) 87 pds[0] = nil 88 } 89 90 func netpolldescriptor() uintptr { 91 // Both fd must be returned 92 if rdwake > 0xFFFF || wrwake > 0xFFFF { 93 throw("netpolldescriptor: invalid fd number") 94 } 95 return uintptr(rdwake<<16 | wrwake) 96 } 97 98 // netpollwakeup writes on wrwake to wakeup poll before any changes. 99 func netpollwakeup() { 100 if pendingUpdates == 0 { 101 pendingUpdates = 1 102 if pollVerbose { 103 println("*** writing 1 byte") 104 } 105 b := [1]byte{0} 106 write(uintptr(wrwake), unsafe.Pointer(&b[0]), 1) 107 } 108 } 109 110 func netpollopen(fd uintptr, pd *pollDesc) int32 { 111 if pollVerbose { 112 println("*** netpollopen", fd) 113 } 114 lock(&mtxpoll) 115 netpollwakeup() 116 117 lock(&mtxset) 118 unlock(&mtxpoll) 119 120 pd.user = uint32(len(pfds)) 121 pfds = append(pfds, pollfd{fd: int32(fd)}) 122 pds = append(pds, pd) 123 unlock(&mtxset) 124 return 0 125 } 126 127 func netpollclose(fd uintptr) int32 { 128 if pollVerbose { 129 println("*** netpollclose", fd) 130 } 131 lock(&mtxpoll) 132 netpollwakeup() 133 134 lock(&mtxset) 135 unlock(&mtxpoll) 136 137 for i := 0; i < len(pfds); i++ { 138 if pfds[i].fd == int32(fd) { 139 pfds[i] = pfds[len(pfds)-1] 140 pfds = pfds[:len(pfds)-1] 141 142 pds[i] = pds[len(pds)-1] 143 pds[i].user = uint32(i) 144 pds = pds[:len(pds)-1] 145 break 146 } 147 } 148 unlock(&mtxset) 149 return 0 150 } 151 152 func netpollarm(pd *pollDesc, mode int) { 153 if pollVerbose { 154 println("*** netpollarm", pd.fd, mode) 155 } 156 lock(&mtxpoll) 157 netpollwakeup() 158 159 lock(&mtxset) 160 unlock(&mtxpoll) 161 162 switch mode { 163 case 'r': 164 pfds[pd.user].events |= _POLLIN 165 case 'w': 166 pfds[pd.user].events |= _POLLOUT 167 } 168 unlock(&mtxset) 169 } 170 171 //go:nowritebarrierrec 172 func netpoll(block bool) gList { 173 timeout := ^uintptr(0) 174 if !block { 175 timeout = 0 176 return gList{} 177 } 178 if pollVerbose { 179 println("*** netpoll", block) 180 } 181 retry: 182 lock(&mtxpoll) 183 lock(&mtxset) 184 pendingUpdates = 0 185 unlock(&mtxpoll) 186 187 if pollVerbose { 188 println("*** netpoll before poll") 189 } 190 n, e := poll(&pfds[0], uintptr(len(pfds)), timeout) 191 if pollVerbose { 192 println("*** netpoll after poll", n) 193 } 194 if n < 0 { 195 if e != _EINTR { 196 println("errno=", e, " len(pfds)=", len(pfds)) 197 throw("poll failed") 198 } 199 if pollVerbose { 200 println("*** poll failed") 201 } 202 unlock(&mtxset) 203 goto retry 204 } 205 // Check if some descriptors need to be changed 206 if n != 0 && pfds[0].revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 { 207 var b [1]byte 208 for read(rdwake, unsafe.Pointer(&b[0]), 1) == 1 { 209 if pollVerbose { 210 println("*** read 1 byte from pipe") 211 } 212 } 213 // Do not look at the other fds in this case as the mode may have changed 214 // XXX only additions of flags are made, so maybe it is ok 215 unlock(&mtxset) 216 goto retry 217 } 218 var toRun gList 219 for i := 0; i < len(pfds) && n > 0; i++ { 220 pfd := &pfds[i] 221 222 var mode int32 223 if pfd.revents&(_POLLIN|_POLLHUP|_POLLERR) != 0 { 224 mode += 'r' 225 pfd.events &= ^_POLLIN 226 } 227 if pfd.revents&(_POLLOUT|_POLLHUP|_POLLERR) != 0 { 228 mode += 'w' 229 pfd.events &= ^_POLLOUT 230 } 231 if mode != 0 { 232 if pollVerbose { 233 println("*** netpollready i=", i, "revents=", pfd.revents, "events=", pfd.events, "pd=", pds[i]) 234 } 235 netpollready(&toRun, pds[i], mode) 236 n-- 237 } 238 } 239 unlock(&mtxset) 240 if block && toRun.empty() { 241 goto retry 242 } 243 if pollVerbose { 244 println("*** netpoll returning end") 245 } 246 return toRun 247 }