diff options
author | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:22 +0100 |
---|---|---|
committer | Stefan Fritsch <sf@sfritsch.de> | 2011-12-27 19:42:22 +0100 |
commit | 0268977037115539ad65a26e858aa0df8d18cd13 (patch) | |
tree | f761b541b04d08b75e32efc6c293111c61a8b79c /srclib/apr/poll/unix | |
parent | 9e615cb6aa4afcee97f8a1646e5a586261a7b81f (diff) | |
download | apache2-0268977037115539ad65a26e858aa0df8d18cd13.tar.gz |
Upstream tarball 2.2.9upstream/2.2.9
Diffstat (limited to 'srclib/apr/poll/unix')
-rw-r--r-- | srclib/apr/poll/unix/epoll.c | 249 | ||||
-rw-r--r-- | srclib/apr/poll/unix/kqueue.c | 162 | ||||
-rw-r--r-- | srclib/apr/poll/unix/poll.c | 33 | ||||
-rw-r--r-- | srclib/apr/poll/unix/port.c | 174 | ||||
-rw-r--r-- | srclib/apr/poll/unix/select.c | 29 |
5 files changed, 580 insertions, 67 deletions
diff --git a/srclib/apr/poll/unix/epoll.c b/srclib/apr/poll/unix/epoll.c index 388c67c0..7a3831be 100644 --- a/srclib/apr/poll/unix/epoll.c +++ b/srclib/apr/poll/unix/epoll.c @@ -101,10 +101,11 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, *pollset = apr_palloc(p, sizeof(**pollset)); #if APR_HAS_THREADS - if (flags & APR_POLLSET_THREADSAFE && + if ((flags & APR_POLLSET_THREADSAFE) && + !(flags & APR_POLLSET_NOCOPY) && ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, APR_THREAD_MUTEX_DEFAULT, - p) != APR_SUCCESS))) { + p)) != APR_SUCCESS)) { *pollset = NULL; return rv; } @@ -123,10 +124,11 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, apr_pool_cleanup_register(p, *pollset, backend_cleanup, backend_cleanup); (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); - APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); - APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); - APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); - + if (!(flags & APR_POLLSET_NOCOPY)) { + APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); + } return APR_SUCCESS; } @@ -138,25 +140,30 @@ APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { - struct epoll_event ev; + struct epoll_event ev = {0}; int ret = -1; - pfd_elem_t *elem; + pfd_elem_t *elem = NULL; apr_status_t rv = APR_SUCCESS; - pollset_lock_rings(); + ev.events = get_epoll_event(descriptor->reqevents); - if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->free_ring)); - APR_RING_REMOVE(elem, link); + if (pollset->flags & APR_POLLSET_NOCOPY) { + ev.data.ptr = (void *)descriptor; } else { - elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); - APR_RING_ELEM_INIT(elem, link); - } - elem->pfd = *descriptor; + pollset_lock_rings(); - ev.events = get_epoll_event(descriptor->reqevents); - ev.data.ptr = elem; + if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; + ev.data.ptr = elem; + } if (descriptor->desc_type == APR_POLL_SOCKET) { ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, descriptor->desc.s->socketdes, &ev); @@ -166,17 +173,23 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, descriptor->desc.f->filedes, &ev); } - if (0 != ret) { - rv = APR_EBADF; - APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + if (pollset->flags & APR_POLLSET_NOCOPY) { + if (0 != ret) { + rv = APR_EBADF; + } } else { - pollset->nelts++; - APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + if (0 != ret) { + rv = APR_EBADF; + APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + } + else { + pollset->nelts++; + APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + } + pollset_unlock_rings(); } - pollset_unlock_rings(); - return rv; } @@ -188,8 +201,6 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, struct epoll_event ev; int ret = -1; - pollset_lock_rings(); - ev.events = get_epoll_event(descriptor->reqevents); if (descriptor->desc_type == APR_POLL_SOCKET) { @@ -204,22 +215,26 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, rv = APR_NOTFOUND; } - if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { - for (ep = APR_RING_FIRST(&(pollset->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->query_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { - - if (descriptor->desc.s == ep->pfd.desc.s) { - APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->dead_ring), - ep, pfd_elem_t, link); - break; + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + pollset_lock_rings(); + + if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { + for (ep = APR_RING_FIRST(&(pollset->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->dead_ring), + ep, pfd_elem_t, link); + break; + } } } - } - pollset_unlock_rings(); + pollset_unlock_rings(); + } return rv; } @@ -247,11 +262,21 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, rv = APR_TIMEUP; } else { - for (i = 0; i < ret; i++) { - pollset->result_set[i] = - (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd); - pollset->result_set[i].rtnevents = - get_epoll_revent(pollset->pollset[i].events); + if (pollset->flags & APR_POLLSET_NOCOPY) { + for (i = 0; i < ret; i++) { + pollset->result_set[i] = + *((apr_pollfd_t *) (pollset->pollset[i].data.ptr)); + pollset->result_set[i].rtnevents = + get_epoll_revent(pollset->pollset[i].events); + } + } + else { + for (i = 0; i < ret; i++) { + pollset->result_set[i] = + (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd); + pollset->result_set[i].rtnevents = + get_epoll_revent(pollset->pollset[i].events); + } } if (descriptors) { @@ -259,13 +284,139 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, } } - pollset_lock_rings(); + if (!(pollset->flags & APR_POLLSET_NOCOPY)) { + 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; +} + +struct apr_pollcb_t { + apr_pool_t *pool; + apr_uint32_t nalloc; + struct epoll_event *pollset; + int epoll_fd; +}; + +static apr_status_t cb_cleanup(void *p_) +{ + apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; + close(pollcb->epoll_fd); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + int fd; + + fd = epoll_create(size); + + if (fd < 0) { + *pollcb = NULL; + return apr_get_netos_error(); + } + + *pollcb = apr_palloc(p, sizeof(**pollcb)); + (*pollcb)->nalloc = size; + (*pollcb)->pool = p; + (*pollcb)->epoll_fd = fd; + (*pollcb)->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); + apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + struct epoll_event ev; + int ret; + + ev.events = get_epoll_event(descriptor->reqevents); + ev.data.ptr = (void *)descriptor; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD, + descriptor->desc.s->socketdes, &ev); + } + else { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_ADD, + descriptor->desc.f->filedes, &ev); + } + + if (ret == -1) { + return apr_get_netos_error(); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + apr_status_t rv = APR_SUCCESS; + struct epoll_event ev; + int ret = -1; + + ev.events = get_epoll_event(descriptor->reqevents); + + if (descriptor->desc_type == APR_POLL_SOCKET) { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL, + descriptor->desc.s->socketdes, &ev); + } + else { + ret = epoll_ctl(pollcb->epoll_fd, EPOLL_CTL_DEL, + descriptor->desc.f->filedes, &ev); + } + + if (ret < 0) { + rv = APR_NOTFOUND; + } + + return rv; +} - /* 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(); +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton) +{ + int ret, i; + apr_status_t rv = APR_SUCCESS; + + if (timeout > 0) { + timeout /= 1000; + } + + ret = epoll_wait(pollcb->epoll_fd, pollcb->pollset, pollcb->nalloc, + timeout); + if (ret < 0) { + rv = apr_get_netos_error(); + } + else if (ret == 0) { + rv = APR_TIMEUP; + } + else { + for (i = 0; i < ret; i++) { + apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset[i].data.ptr); + pollfd->rtnevents = get_epoll_revent(pollcb->pollset[i].events); + rv = func(baton, pollfd); + if (rv) { + return rv; + } + } + } + return rv; } diff --git a/srclib/apr/poll/unix/kqueue.c b/srclib/apr/poll/unix/kqueue.c index fdabd487..501953dc 100644 --- a/srclib/apr/poll/unix/kqueue.c +++ b/srclib/apr/poll/unix/kqueue.c @@ -75,7 +75,7 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, APR_THREAD_MUTEX_DEFAULT, - p) != APR_SUCCESS))) { + p)) != APR_SUCCESS)) { *pollset = NULL; return rv; } @@ -98,7 +98,7 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, (*pollset)->kqueue_fd = kqueue(); if ((*pollset)->kqueue_fd == -1) { - return APR_ENOMEM; + return apr_get_netos_error(); } apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, @@ -149,7 +149,7 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, NULL) == -1) { - rv = APR_ENOMEM; + rv = apr_get_netos_error(); } } @@ -158,7 +158,7 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, NULL) == -1) { - rv = APR_ENOMEM; + rv = apr_get_netos_error(); } } @@ -281,4 +281,158 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, return rv; } + +struct apr_pollcb_t { + apr_pool_t *pool; + apr_uint32_t nalloc; + struct kevent *pollset; + int kqfd; +}; + +static apr_status_t cb_cleanup(void *b_) +{ + apr_pollcb_t *pollcb = (apr_pollcb_t *) b_; + close(pollcb->kqfd); + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + int fd; + + fd = kqueue(); + if (fd < 0) { + *pollcb = NULL; + return apr_get_netos_error(); + } + + *pollcb = apr_palloc(p, sizeof(**pollcb)); + (*pollcb)->nalloc = size; + (*pollcb)->pool = p; + (*pollcb)->kqfd = fd; + (*pollcb)->pollset = (struct kevent *)apr_pcalloc(p, size * sizeof(struct kevent)); + apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + apr_os_sock_t fd; + struct kevent ev; + apr_status_t rv = APR_SUCCESS; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + if (descriptor->reqevents & APR_POLLIN) { + EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, descriptor); + + if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) { + rv = apr_get_netos_error(); + } + } + + if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { + EV_SET(&ev, fd, EVFILT_WRITE, EV_ADD, 0, 0, descriptor); + + if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) { + rv = apr_get_netos_error(); + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + apr_status_t rv = APR_SUCCESS; + struct kevent ev; + apr_os_sock_t fd; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + if (descriptor->reqevents & APR_POLLIN) { + EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + + if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) { + rv = APR_NOTFOUND; + } + } + + if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { + /* XXXX: this is less than optimal, shouldn't we still try to + * remove the FD even if it wasn't in the readset? + */ + EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + + if (kevent(pollcb->kqfd, &ev, 1, NULL, 0, NULL) == -1) { + rv = APR_NOTFOUND; + } + } + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton) +{ + int ret, i; + 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; + } + + ret = kevent(pollcb->kqfd, NULL, 0, pollcb->pollset, pollcb->nalloc, + tvptr); + + if (ret < 0) { + rv = apr_get_netos_error(); + } + else if (ret == 0) { + rv = APR_TIMEUP; + } + else { + for (i = 0; i < ret; i++) { + apr_pollfd_t *pollfd = (apr_pollfd_t *)(pollcb->pollset[i].udata); + + pollfd->rtnevents = get_kqueue_revent(pollcb->pollset[i].filter, + pollcb->pollset[i].flags); + + rv = func(baton, pollfd); + + if (rv) { + return rv; + } + } + } + + return rv; +} + #endif /* POLLSET_USES_KQUEUE */ diff --git a/srclib/apr/poll/unix/poll.c b/srclib/apr/poll/unix/poll.c index d27a9998..cca8bfe8 100644 --- a/srclib/apr/poll/unix/poll.c +++ b/srclib/apr/poll/unix/poll.c @@ -18,6 +18,10 @@ #if defined(POLL_USES_POLL) || defined(POLLSET_USES_POLL) +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif + static apr_int16_t get_event(apr_int16_t event) { apr_int16_t rv = 0; @@ -266,4 +270,33 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + return APR_ENOTIMPL; +} + + +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton) +{ + return APR_ENOTIMPL; +} + #endif /* POLLSET_USES_POLL */ diff --git a/srclib/apr/poll/unix/port.c b/srclib/apr/poll/unix/port.c index 31f48cee..6f0ce755 100644 --- a/srclib/apr/poll/unix/port.c +++ b/srclib/apr/poll/unix/port.c @@ -15,6 +15,7 @@ */ #include "apr_arch_poll_private.h" +#include "apr_atomic.h" #ifdef POLLSET_USES_PORT @@ -80,6 +81,8 @@ struct apr_pollset_t /* A ring of pollfd_t where rings that have been _remove'd but might still be inside a _poll */ APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring; + /* number of threads in poll */ + volatile apr_uint32_t waiting; }; static apr_status_t backend_cleanup(void *p_) @@ -100,7 +103,7 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, if (flags & APR_POLLSET_THREADSAFE && ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, APR_THREAD_MUTEX_DEFAULT, - p) != APR_SUCCESS))) { + p)) != APR_SUCCESS)) { *pollset = NULL; return rv; } @@ -110,6 +113,7 @@ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, return APR_ENOTIMPL; } #endif + (*pollset)->waiting = 0; (*pollset)->nelts = 0; (*pollset)->nalloc = size; (*pollset)->flags = flags; @@ -168,16 +172,22 @@ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, fd = descriptor->desc.f->filedes; } - res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, - get_event(descriptor->reqevents), (void *)elem); + if (apr_atomic_read32(&pollset->waiting)) { + res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, + get_event(descriptor->reqevents), (void *)elem); - if (res < 0) { - rv = APR_ENOMEM; - APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); - } + if (res < 0) { + rv = APR_ENOMEM; + APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + } + else { + pollset->nelts++; + APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + } + } else { pollset->nelts++; - APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + APR_RING_INSERT_TAIL(&(pollset->add_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); @@ -192,6 +202,7 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; int res; + int err; pollset_lock_rings(); @@ -205,6 +216,7 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, res = port_dissociate(pollset->port_fd, PORT_SOURCE_FD, fd); if (res < 0) { + err = errno; rv = APR_NOTFOUND; } @@ -233,6 +245,9 @@ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, APR_RING_REMOVE(ep, link); APR_RING_INSERT_TAIL(&(pollset->dead_ring), ep, pfd_elem_t, link); + if (ENOENT == err) { + rv = APR_SUCCESS; + } break; } } @@ -268,6 +283,8 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, pollset_lock_rings(); + apr_atomic_inc32(&pollset->waiting); + while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { ep = APR_RING_FIRST(&(pollset->add_ring)); APR_RING_REMOVE(ep, link); @@ -291,16 +308,14 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, ret = port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc, &nget, tvptr); + /* decrease the waiting ASAP to reduce the window for calling + port_associate within apr_pollset_add() */ + apr_atomic_dec32(&pollset->waiting); (*num) = nget; if (ret == -1) { (*num) = 0; - if (errno == ETIME || errno == EINTR) { - rv = APR_TIMEUP; - } - else { - rv = APR_EGENERAL; - } + rv = apr_get_netos_error(); } else if (nget == 0) { rv = APR_TIMEUP; @@ -340,4 +355,135 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, return rv; } +struct apr_pollcb_t { + apr_pool_t *pool; + apr_uint32_t nalloc; + port_event_t *port_set; + int port_fd; +}; + +static apr_status_t cb_cleanup(void *p_) +{ + apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; + close(pollcb->port_fd); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + int fd; + + fd = port_create(); + + if (fd < 0) { + *pollcb = NULL; + return apr_get_netos_error(); + } + + *pollcb = apr_palloc(p, sizeof(**pollcb)); + (*pollcb)->nalloc = size; + (*pollcb)->pool = p; + (*pollcb)->port_fd = fd; + (*pollcb)->port_set = apr_palloc(p, size * sizeof(port_event_t)); + apr_pool_cleanup_register(p, *pollcb, cb_cleanup, cb_cleanup); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + int ret, fd; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + ret = port_associate(pollcb->port_fd, PORT_SOURCE_FD, fd, + get_event(descriptor->reqevents), descriptor); + + if (ret == -1) { + return apr_get_netos_error(); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + int fd, ret; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + ret = port_dissociate(pollcb->port_fd, PORT_SOURCE_FD, fd); + + if (ret < 0) { + return APR_NOTFOUND; + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton) +{ + int ret; + apr_pollfd_t *pollfd; + struct timespec tv, *tvptr; + apr_status_t rv = APR_SUCCESS; + unsigned int i, nget = pollcb->nalloc; + + 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 = port_getn(pollcb->port_fd, pollcb->port_set, pollcb->nalloc, + &nget, tvptr); + + if (ret == -1) { + if (errno == ETIME || errno == EINTR) { + rv = APR_TIMEUP; + } + else { + rv = APR_EGENERAL; + } + } + else if (nget == 0) { + rv = APR_TIMEUP; + } + else { + for (i = 0; i < nget; i++) { + pollfd = (apr_pollfd_t *)(pollcb->port_set[i].portev_user); + pollfd->rtnevents = get_revent(pollcb->port_set[i].portev_events); + + rv = func(baton, pollfd); + if (rv) { + return rv; + } + rv = apr_pollcb_add(pollcb, pollfd); + } + } + + return rv; +} + #endif /* POLLSET_USES_PORT */ diff --git a/srclib/apr/poll/unix/select.c b/srclib/apr/poll/unix/select.c index ca35b77d..42e7a3f6 100644 --- a/srclib/apr/poll/unix/select.c +++ b/srclib/apr/poll/unix/select.c @@ -406,4 +406,33 @@ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, return APR_SUCCESS; } +APR_DECLARE(apr_status_t) apr_pollcb_create(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) +{ + return APR_ENOTIMPL; +} + + +APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, + apr_interval_time_t timeout, + apr_pollcb_cb_t func, + void *baton) +{ + return APR_ENOTIMPL; +} + #endif /* POLLSET_USES_SELECT */ |