* Update revents in each struct pollfd. * Optionally update select_waiting in struct lwip_sock. * * @param fds array of structures to update * @param nfds number of structures in fds * @param opts what to update and how * @return number of structures that have revents != 0 */
| 2212 | * @return number of structures that have revents != 0 |
| 2213 | */ |
| 2214 | static int |
| 2215 | lwip_pollscan(struct pollfd *fds, nfds_t nfds, enum lwip_pollscan_opts opts) |
| 2216 | { |
| 2217 | int nready = 0; |
| 2218 | nfds_t fdi; |
| 2219 | struct lwip_sock *sock; |
| 2220 | SYS_ARCH_DECL_PROTECT(lev); |
| 2221 | |
| 2222 | /* Go through each struct pollfd in the array. */ |
| 2223 | for (fdi = 0; fdi < nfds; fdi++) { |
| 2224 | if ((opts & LWIP_POLLSCAN_CLEAR) != 0) { |
| 2225 | fds[fdi].revents = 0; |
| 2226 | } |
| 2227 | |
| 2228 | /* Negative fd means the caller wants us to ignore this struct. |
| 2229 | POLLNVAL means we already detected that the fd is invalid; |
| 2230 | if another thread has since opened a new socket with that fd, |
| 2231 | we must not use that socket. */ |
| 2232 | if (fds[fdi].fd >= 0 && (fds[fdi].revents & POLLNVAL) == 0) { |
| 2233 | /* First get the socket's status (protected)... */ |
| 2234 | SYS_ARCH_PROTECT(lev); |
| 2235 | sock = tryget_socket_unconn_locked(fds[fdi].fd); |
| 2236 | if (sock != NULL) { |
| 2237 | void* lastdata = sock->lastdata.pbuf; |
| 2238 | s16_t rcvevent = sock->rcvevent; |
| 2239 | u16_t sendevent = sock->sendevent; |
| 2240 | u16_t errevent = sock->errevent; |
| 2241 | |
| 2242 | if ((opts & LWIP_POLLSCAN_INC_WAIT) != 0) { |
| 2243 | sock->select_waiting++; |
| 2244 | if (sock->select_waiting == 0) { |
| 2245 | /* overflow - too many threads waiting */ |
| 2246 | sock->select_waiting--; |
| 2247 | nready = -1; |
| 2248 | SYS_ARCH_UNPROTECT(lev); |
| 2249 | done_socket(sock); |
| 2250 | break; |
| 2251 | } |
| 2252 | } else if ((opts & LWIP_POLLSCAN_DEC_WAIT) != 0) { |
| 2253 | /* for now, handle select_waiting==0... */ |
| 2254 | LWIP_ASSERT("sock->select_waiting > 0", sock->select_waiting > 0); |
| 2255 | if (sock->select_waiting > 0) { |
| 2256 | sock->select_waiting--; |
| 2257 | } |
| 2258 | } |
| 2259 | SYS_ARCH_UNPROTECT(lev); |
| 2260 | done_socket(sock); |
| 2261 | |
| 2262 | /* ... then examine it: */ |
| 2263 | /* See if netconn of this socket is ready for read */ |
| 2264 | if ((fds[fdi].events & POLLIN) != 0 && ((lastdata != NULL) || (rcvevent > 0))) { |
| 2265 | fds[fdi].revents |= POLLIN; |
| 2266 | LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_pollscan: fd=%d ready for reading\n", fds[fdi].fd)); |
| 2267 | } |
| 2268 | /* See if netconn of this socket is ready for write */ |
| 2269 | if ((fds[fdi].events & POLLOUT) != 0 && (sendevent != 0)) { |
| 2270 | fds[fdi].revents |= POLLOUT; |
| 2271 | LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_pollscan: fd=%d ready for writing\n", fds[fdi].fd)); |
no test coverage detected