From commits-return-10889-apmail-apr-commits-archive=apr.apache.org@apr.apache.org Fri Oct 02 23:25:27 2009 Return-Path: Delivered-To: apmail-apr-commits-archive@www.apache.org Received: (qmail 18283 invoked from network); 2 Oct 2009 23:25:26 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 2 Oct 2009 23:25:26 -0000 Received: (qmail 12673 invoked by uid 500); 2 Oct 2009 23:25:26 -0000 Delivered-To: apmail-apr-commits-archive@apr.apache.org Received: (qmail 12589 invoked by uid 500); 2 Oct 2009 23:25:26 -0000 Mailing-List: contact commits-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: Reply-To: dev@apr.apache.org List-Id: Delivered-To: mailing list commits@apr.apache.org Received: (qmail 12580 invoked by uid 99); 2 Oct 2009 23:25:26 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 02 Oct 2009 23:25:26 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 02 Oct 2009 23:25:19 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id BF52423888DB; Fri, 2 Oct 2009 23:24:57 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r821199 [2/2] - in /apr/apr/branches/1.4.x: ./ include/ include/arch/unix/ poll/os2/ poll/unix/ Date: Fri, 02 Oct 2009 23:24:57 -0000 To: commits@apr.apache.org From: jim@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091002232457.BF52423888DB@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: apr/apr/branches/1.4.x/poll/unix/port.c URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/port.c?rev=821199&r1=821198&r2=821199&view=diff ============================================================================== --- apr/apr/branches/1.4.x/poll/unix/port.c (original) +++ apr/apr/branches/1.4.x/poll/unix/port.c Fri Oct 2 23:24:56 2009 @@ -14,11 +14,17 @@ * limitations under the License. */ -#include "apr_arch_poll_private.h" +#include "apr.h" +#include "apr_poll.h" +#include "apr_time.h" +#include "apr_portable.h" #include "apr_atomic.h" +#include "apr_arch_file_io.h" +#include "apr_arch_networkio.h" +#include "apr_arch_poll_private.h" #include "apr_arch_inherit.h" -#ifdef POLLSET_USES_PORT +#if defined(HAVE_PORT_CREATE) static apr_int16_t get_event(apr_int16_t event) { @@ -56,16 +62,11 @@ } -struct apr_pollset_t +struct apr_pollset_private_t { - apr_pool_t *pool; - apr_uint32_t nalloc; int port_fd; port_event_t *port_set; apr_pollfd_t *result_set; - apr_uint32_t flags; - /* Pipe descriptors used for wakeup */ - apr_file_t *wakeup_pipe[2]; #if APR_HAS_THREADS /* A thread mutex to protect operations on the rings */ apr_thread_mutex_t *ring_lock; @@ -137,138 +138,67 @@ return rv; } -static apr_status_t backend_cleanup(void *p_) +static apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset) { - apr_pollset_t *pollset = (apr_pollset_t *) p_; - close(pollset->port_fd); - if (pollset->flags & APR_POLLSET_WAKEABLE) { - /* Close both sides of the wakeup pipe */ - if (pollset->wakeup_pipe[0]) { - apr_file_close(pollset->wakeup_pipe[0]); - pollset->wakeup_pipe[0] = NULL; - } - if (pollset->wakeup_pipe[1]) { - apr_file_close(pollset->wakeup_pipe[1]); - pollset->wakeup_pipe[1] = NULL; - } - } + close(pollset->p->port_fd); return APR_SUCCESS; } -/* Create a dummy wakeup pipe for interrupting the poller - */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - apr_status_t rv; - apr_pollfd_t fd; - - if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0], - &pollset->wakeup_pipe[1], - pollset->pool)) != APR_SUCCESS) - return rv; - fd.reqevents = APR_POLLIN; - fd.desc_type = APR_POLL_FILE; - fd.desc.f = pollset->wakeup_pipe[0]; - /* Add the pipe to the pollset - */ - return apr_pollset_add(pollset, &fd); -} - -/* Read and discard what's ever in the wakeup pipe. - */ -static void drain_wakeup_pipe(apr_pollset_t *pollset) -{ - char rb[512]; - apr_size_t nr = sizeof(rb); - - while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) { - /* Although we write just one byte to the other end of the pipe - * during wakeup, multiple treads could call the wakeup. - * So simply drain out from the input side of the pipe all - * the data. - */ - if (nr != sizeof(rb)) - break; - } -} - -APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, +static apr_status_t impl_pollset_create(apr_pollset_t *pollset, apr_uint32_t size, apr_pool_t *p, apr_uint32_t flags) { apr_status_t rv = APR_SUCCESS; - *pollset = apr_palloc(p, sizeof(**pollset)); + pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); #if APR_HAS_THREADS if (flags & APR_POLLSET_THREADSAFE && - ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, + ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, APR_THREAD_MUTEX_DEFAULT, p)) != APR_SUCCESS)) { - *pollset = NULL; + pollset->p = NULL; return rv; } #else if (flags & APR_POLLSET_THREADSAFE) { - *pollset = NULL; + pollset->p = NULL; return APR_ENOTIMPL; } #endif - if (flags & APR_POLLSET_WAKEABLE) { - /* Add room for wakeup descriptor */ - size++; - } - (*pollset)->waiting = 0; - (*pollset)->nalloc = size; - (*pollset)->flags = flags; - (*pollset)->pool = p; + pollset->p->waiting = 0; - (*pollset)->port_set = apr_palloc(p, size * sizeof(port_event_t)); + pollset->p->port_set = apr_palloc(p, size * sizeof(port_event_t)); - (*pollset)->port_fd = port_create(); + pollset->p->port_fd = port_create(); - if ((*pollset)->port_fd < 0) { + if (pollset->p->port_fd < 0) { + pollset->p = NULL; return apr_get_netos_error(); } { int flags; - if ((flags = fcntl((*pollset)->port_fd, F_GETFD)) == -1) + if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1) return errno; flags |= FD_CLOEXEC; - if (fcntl((*pollset)->port_fd, F_SETFD, flags) == -1) + if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1) return errno; } - (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); - APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); - APR_RING_INIT(&(*pollset)->add_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_WAKEABLE) { - /* Create wakeup pipe */ - if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) { - close((*pollset)->port_fd); - *pollset = NULL; - return rv; - } - } - apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, - apr_pool_cleanup_null); + APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); + APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); return rv; } -APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) -{ - return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); -} - -APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, - const apr_pollfd_t *descriptor) +static apr_status_t impl_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) { apr_os_sock_t fd; pfd_elem_t *elem; @@ -277,13 +207,14 @@ pollset_lock_rings(); - if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { - elem = APR_RING_FIRST(&(pollset->free_ring)); + if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->p->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->on_query_ring = 0; } elem->pfd = *descriptor; @@ -297,20 +228,21 @@ /* If another thread is polling, notify the kernel immediately; otherwise, * wait until the next call to apr_pollset_poll(). */ - if (apr_atomic_read32(&pollset->waiting)) { - res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, + if (apr_atomic_read32(&pollset->p->waiting)) { + res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, get_event(descriptor->reqevents), (void *)elem); if (res < 0) { rv = apr_get_netos_error(); - APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); } else { - APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + elem->on_query_ring = 1; + APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); } } else { - APR_RING_INSERT_TAIL(&(pollset->add_ring), elem, pfd_elem_t, link); + APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); @@ -318,14 +250,15 @@ return rv; } -APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, - const apr_pollfd_t *descriptor) +static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) { apr_os_sock_t fd; pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; int res; int err = 0; + int found; pollset_lock_rings(); @@ -336,42 +269,60 @@ fd = descriptor->desc.f->filedes; } - res = port_dissociate(pollset->port_fd, PORT_SOURCE_FD, fd); - - if (res < 0) { - err = errno; - rv = APR_NOTFOUND; - } - - for (ep = APR_RING_FIRST(&(pollset->query_ring)); - ep != APR_RING_SENTINEL(&(pollset->query_ring), + /* Search the add ring first. This ring is often shorter, + * and it often contains the descriptor being removed. + * (For the common scenario where apr_pollset_poll() + * returns activity for the descriptor and the descriptor + * is then removed from the pollset, it will have just + * been moved to the add ring by apr_pollset_poll().) + * + * If it is on the add ring, it isn't associated with the + * event port yet/anymore. + */ + found = 0; + for (ep = APR_RING_FIRST(&(pollset->p->add_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->add_ring), pfd_elem_t, link); ep = APR_RING_NEXT(ep, link)) { if (descriptor->desc.s == ep->pfd.desc.s) { + found = 1; APR_RING_REMOVE(ep, link); - APR_RING_INSERT_TAIL(&(pollset->dead_ring), + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); - if (ENOENT == err) { - rv = APR_SUCCESS; - } break; } } - for (ep = APR_RING_FIRST(&(pollset->add_ring)); - ep != APR_RING_SENTINEL(&(pollset->add_ring), - pfd_elem_t, link); - ep = APR_RING_NEXT(ep, link)) { + if (!found) { + res = port_dissociate(pollset->p->port_fd, PORT_SOURCE_FD, fd); - 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); - if (ENOENT == err) { - rv = APR_SUCCESS; + if (res < 0) { + /* The expected case for this failure is that another + * thread's call to port_getn() returned this fd and + * disassociated the fd from the event port, and + * impl_pollset_poll() is blocked on the ring lock, + * which this thread holds. + */ + err = errno; + rv = APR_NOTFOUND; + } + + for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->p->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); + ep->on_query_ring = 0; + APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), + ep, pfd_elem_t, link); + if (ENOENT == err) { + rv = APR_SUCCESS; + } + break; } - break; } } @@ -380,10 +331,10 @@ 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) +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; @@ -396,10 +347,10 @@ pollset_lock_rings(); - apr_atomic_inc32(&pollset->waiting); + apr_atomic_inc32(&pollset->p->waiting); - while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { - ep = APR_RING_FIRST(&(pollset->add_ring)); + 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) { @@ -409,30 +360,31 @@ fd = ep->pfd.desc.f->filedes; } - ret = port_associate(pollset->port_fd, PORT_SOURCE_FD, + 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->free_ring), ep, pfd_elem_t, link); + APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); break; } - APR_RING_INSERT_TAIL(&(pollset->query_ring), ep, pfd_elem_t, link); + 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->waiting); + apr_atomic_dec32(&pollset->p->waiting); return rv; } - rv = call_port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc, - &nget, timeout); + 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->waiting); + apr_atomic_dec32(&pollset->p->waiting); (*num) = nget; if (nget) { @@ -440,31 +392,38 @@ pollset_lock_rings(); for (i = 0, j = 0; i < nget; i++) { - fp = (((pfd_elem_t*)(pollset->port_set[i].portev_user))->pfd); + 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]) { - drain_wakeup_pipe(pollset); + apr_pollset_drain_wakeup_pipe(pollset); rv = APR_EINTR; } else { - pollset->result_set[j] = fp; - pollset->result_set[j].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->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? */ + if ((*num = j)) { /* any event besides wakeup pipe? */ rv = APR_SUCCESS; if (descriptors) { - *descriptors = pollset->result_set; + *descriptors = pollset->p->result_set; } } } @@ -472,72 +431,61 @@ pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ - APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link); + APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); return rv; } -APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset) -{ - if (pollset->flags & APR_POLLSET_WAKEABLE) - return apr_file_putc(1, pollset->wakeup_pipe[1]); - else - return APR_EINIT; -} - -struct apr_pollcb_t { - apr_pool_t *pool; - apr_uint32_t nalloc; - port_event_t *port_set; - int port_fd; +static apr_pollset_provider_t impl = { + impl_pollset_create, + impl_pollset_add, + impl_pollset_remove, + impl_pollset_poll, + impl_pollset_cleanup, + "port" }; +apr_pollset_provider_t *apr_pollset_provider_port = &impl; + static apr_status_t cb_cleanup(void *p_) { apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; - close(pollcb->port_fd); + close(pollcb->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) +static apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) { - int fd; - - fd = port_create(); + pollcb->fd = port_create(); - if (fd < 0) { - *pollcb = NULL; + if (pollcb->fd < 0) { return apr_get_netos_error(); } { int flags; - if ((flags = fcntl(fd, F_GETFD)) == -1) + if ((flags = fcntl(pollcb->fd, F_GETFD)) == -1) return errno; flags |= FD_CLOEXEC; - if (fcntl(fd, F_SETFD, flags) == -1) + if (fcntl(pollcb->fd, F_SETFD, flags) == -1) return errno; } - *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); + pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t)); + apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, - apr_pollfd_t *descriptor) +static apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) { int ret, fd; @@ -548,7 +496,7 @@ fd = descriptor->desc.f->filedes; } - ret = port_associate(pollcb->port_fd, PORT_SOURCE_FD, fd, + ret = port_associate(pollcb->fd, PORT_SOURCE_FD, fd, get_event(descriptor->reqevents), descriptor); if (ret == -1) { @@ -558,8 +506,8 @@ return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, - apr_pollfd_t *descriptor) +static apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb, + apr_pollfd_t *descriptor) { int fd, ret; @@ -570,7 +518,7 @@ fd = descriptor->desc.f->filedes; } - ret = port_dissociate(pollcb->port_fd, PORT_SOURCE_FD, fd); + ret = port_dissociate(pollcb->fd, PORT_SOURCE_FD, fd); if (ret < 0) { return APR_NOTFOUND; @@ -579,22 +527,22 @@ 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) +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 = pollcb->nalloc; - rv = call_port_getn(pollcb->port_fd, pollcb->port_set, pollcb->nalloc, + 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->port_set[i].portev_user); - pollfd->rtnevents = get_revent(pollcb->port_set[i].portev_events); + 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) { @@ -607,4 +555,14 @@ return rv; } -#endif /* POLLSET_USES_PORT */ +static apr_pollcb_provider_t impl_cb = { + impl_pollcb_create, + impl_pollcb_add, + impl_pollcb_remove, + impl_pollcb_poll, + "port" +}; + +apr_pollcb_provider_t *apr_pollcb_provider_port = &impl_cb; + +#endif /* HAVE_PORT_CREATE */ Modified: apr/apr/branches/1.4.x/poll/unix/select.c URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/poll/unix/select.c?rev=821199&r1=821198&r2=821199&view=diff ============================================================================== --- apr/apr/branches/1.4.x/poll/unix/select.c (original) +++ apr/apr/branches/1.4.x/poll/unix/select.c Fri Oct 2 23:24:56 2009 @@ -23,8 +23,8 @@ #include "apr_poll.h" #include "apr_time.h" #include "apr_portable.h" -#include "apr_arch_networkio.h" #include "apr_arch_file_io.h" +#include "apr_arch_networkio.h" #include "apr_arch_poll_private.h" #ifdef POLL_USES_SELECT @@ -167,191 +167,49 @@ #endif /* POLL_USES_SELECT */ -#ifdef POLLSET_USES_SELECT - -struct apr_pollset_t +struct apr_pollset_private_t { - apr_pool_t *pool; - - apr_uint32_t nelts; - apr_uint32_t nalloc; fd_set readset, writeset, exceptset; int maxfd; apr_pollfd_t *query_set; apr_pollfd_t *result_set; apr_uint32_t flags; - /* Pipe descriptors used for wakeup */ - apr_file_t *wakeup_pipe[2]; #ifdef NETWARE int set_type; #endif }; -#if !APR_FILES_AS_SOCKETS -#if defined (WIN32) - -extern apr_status_t -apr_file_socket_pipe_create(apr_file_t **in, - apr_file_t **out, - apr_pool_t *p); - -extern apr_status_t -apr_file_socket_pipe_close(apr_file_t *file); - -/* Create a dummy wakeup socket pipe for interrupting the poller - */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - apr_status_t rv; - apr_pollfd_t fd; - - if ((rv = apr_file_socket_pipe_create(&pollset->wakeup_pipe[0], - &pollset->wakeup_pipe[1], - pollset->pool)) != APR_SUCCESS) - return rv; - fd.reqevents = APR_POLLIN; - fd.desc_type = APR_POLL_FILE; - fd.desc.f = pollset->wakeup_pipe[0]; - /* Add the pipe to the pollset - */ - return apr_pollset_add(pollset, &fd); -} -#else /* !WIN32 */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - return APR_ENOTIMPL; -} - -static apr_status_t apr_file_socket_pipe_close(apr_file_t *file) -{ - return APR_ENOTIMPL; -} - -#endif /* WIN32 */ -#else /* APR_FILES_AS_SOCKETS */ - -/* Create a dummy wakeup pipe for interrupting the poller - */ -static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset) -{ - apr_status_t rv; - apr_pollfd_t fd; - - if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0], - &pollset->wakeup_pipe[1], - pollset->pool)) != APR_SUCCESS) - return rv; - fd.reqevents = APR_POLLIN; - fd.desc_type = APR_POLL_FILE; - fd.desc.f = pollset->wakeup_pipe[0]; - /* Add the pipe to the pollset - */ - return apr_pollset_add(pollset, &fd); -} -#endif /* !APR_FILES_AS_SOCKETS */ - -/* Read and discard what's ever in the wakeup pipe. - */ -static void drain_wakeup_pipe(apr_pollset_t *pollset) -{ - char rb[512]; - apr_size_t nr = sizeof(rb); - - while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) { - /* Although we write just one byte to the other end of the pipe - * during wakeup, multiple treads could call the wakeup. - * So simply drain out from the input side of the pipe all - * the data. - */ - if (nr != sizeof(rb)) - break; - } -} - -static apr_status_t wakeup_pipe_cleanup(void *p) -{ - apr_pollset_t *pollset = (apr_pollset_t *) p; - if (pollset->flags & APR_POLLSET_WAKEABLE) { - /* Close both sides of the wakeup pipe */ - if (pollset->wakeup_pipe[0]) { -#if APR_FILES_AS_SOCKETS - apr_file_close(pollset->wakeup_pipe[0]); -#else - apr_file_socket_pipe_close(pollset->wakeup_pipe[0]); -#endif - pollset->wakeup_pipe[0] = NULL; - } - if (pollset->wakeup_pipe[1]) { -#if APR_FILES_AS_SOCKETS - apr_file_close(pollset->wakeup_pipe[1]); -#else - apr_file_socket_pipe_close(pollset->wakeup_pipe[1]); -#endif - pollset->wakeup_pipe[1] = NULL; - } - } - - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, - apr_uint32_t size, - apr_pool_t *p, - apr_uint32_t flags) +static apr_status_t impl_pollset_create(apr_pollset_t *pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) { if (flags & APR_POLLSET_THREADSAFE) { - *pollset = NULL; + pollset->p = NULL; return APR_ENOTIMPL; } - if (flags & APR_POLLSET_WAKEABLE) { - /* Add room for wakeup descriptor */ - size++; - } #ifdef FD_SETSIZE if (size > FD_SETSIZE) { - *pollset = NULL; + pollset->p = NULL; return APR_EINVAL; } #endif - *pollset = apr_palloc(p, sizeof(**pollset)); - (*pollset)->nelts = 0; - (*pollset)->nalloc = size; - (*pollset)->pool = p; - (*pollset)->flags = flags; - FD_ZERO(&((*pollset)->readset)); - FD_ZERO(&((*pollset)->writeset)); - FD_ZERO(&((*pollset)->exceptset)); - (*pollset)->maxfd = 0; + pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); + FD_ZERO(&(pollset->p->readset)); + FD_ZERO(&(pollset->p->writeset)); + FD_ZERO(&(pollset->p->exceptset)); + pollset->p->maxfd = 0; #ifdef NETWARE - (*pollset)->set_type = APR_NO_DESC; + pollset->p->set_type = APR_NO_DESC; #endif - (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); - (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + pollset->p->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); - if (flags & APR_POLLSET_WAKEABLE) { - apr_status_t rv; - /* Create wakeup pipe */ - if ((rv = create_wakeup_pipe(*pollset)) != APR_SUCCESS) { - *pollset = NULL; - return rv; - } - apr_pool_cleanup_register(p, *pollset, wakeup_pipe_cleanup, - apr_pool_cleanup_null); - } return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) -{ - if (pollset->flags & APR_POLLSET_WAKEABLE) - return apr_pool_cleanup_run(pollset->pool, pollset, - wakeup_pipe_cleanup); - else - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, - const apr_pollfd_t *descriptor) +static apr_status_t impl_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) { apr_os_sock_t fd; @@ -359,16 +217,16 @@ return APR_ENOMEM; } - pollset->query_set[pollset->nelts] = *descriptor; + pollset->p->query_set[pollset->nelts] = *descriptor; if (descriptor->desc_type == APR_POLL_SOCKET) { #ifdef NETWARE /* NetWare can't handle mixed descriptor types in select() */ - if (HAS_PIPES(pollset->set_type)) { + if (HAS_PIPES(pollset->p->set_type)) { return APR_EBADF; } else { - pollset->set_type = APR_POLL_SOCKET; + pollset->p->set_type = APR_POLL_SOCKET; } #endif fd = descriptor->desc.s->socketdes; @@ -376,16 +234,15 @@ else { #if !APR_FILES_AS_SOCKETS if ((pollset->flags & APR_POLLSET_WAKEABLE) && - descriptor->desc.f == pollset->wakeup_pipe[0]) { + descriptor->desc.f == pollset->wakeup_pipe[0]) fd = (apr_os_sock_t)descriptor->desc.f->filedes; - } else return APR_EBADF; #else #ifdef NETWARE /* NetWare can't handle mixed descriptor types in select() */ - if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) { - pollset->set_type = APR_POLL_FILE; + if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->p->set_type)) { + pollset->p->set_type = APR_POLL_FILE; fd = descriptor->desc.f->filedes; } else { @@ -403,24 +260,24 @@ } #endif if (descriptor->reqevents & APR_POLLIN) { - FD_SET(fd, &(pollset->readset)); + FD_SET(fd, &(pollset->p->readset)); } if (descriptor->reqevents & APR_POLLOUT) { - FD_SET(fd, &(pollset->writeset)); + FD_SET(fd, &(pollset->p->writeset)); } if (descriptor->reqevents & (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { - FD_SET(fd, &(pollset->exceptset)); + FD_SET(fd, &(pollset->p->exceptset)); } - if ((int) fd > pollset->maxfd) { - pollset->maxfd = (int) fd; + if ((int) fd > pollset->p->maxfd) { + pollset->p->maxfd = (int) fd; } pollset->nelts++; return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t * pollset, - const apr_pollfd_t * descriptor) +static apr_status_t impl_pollset_remove(apr_pollset_t * pollset, + const apr_pollfd_t * descriptor) { apr_uint32_t i; apr_os_sock_t fd; @@ -437,25 +294,25 @@ } for (i = 0; i < pollset->nelts; i++) { - if (descriptor->desc.s == pollset->query_set[i].desc.s) { + if (descriptor->desc.s == pollset->p->query_set[i].desc.s) { /* Found an instance of the fd: remove this and any other copies */ apr_uint32_t dst = i; apr_uint32_t old_nelts = pollset->nelts; pollset->nelts--; for (i++; i < old_nelts; i++) { - if (descriptor->desc.s == pollset->query_set[i].desc.s) { + if (descriptor->desc.s == pollset->p->query_set[i].desc.s) { pollset->nelts--; } else { - pollset->query_set[dst] = pollset->query_set[i]; + pollset->p->query_set[dst] = pollset->p->query_set[i]; dst++; } } - FD_CLR(fd, &(pollset->readset)); - FD_CLR(fd, &(pollset->writeset)); - FD_CLR(fd, &(pollset->exceptset)); - if (((int) fd == pollset->maxfd) && (pollset->maxfd > 0)) { - pollset->maxfd--; + FD_CLR(fd, &(pollset->p->readset)); + FD_CLR(fd, &(pollset->p->writeset)); + FD_CLR(fd, &(pollset->p->exceptset)); + if (((int) fd == pollset->p->maxfd) && (pollset->p->maxfd > 0)) { + pollset->p->maxfd--; } return APR_SUCCESS; } @@ -464,10 +321,10 @@ return APR_NOTFOUND; } -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) +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 rs; apr_uint32_t i, j; @@ -495,18 +352,18 @@ tvptr = &tv; } - memcpy(&readset, &(pollset->readset), sizeof(fd_set)); - memcpy(&writeset, &(pollset->writeset), sizeof(fd_set)); - memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set)); + memcpy(&readset, &(pollset->p->readset), sizeof(fd_set)); + memcpy(&writeset, &(pollset->p->writeset), sizeof(fd_set)); + memcpy(&exceptset, &(pollset->p->exceptset), sizeof(fd_set)); #ifdef NETWARE - if (HAS_PIPES(pollset->set_type)) { - rs = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset, + if (HAS_PIPES(pollset->p->set_type)) { + rs = pipe_select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset, tvptr); } else #endif - rs = select(pollset->maxfd + 1, &readset, &writeset, &exceptset, + rs = select(pollset->p->maxfd + 1, &readset, &writeset, &exceptset, tvptr); (*num) = rs; @@ -519,13 +376,13 @@ j = 0; for (i = 0; i < pollset->nelts; i++) { apr_os_sock_t fd; - if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { - fd = pollset->query_set[i].desc.s->socketdes; + if (pollset->p->query_set[i].desc_type == APR_POLL_SOCKET) { + fd = pollset->p->query_set[i].desc.s->socketdes; } else { if ((pollset->flags & APR_POLLSET_WAKEABLE) && - pollset->query_set[i].desc.f == pollset->wakeup_pipe[0]) { - drain_wakeup_pipe(pollset); + pollset->p->query_set[i].desc.f == pollset->wakeup_pipe[0]) { + apr_pollset_drain_wakeup_pipe(pollset); rv = APR_EINTR; continue; } @@ -533,22 +390,22 @@ #if !APR_FILES_AS_SOCKETS return APR_EBADF; #else - fd = pollset->query_set[i].desc.f->filedes; + fd = pollset->p->query_set[i].desc.f->filedes; #endif } } if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || FD_ISSET(fd, &exceptset)) { - pollset->result_set[j] = pollset->query_set[i]; - pollset->result_set[j].rtnevents = 0; + pollset->p->result_set[j] = pollset->p->query_set[i]; + pollset->p->result_set[j].rtnevents = 0; if (FD_ISSET(fd, &readset)) { - pollset->result_set[j].rtnevents |= APR_POLLIN; + pollset->p->result_set[j].rtnevents |= APR_POLLIN; } if (FD_ISSET(fd, &writeset)) { - pollset->result_set[j].rtnevents |= APR_POLLOUT; + pollset->p->result_set[j].rtnevents |= APR_POLLOUT; } if (FD_ISSET(fd, &exceptset)) { - pollset->result_set[j].rtnevents |= APR_POLLERR; + pollset->p->result_set[j].rtnevents |= APR_POLLERR; } j++; } @@ -557,45 +414,17 @@ rv = APR_SUCCESS; if (descriptors) - *descriptors = pollset->result_set; + *descriptors = pollset->p->result_set; return rv; } -APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset) -{ - if (pollset->flags & APR_POLLSET_WAKEABLE) - return apr_file_putc(1, pollset->wakeup_pipe[1]); - else - return APR_EINIT; -} - -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; -} +static apr_pollset_provider_t impl = { + impl_pollset_create, + impl_pollset_add, + impl_pollset_remove, + impl_pollset_poll, + NULL, + "select" +}; -#endif /* POLLSET_USES_SELECT */ +apr_pollset_provider_t *apr_pollset_provider_select = &impl;