int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout) { WDOG_ID wdog; sem_t sem; int count = 0; int ret; sem_init(&sem, 0, 0); ret = poll_setup(fds, nfds, &sem); if (ret >= 0) { if (timeout >= 0) { /* Wait for the poll event with a timeout. Note that the * millisecond timeout has to be converted to system clock * ticks for wd_start */ wdog = wd_create(); wd_start(wdog, MSEC2TICK(timeout), poll_timeout, 1, (uint32_t)&sem); poll_semtake(&sem); wd_delete(wdog); } else { /* Wait for the poll event with no timeout */ poll_semtake(&sem); } /* Teardown the poll operation and get the count of events */ ret = poll_teardown(fds, nfds, &count); } sem_destroy(&sem); /* Check for errors */ if (ret < 0) { set_errno(-ret); return ERROR; } return count; }
int poll(FAR struct pollfd *fds, nfds_t nfds, int timeout) { struct timespec abstime; irqstate_t flags; sem_t sem; int count = 0; int ret; sem_init(&sem, 0, 0); ret = poll_setup(fds, nfds, &sem); if (ret >= 0) { if (timeout == 0) { /* Poll returns immediately whether we have a poll event or not. */ } else if (timeout > 0) { time_t sec; uint32_t nsec; /* Either wait for either a poll event(s) to occur or for the * specified timeout to elapse with no event. * * NOTE: If a poll event is pending (i.e., the semaphore has already * been incremented), sem_timedwait() will not wait, but will return * immediately. */ sec = timeout / MSEC_PER_SEC; nsec = (timeout - MSEC_PER_SEC * sec) * NSEC_PER_MSEC; /* Make sure that the following are atomic by disabling interrupts. * Interrupts will be re-enabled while we are waiting. */ flags = irqsave(); (void)clock_gettime(CLOCK_REALTIME, &abstime); abstime.tv_sec += sec; abstime.tv_nsec += nsec; if (abstime.tv_nsec > NSEC_PER_SEC) { abstime.tv_sec++; abstime.tv_nsec -= NSEC_PER_SEC; } (void)sem_timedwait(&sem, &abstime); irqrestore(flags); } else { /* Wait for the poll event with no timeout */ poll_semtake(&sem); } /* Teardown the poll operation and get the count of events. Zero will be * returned in the case of a timeout. */ ret = poll_teardown(fds, nfds, &count); } sem_destroy(&sem); /* Check for errors */ if (ret < 0) { set_errno(-ret); return ERROR; } return count; }
/** * Main polling loop for async I/O events. This function will only return when * re_cancel() is called or an error occured. * * @param signalh Optional Signal handler * * @return 0 if success, otherwise errorcode */ int re_main(re_signal_h *signalh) { struct re *re = re_get(); int err; #ifdef HAVE_SIGNAL if (signalh) { (void)signal(SIGINT, signal_handler); (void)signal(SIGALRM, signal_handler); (void)signal(SIGTERM, signal_handler); } #endif if (re->polling) { DEBUG_WARNING("main loop already polling\n"); return EALREADY; } err = poll_setup(re); if (err) goto out; DEBUG_INFO("Using async I/O polling method: `%s'\n", poll_method_name(re->method)); re->polling = true; #ifdef HAVE_ACTSCHED if (METHOD_ACTSCHED == re->method) { err = actsched_start(); goto out; } #endif re_lock(re); for (;;) { if (re->sig) { if (signalh) signalh(re->sig); re->sig = 0; } if (!re->polling) { err = 0; break; } err = fd_poll(re); if (err) { if (EINTR == err) continue; #ifdef DARWIN /* NOTE: workaround for Darwin */ if (EBADF == err) continue; #endif break; } tmr_poll(&re->tmrl); } re_unlock(re); out: re->polling = false; return err; }
/** * Listen for events on a file descriptor * * @param fd File descriptor * @param flags Wanted event flags * @param fh Event handler * @param arg Handler argument * * @return 0 if success, otherwise errorcode */ int fd_listen(int fd, int flags, fd_h *fh, void *arg) { struct re *re = re_get(); int err = 0; DEBUG_INFO("fd_listen: fd=%d flags=0x%02x\n", fd, flags); if (fd < 0) { DEBUG_WARNING("fd_listen: corrupt fd %d\n", fd); return EBADF; } if (flags || fh) { err = poll_setup(re); if (err) return err; } if (fd >= re->maxfds) { if (flags) { DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x" " - Max %d fds\n", fd, flags, re->maxfds); } return EMFILE; } /* Update fh set */ if (re->fhs) { re->fhs[fd].flags = flags; re->fhs[fd].fh = fh; re->fhs[fd].arg = arg; } re->nfds = max(re->nfds, fd+1); switch (re->method) { #ifdef HAVE_POLL case METHOD_POLL: err = set_poll_fds(re, fd, flags); break; #endif #ifdef HAVE_EPOLL case METHOD_EPOLL: if (re->epfd <= 0) return EBADFD; err = set_epoll_fds(re, fd, flags); break; #endif default: break; } if (err) { if (flags && fh) { fd_close(fd); DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x (%m)\n", fd, flags, err); } } return err; }