APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors) { apr_os_sock_t fd; int ret, i; unsigned int nget; pfd_elem_t *ep; struct timespec tv, *tvptr; apr_status_t rv = APR_SUCCESS; if (timeout < 0) { tvptr = NULL; } else { tv.tv_sec = (long) apr_time_sec(timeout); tv.tv_nsec = (long) apr_time_usec(timeout) * 1000; tvptr = &tv; } nget = 1; pollset_lock_rings(); while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { ep = APR_RING_FIRST(&(pollset->add_ring)); APR_RING_REMOVE(ep, link); if (ep->pfd.desc_type == APR_POLL_SOCKET) { fd = ep->pfd.desc.s->socketdes; } else { fd = ep->pfd.desc.f->filedes; } port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, get_event(ep->pfd.reqevents), ep); APR_RING_INSERT_TAIL(&(pollset->query_ring), ep, pfd_elem_t, link); } pollset_unlock_rings(); ret = port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc, &nget, tvptr); (*num) = nget; if (ret == -1) { (*num) = 0; if (errno == ETIME || errno == EINTR) { rv = APR_TIMEUP; } else { rv = APR_EGENERAL; } } else if (nget == 0) { rv = APR_TIMEUP; } else { pollset_lock_rings(); for (i = 0; i < nget; i++) { pollset->result_set[i] = (((pfd_elem_t*)(pollset->port_set[i].portev_user))->pfd); pollset->result_set[i].rtnevents = get_revent(pollset->port_set[i].portev_events); APR_RING_REMOVE((pfd_elem_t*)pollset->port_set[i].portev_user, link); APR_RING_INSERT_TAIL(&(pollset->add_ring), (pfd_elem_t*)pollset->port_set[i].portev_user, pfd_elem_t, link); } pollset_unlock_rings(); if (descriptors) { *descriptors = pollset->result_set; } } pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to be Free Ring */ APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); return rv; }
static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors) { int ret, i, j; apr_status_t rv = APR_SUCCESS; apr_pollfd_t *fdptr; if (timeout > 0) { timeout /= 1000; } ret = epoll_wait(pollset->p->epoll_fd, pollset->p->pollset, pollset->nalloc, timeout); (*num) = ret; if (ret < 0) { rv = apr_get_netos_error(); } else if (ret == 0) { rv = APR_TIMEUP; } else { for (i = 0, j = 0; i < ret; i++) { if (pollset->flags & APR_POLLSET_NOCOPY) { fdptr = (apr_pollfd_t *)(pollset->p->pollset[i].data.ptr); } else { fdptr = &(((pfd_elem_t *) (pollset->p->pollset[i].data.ptr))->pfd); } /* Check if the polled descriptor is our * wakeup pipe. In that case do not put it result set. */ if ((pollset->flags & APR_POLLSET_WAKEABLE) && fdptr->desc_type == APR_POLL_FILE && fdptr->desc.f == pollset->wakeup_pipe[0]) { apr_pollset_drain_wakeup_pipe(pollset); rv = APR_EINTR; } else { pollset->p->result_set[j] = *fdptr; pollset->p->result_set[j].rtnevents = get_epoll_revent(pollset->p->pollset[i].events); j++; } } if (((*num) = j)) { /* any event besides wakeup pipe? */ rv = APR_SUCCESS; if (descriptors) { *descriptors = pollset->p->result_set; } } } if (!(pollset->flags & APR_POLLSET_NOCOPY)) { pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); } return rv; }
static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors) { int ret, i, j; struct timespec tv, *tvptr; apr_status_t rv = APR_SUCCESS; apr_pollfd_t fd; if (timeout < 0) { tvptr = NULL; } else { tv.tv_sec = (long) apr_time_sec(timeout); tv.tv_nsec = (long) apr_time_usec(timeout) * 1000; tvptr = &tv; } ret = kevent(pollset->p->kqueue_fd, NULL, 0, pollset->p->ke_set, pollset->p->setsize, tvptr); (*num) = ret; if (ret < 0) { rv = apr_get_netos_error(); } else if (ret == 0) { rv = APR_TIMEUP; } else { for (i = 0, j = 0; i < ret; i++) { fd = (((pfd_elem_t*)(pollset->p->ke_set[i].udata))->pfd); if ((pollset->flags & APR_POLLSET_WAKEABLE) && fd.desc_type == APR_POLL_FILE && fd.desc.f == pollset->wakeup_pipe[0]) { apr_pollset_drain_wakeup_pipe(pollset); rv = APR_EINTR; } else { pollset->p->result_set[j] = fd; pollset->p->result_set[j].rtnevents = get_kqueue_revent(pollset->p->ke_set[i].filter, pollset->p->ke_set[i].flags); j++; } } if ((*num = j)) { /* any event besides wakeup pipe? */ rv = APR_SUCCESS; if (descriptors) { *descriptors = pollset->p->result_set; } } } pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); return rv; }
static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors) { apr_os_sock_t fd; int ret, i, j; unsigned int nget; pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; apr_pollfd_t fp; nget = 1; pollset_lock_rings(); apr_atomic_inc32(&pollset->p->waiting); while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { ep = APR_RING_FIRST(&(pollset->p->add_ring)); APR_RING_REMOVE(ep, link); if (ep->pfd.desc_type == APR_POLL_SOCKET) { fd = ep->pfd.desc.s->socketdes; } else { fd = ep->pfd.desc.f->filedes; } ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, get_event(ep->pfd.reqevents), ep); if (ret < 0) { rv = apr_get_netos_error(); APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); break; } ep->on_query_ring = 1; APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); } pollset_unlock_rings(); if (rv != APR_SUCCESS) { apr_atomic_dec32(&pollset->p->waiting); return rv; } rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set, pollset->nalloc, &nget, timeout); /* decrease the waiting ASAP to reduce the window for calling port_associate within apr_pollset_add() */ apr_atomic_dec32(&pollset->p->waiting); (*num) = nget; if (nget) { pollset_lock_rings(); for (i = 0, j = 0; i < nget; i++) { fp = (((pfd_elem_t*)(pollset->p->port_set[i].portev_user))->pfd); if ((pollset->flags & APR_POLLSET_WAKEABLE) && fp.desc_type == APR_POLL_FILE && fp.desc.f == pollset->wakeup_pipe[0]) { apr_pollset_drain_wakeup_pipe(pollset); rv = APR_EINTR; } else { pollset->p->result_set[j] = fp; pollset->p->result_set[j].rtnevents = get_revent(pollset->p->port_set[i].portev_events); /* If the ring element is still on the query ring, move it * to the add ring for re-association with the event port * later. (It may have already been moved to the dead ring * by a call to pollset_remove on another thread.) */ ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; if (ep->on_query_ring) { APR_RING_REMOVE(ep, link); ep->on_query_ring = 0; APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, pfd_elem_t, link); } j++; } } pollset_unlock_rings(); if ((*num = j)) { /* any event besides wakeup pipe? */ rv = APR_SUCCESS; if (descriptors) { *descriptors = pollset->p->result_set; } } } pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); return rv; }