static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, apr_interval_time_t timeout, apr_pollcb_cb_t func, void *baton) { apr_pollfd_t *pollfd; apr_status_t rv; unsigned int i, nget = 1; rv = call_port_getn(pollcb->fd, pollcb->pollset.port, pollcb->nalloc, &nget, timeout); if (nget) { for (i = 0; i < nget; i++) { pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user); pollfd->rtnevents = get_revent(pollcb->pollset.port[i].portev_events); rv = func(baton, pollfd); if (rv) { return rv; } rv = apr_pollcb_add(pollcb, pollfd); } } return rv; }
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) { int rv; apr_uint32_t i, j; if (timeout > 0) { timeout /= 1000; } rv = poll(pollset->pollset, pollset->nelts, timeout); (*num) = rv; if (rv < 0) { return apr_get_netos_error(); } if (rv == 0) { return APR_TIMEUP; } j = 0; for (i = 0; i < pollset->nelts; i++) { if (pollset->pollset[i].revents != 0) { pollset->result_set[j] = pollset->query_set[i]; pollset->result_set[j].rtnevents = get_revent(pollset->pollset[i].revents); j++; } } *descriptors = pollset->result_set; return APR_SUCCESS; }
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; apr_status_t rv = APR_SUCCESS; if (timeout > 0) { timeout /= 1000; } #ifdef WIN32 ret = WSAPoll(pollset->p->pollset, pollset->nelts, (int)timeout); #else ret = poll(pollset->p->pollset, pollset->nelts, timeout); #endif (*num) = ret; if (ret < 0) { return apr_get_netos_error(); } else if (ret == 0) { return APR_TIMEUP; } else { apr_uint32_t i, j; for (i = 0, j = 0; i < pollset->nelts; i++) { if (pollset->p->pollset[i].revents != 0) { /* Check if the polled descriptor is our * wakeup pipe. In that case do not put it result set. */ if ((pollset->flags & APR_POLLSET_WAKEABLE) && pollset->p->query_set[i].desc_type == APR_POLL_FILE && pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(pollset->wakeup_pipe); rv = APR_EINTR; } else { pollset->p->result_set[j] = pollset->p->query_set[i]; pollset->p->result_set[j].rtnevents = get_revent(pollset->p->pollset[i].revents); j++; } } } if (((*num) = j) > 0) rv = APR_SUCCESS; } if (descriptors && (*num)) *descriptors = pollset->p->result_set; return rv; }
static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, apr_interval_time_t timeout, apr_pollcb_cb_t func, void *baton) { int ret; apr_status_t rv = APR_SUCCESS; apr_uint32_t i; #ifdef WIN32 /* WSAPoll() requires at least one socket. */ if (pollcb->nelts == 0) { if (timeout > 0) { apr_sleep(timeout); return APR_TIMEUP; } return APR_SUCCESS; } if (timeout > 0) { timeout /= 1000; } ret = WSAPoll(pollcb->pollset.ps, pollcb->nelts, (int)timeout); #else if (timeout > 0) { timeout /= 1000; } ret = poll(pollcb->pollset.ps, pollcb->nelts, timeout); #endif if (ret < 0) { return apr_get_netos_error(); } else if (ret == 0) { return APR_TIMEUP; } else { for (i = 0; i < pollcb->nelts; i++) { if (pollcb->pollset.ps[i].revents != 0) { apr_pollfd_t *pollfd = pollcb->copyset[i]; pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents); rv = func(baton, pollfd); if (rv) { return rv; } } } } return rv; }
static apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, apr_interval_time_t timeout, apr_pollcb_cb_t func, void *baton) { int ret; apr_status_t rv = APR_SUCCESS; apr_uint32_t i; if (timeout > 0) { timeout /= 1000; } #ifdef WIN32 ret = WSAPoll(pollcb->pollset.ps, pollcb->nelts, (int)timeout); #else ret = poll(pollcb->pollset.ps, pollcb->nelts, timeout); #endif if (ret < 0) { return apr_get_netos_error(); } else if (ret == 0) { return APR_TIMEUP; } else { for (i = 0; i < pollcb->nelts; i++) { if (pollcb->pollset.ps[i].revents != 0) { apr_pollfd_t *pollfd = pollcb->copyset[i]; if ((pollcb->flags & APR_POLLSET_WAKEABLE) && pollfd->desc_type == APR_POLL_FILE && pollfd->desc.f == pollcb->wakeup_pipe[0]) { apr_poll_drain_wakeup_pipe(pollcb->wakeup_pipe); return APR_EINTR; } pollfd->rtnevents = get_revent(pollcb->pollset.ps[i].revents); rv = func(baton, pollfd); if (rv) { return rv; } } } } return rv; }
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; }
APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num, apr_int32_t *nsds, apr_interval_time_t timeout) { int i, num_to_poll; #ifdef HAVE_VLA /* XXX: I trust that this is a segv when insufficient stack exists? */ struct pollfd pollset[num]; #elif defined(HAVE_ALLOCA) struct pollfd *pollset = alloca(sizeof(struct pollfd) * num); if (!pollset) return APR_ENOMEM; #else struct pollfd tmp_pollset[SMALL_POLLSET_LIMIT]; struct pollfd *pollset; if (num <= SMALL_POLLSET_LIMIT) { pollset = tmp_pollset; } else { /* This does require O(n) to copy the descriptors to the internal * mapping. */ pollset = malloc(sizeof(struct pollfd) * num); /* The other option is adding an apr_pool_abort() fn to invoke * the pool's out of memory handler */ if (!pollset) return APR_ENOMEM; } #endif for (i = 0; i < num; i++) { if (aprset[i].desc_type == APR_POLL_SOCKET) { pollset[i].fd = aprset[i].desc.s->socketdes; } else if (aprset[i].desc_type == APR_POLL_FILE) { pollset[i].fd = aprset[i].desc.f->filedes; } else { break; } pollset[i].events = get_event(aprset[i].reqevents); } num_to_poll = i; if (timeout > 0) { timeout /= 1000; /* convert microseconds to milliseconds */ } i = poll(pollset, num_to_poll, timeout); (*nsds) = i; if (i > 0) { /* poll() sets revents only if an event was signalled; * we don't promise to set rtnevents unless an event * was signalled */ for (i = 0; i < num; i++) { aprset[i].rtnevents = get_revent(pollset[i].revents); } } #if !defined(HAVE_VLA) && !defined(HAVE_ALLOCA) if (num > SMALL_POLLSET_LIMIT) { free(pollset); } #endif if ((*nsds) < 0) { return apr_get_netos_error(); } if ((*nsds) == 0) { return APR_TIMEUP; } return APR_SUCCESS; }
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; }