summaryrefslogtreecommitdiff
path: root/srclib/apr/poll/unix
diff options
context:
space:
mode:
authorStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:22 +0100
committerStefan Fritsch <sf@sfritsch.de>2011-12-27 19:42:22 +0100
commit0268977037115539ad65a26e858aa0df8d18cd13 (patch)
treef761b541b04d08b75e32efc6c293111c61a8b79c /srclib/apr/poll/unix
parent9e615cb6aa4afcee97f8a1646e5a586261a7b81f (diff)
downloadapache2-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.c249
-rw-r--r--srclib/apr/poll/unix/kqueue.c162
-rw-r--r--srclib/apr/poll/unix/poll.c33
-rw-r--r--srclib/apr/poll/unix/port.c174
-rw-r--r--srclib/apr/poll/unix/select.c29
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 */