1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more 2251875Speter * contributor license agreements. See the NOTICE file distributed with 3251875Speter * this work for additional information regarding copyright ownership. 4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0 5251875Speter * (the "License"); you may not use this file except in compliance with 6251875Speter * the License. You may obtain a copy of the License at 7251875Speter * 8251875Speter * http://www.apache.org/licenses/LICENSE-2.0 9251875Speter * 10251875Speter * Unless required by applicable law or agreed to in writing, software 11251875Speter * distributed under the License is distributed on an "AS IS" BASIS, 12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13251875Speter * See the License for the specific language governing permissions and 14251875Speter * limitations under the License. 15251875Speter */ 16251875Speter 17251875Speter#include "apr.h" 18251875Speter#include "apr_poll.h" 19251875Speter#include "apr_time.h" 20251875Speter#include "apr_portable.h" 21251875Speter#include "apr_atomic.h" 22251875Speter#include "apr_arch_file_io.h" 23251875Speter#include "apr_arch_networkio.h" 24251875Speter#include "apr_arch_poll_private.h" 25251875Speter#include "apr_arch_inherit.h" 26251875Speter 27251875Speter#if defined(HAVE_PORT_CREATE) 28251875Speter 29251875Speterstatic apr_int16_t get_event(apr_int16_t event) 30251875Speter{ 31251875Speter apr_int16_t rv = 0; 32251875Speter 33251875Speter if (event & APR_POLLIN) 34251875Speter rv |= POLLIN; 35251875Speter if (event & APR_POLLPRI) 36251875Speter rv |= POLLPRI; 37251875Speter if (event & APR_POLLOUT) 38251875Speter rv |= POLLOUT; 39251875Speter /* POLLERR, POLLHUP, and POLLNVAL aren't valid as requested events */ 40251875Speter 41251875Speter return rv; 42251875Speter} 43251875Speter 44251875Speterstatic apr_int16_t get_revent(apr_int16_t event) 45251875Speter{ 46251875Speter apr_int16_t rv = 0; 47251875Speter 48251875Speter if (event & POLLIN) 49251875Speter rv |= APR_POLLIN; 50251875Speter if (event & POLLPRI) 51251875Speter rv |= APR_POLLPRI; 52251875Speter if (event & POLLOUT) 53251875Speter rv |= APR_POLLOUT; 54251875Speter if (event & POLLERR) 55251875Speter rv |= APR_POLLERR; 56251875Speter if (event & POLLHUP) 57251875Speter rv |= APR_POLLHUP; 58251875Speter if (event & POLLNVAL) 59251875Speter rv |= APR_POLLNVAL; 60251875Speter 61251875Speter return rv; 62251875Speter} 63251875Speter 64251875Speter 65251875Speterstruct apr_pollset_private_t 66251875Speter{ 67251875Speter int port_fd; 68251875Speter port_event_t *port_set; 69251875Speter apr_pollfd_t *result_set; 70251875Speter#if APR_HAS_THREADS 71251875Speter /* A thread mutex to protect operations on the rings */ 72251875Speter apr_thread_mutex_t *ring_lock; 73251875Speter#endif 74251875Speter /* A ring containing all of the pollfd_t that are active */ 75251875Speter APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring; 76251875Speter /* A ring containing the pollfd_t that will be added on the 77251875Speter * next call to apr_pollset_poll(). 78251875Speter */ 79251875Speter APR_RING_HEAD(pfd_add_ring_t, pfd_elem_t) add_ring; 80251875Speter /* A ring of pollfd_t that have been used, and then _remove'd */ 81251875Speter APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring; 82251875Speter /* A ring of pollfd_t where rings that have been _remove'd but 83251875Speter might still be inside a _poll */ 84251875Speter APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring; 85251875Speter /* number of threads in poll */ 86251875Speter volatile apr_uint32_t waiting; 87251875Speter}; 88251875Speter 89251875Speterstatic apr_status_t call_port_getn(int port, port_event_t list[], 90251875Speter unsigned int max, unsigned int *nget, 91251875Speter apr_interval_time_t timeout) 92251875Speter{ 93251875Speter struct timespec tv, *tvptr; 94251875Speter int ret; 95251875Speter apr_status_t rv = APR_SUCCESS; 96251875Speter 97251875Speter if (timeout < 0) { 98251875Speter tvptr = NULL; 99251875Speter } 100251875Speter else { 101251875Speter tv.tv_sec = (long) apr_time_sec(timeout); 102251875Speter tv.tv_nsec = (long) apr_time_usec(timeout) * 1000; 103251875Speter tvptr = &tv; 104251875Speter } 105251875Speter 106251875Speter list[0].portev_user = (void *)-1; /* so we can double check that an 107251875Speter * event was returned 108251875Speter */ 109251875Speter 110251875Speter ret = port_getn(port, list, max, nget, tvptr); 111251875Speter /* Note: 32-bit port_getn() on Solaris 10 x86 returns large negative 112251875Speter * values instead of 0 when returning immediately. 113251875Speter */ 114251875Speter 115251875Speter if (ret == -1) { 116251875Speter rv = apr_get_netos_error(); 117251875Speter 118251875Speter switch(rv) { 119251875Speter case EINTR: 120251875Speter case ETIME: 121251875Speter if (*nget > 0 && list[0].portev_user != (void *)-1) { 122251875Speter /* This confusing API can return an event at the same time 123251875Speter * that it reports EINTR or ETIME. If that occurs, just 124251875Speter * report the event. With EINTR, nget can be > 0 without 125251875Speter * any event, so check that portev_user was filled in. 126251875Speter * 127251875Speter * (Maybe it will be simplified; see thread 128251875Speter * http://mail.opensolaris.org 129251875Speter * /pipermail/networking-discuss/2009-August/011979.html 130251875Speter * This code will still work afterwards.) 131251875Speter */ 132251875Speter rv = APR_SUCCESS; 133251875Speter break; 134251875Speter } 135251875Speter if (rv == ETIME) { 136251875Speter rv = APR_TIMEUP; 137251875Speter } 138251875Speter /* fall-through */ 139251875Speter default: 140251875Speter *nget = 0; 141251875Speter } 142251875Speter } 143251875Speter else if (*nget == 0) { 144251875Speter rv = APR_TIMEUP; 145251875Speter } 146251875Speter 147251875Speter return rv; 148251875Speter} 149251875Speter 150251875Speterstatic apr_status_t impl_pollset_cleanup(apr_pollset_t *pollset) 151251875Speter{ 152251875Speter close(pollset->p->port_fd); 153251875Speter return APR_SUCCESS; 154251875Speter} 155251875Speter 156251875Speterstatic apr_status_t impl_pollset_create(apr_pollset_t *pollset, 157251875Speter apr_uint32_t size, 158251875Speter apr_pool_t *p, 159251875Speter apr_uint32_t flags) 160251875Speter{ 161251875Speter apr_status_t rv = APR_SUCCESS; 162251875Speter pollset->p = apr_palloc(p, sizeof(apr_pollset_private_t)); 163251875Speter#if APR_HAS_THREADS 164251875Speter if (flags & APR_POLLSET_THREADSAFE && 165251875Speter ((rv = apr_thread_mutex_create(&pollset->p->ring_lock, 166251875Speter APR_THREAD_MUTEX_DEFAULT, 167251875Speter p)) != APR_SUCCESS)) { 168251875Speter pollset->p = NULL; 169251875Speter return rv; 170251875Speter } 171251875Speter#else 172251875Speter if (flags & APR_POLLSET_THREADSAFE) { 173251875Speter pollset->p = NULL; 174251875Speter return APR_ENOTIMPL; 175251875Speter } 176251875Speter#endif 177251875Speter pollset->p->waiting = 0; 178251875Speter 179251875Speter pollset->p->port_set = apr_palloc(p, size * sizeof(port_event_t)); 180251875Speter 181251875Speter pollset->p->port_fd = port_create(); 182251875Speter 183251875Speter if (pollset->p->port_fd < 0) { 184251875Speter pollset->p = NULL; 185251875Speter return apr_get_netos_error(); 186251875Speter } 187251875Speter 188251875Speter { 189251875Speter int flags; 190251875Speter 191289166Speter if ((flags = fcntl(pollset->p->port_fd, F_GETFD)) == -1) { 192289166Speter rv = errno; 193289166Speter close(pollset->p->port_fd); 194289166Speter pollset->p = NULL; 195289166Speter return rv; 196289166Speter } 197251875Speter 198251875Speter flags |= FD_CLOEXEC; 199289166Speter if (fcntl(pollset->p->port_fd, F_SETFD, flags) == -1) { 200289166Speter rv = errno; 201289166Speter close(pollset->p->port_fd); 202289166Speter pollset->p = NULL; 203289166Speter return rv; 204289166Speter } 205251875Speter } 206251875Speter 207251875Speter pollset->p->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); 208251875Speter 209251875Speter APR_RING_INIT(&pollset->p->query_ring, pfd_elem_t, link); 210251875Speter APR_RING_INIT(&pollset->p->add_ring, pfd_elem_t, link); 211251875Speter APR_RING_INIT(&pollset->p->free_ring, pfd_elem_t, link); 212251875Speter APR_RING_INIT(&pollset->p->dead_ring, pfd_elem_t, link); 213251875Speter 214251875Speter return rv; 215251875Speter} 216251875Speter 217251875Speterstatic apr_status_t impl_pollset_add(apr_pollset_t *pollset, 218251875Speter const apr_pollfd_t *descriptor) 219251875Speter{ 220251875Speter apr_os_sock_t fd; 221251875Speter pfd_elem_t *elem; 222251875Speter int res; 223251875Speter apr_status_t rv = APR_SUCCESS; 224251875Speter 225251875Speter pollset_lock_rings(); 226251875Speter 227251875Speter if (!APR_RING_EMPTY(&(pollset->p->free_ring), pfd_elem_t, link)) { 228251875Speter elem = APR_RING_FIRST(&(pollset->p->free_ring)); 229251875Speter APR_RING_REMOVE(elem, link); 230251875Speter } 231251875Speter else { 232251875Speter elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); 233251875Speter APR_RING_ELEM_INIT(elem, link); 234251875Speter elem->on_query_ring = 0; 235251875Speter } 236251875Speter elem->pfd = *descriptor; 237251875Speter 238251875Speter if (descriptor->desc_type == APR_POLL_SOCKET) { 239251875Speter fd = descriptor->desc.s->socketdes; 240251875Speter } 241251875Speter else { 242251875Speter fd = descriptor->desc.f->filedes; 243251875Speter } 244251875Speter 245251875Speter /* If another thread is polling, notify the kernel immediately; otherwise, 246251875Speter * wait until the next call to apr_pollset_poll(). 247251875Speter */ 248251875Speter if (apr_atomic_read32(&pollset->p->waiting)) { 249251875Speter res = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, 250251875Speter get_event(descriptor->reqevents), (void *)elem); 251251875Speter 252251875Speter if (res < 0) { 253251875Speter rv = apr_get_netos_error(); 254251875Speter APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); 255251875Speter } 256251875Speter else { 257251875Speter elem->on_query_ring = 1; 258251875Speter APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); 259251875Speter } 260251875Speter } 261251875Speter else { 262251875Speter APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); 263251875Speter } 264251875Speter 265251875Speter pollset_unlock_rings(); 266251875Speter 267251875Speter return rv; 268251875Speter} 269251875Speter 270251875Speterstatic apr_status_t impl_pollset_remove(apr_pollset_t *pollset, 271251875Speter const apr_pollfd_t *descriptor) 272251875Speter{ 273251875Speter apr_os_sock_t fd; 274251875Speter pfd_elem_t *ep; 275251875Speter apr_status_t rv = APR_SUCCESS; 276251875Speter int res; 277251875Speter int err = 0; 278251875Speter int found; 279251875Speter 280251875Speter pollset_lock_rings(); 281251875Speter 282251875Speter if (descriptor->desc_type == APR_POLL_SOCKET) { 283251875Speter fd = descriptor->desc.s->socketdes; 284251875Speter } 285251875Speter else { 286251875Speter fd = descriptor->desc.f->filedes; 287251875Speter } 288251875Speter 289251875Speter /* Search the add ring first. This ring is often shorter, 290251875Speter * and it often contains the descriptor being removed. 291251875Speter * (For the common scenario where apr_pollset_poll() 292251875Speter * returns activity for the descriptor and the descriptor 293251875Speter * is then removed from the pollset, it will have just 294251875Speter * been moved to the add ring by apr_pollset_poll().) 295251875Speter * 296251875Speter * If it is on the add ring, it isn't associated with the 297251875Speter * event port yet/anymore. 298251875Speter */ 299251875Speter found = 0; 300251875Speter for (ep = APR_RING_FIRST(&(pollset->p->add_ring)); 301251875Speter ep != APR_RING_SENTINEL(&(pollset->p->add_ring), 302251875Speter pfd_elem_t, link); 303251875Speter ep = APR_RING_NEXT(ep, link)) { 304251875Speter 305251875Speter if (descriptor->desc.s == ep->pfd.desc.s) { 306251875Speter found = 1; 307251875Speter APR_RING_REMOVE(ep, link); 308251875Speter APR_RING_INSERT_TAIL(&(pollset->p->free_ring), 309251875Speter ep, pfd_elem_t, link); 310251875Speter break; 311251875Speter } 312251875Speter } 313251875Speter 314251875Speter if (!found) { 315251875Speter res = port_dissociate(pollset->p->port_fd, PORT_SOURCE_FD, fd); 316251875Speter 317251875Speter if (res < 0) { 318251875Speter /* The expected case for this failure is that another 319251875Speter * thread's call to port_getn() returned this fd and 320251875Speter * disassociated the fd from the event port, and 321251875Speter * impl_pollset_poll() is blocked on the ring lock, 322251875Speter * which this thread holds. 323251875Speter */ 324251875Speter err = errno; 325251875Speter rv = APR_NOTFOUND; 326251875Speter } 327251875Speter 328251875Speter for (ep = APR_RING_FIRST(&(pollset->p->query_ring)); 329251875Speter ep != APR_RING_SENTINEL(&(pollset->p->query_ring), 330251875Speter pfd_elem_t, link); 331251875Speter ep = APR_RING_NEXT(ep, link)) { 332251875Speter 333251875Speter if (descriptor->desc.s == ep->pfd.desc.s) { 334251875Speter APR_RING_REMOVE(ep, link); 335251875Speter ep->on_query_ring = 0; 336251875Speter APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), 337251875Speter ep, pfd_elem_t, link); 338251875Speter if (ENOENT == err) { 339251875Speter rv = APR_SUCCESS; 340251875Speter } 341251875Speter break; 342251875Speter } 343251875Speter } 344251875Speter } 345251875Speter 346251875Speter pollset_unlock_rings(); 347251875Speter 348251875Speter return rv; 349251875Speter} 350251875Speter 351251875Speterstatic apr_status_t impl_pollset_poll(apr_pollset_t *pollset, 352251875Speter apr_interval_time_t timeout, 353251875Speter apr_int32_t *num, 354251875Speter const apr_pollfd_t **descriptors) 355251875Speter{ 356251875Speter apr_os_sock_t fd; 357251875Speter int ret, i, j; 358251875Speter unsigned int nget; 359251875Speter pfd_elem_t *ep; 360251875Speter apr_status_t rv = APR_SUCCESS; 361251875Speter apr_pollfd_t fp; 362251875Speter 363251875Speter nget = 1; 364251875Speter 365251875Speter pollset_lock_rings(); 366251875Speter 367251875Speter apr_atomic_inc32(&pollset->p->waiting); 368251875Speter 369251875Speter while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { 370251875Speter ep = APR_RING_FIRST(&(pollset->p->add_ring)); 371251875Speter APR_RING_REMOVE(ep, link); 372251875Speter 373251875Speter if (ep->pfd.desc_type == APR_POLL_SOCKET) { 374251875Speter fd = ep->pfd.desc.s->socketdes; 375251875Speter } 376251875Speter else { 377251875Speter fd = ep->pfd.desc.f->filedes; 378251875Speter } 379251875Speter 380251875Speter ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, 381251875Speter fd, get_event(ep->pfd.reqevents), ep); 382251875Speter if (ret < 0) { 383251875Speter rv = apr_get_netos_error(); 384251875Speter APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); 385251875Speter break; 386251875Speter } 387251875Speter 388251875Speter ep->on_query_ring = 1; 389251875Speter APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); 390251875Speter } 391251875Speter 392251875Speter pollset_unlock_rings(); 393251875Speter 394251875Speter if (rv != APR_SUCCESS) { 395251875Speter apr_atomic_dec32(&pollset->p->waiting); 396251875Speter return rv; 397251875Speter } 398251875Speter 399251875Speter rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set, 400251875Speter pollset->nalloc, &nget, timeout); 401251875Speter 402251875Speter /* decrease the waiting ASAP to reduce the window for calling 403251875Speter port_associate within apr_pollset_add() */ 404251875Speter apr_atomic_dec32(&pollset->p->waiting); 405251875Speter 406251875Speter (*num) = nget; 407251875Speter if (nget) { 408251875Speter 409251875Speter pollset_lock_rings(); 410251875Speter 411251875Speter for (i = 0, j = 0; i < nget; i++) { 412251875Speter fp = (((pfd_elem_t*)(pollset->p->port_set[i].portev_user))->pfd); 413251875Speter if ((pollset->flags & APR_POLLSET_WAKEABLE) && 414251875Speter fp.desc_type == APR_POLL_FILE && 415251875Speter fp.desc.f == pollset->wakeup_pipe[0]) { 416251875Speter apr_pollset_drain_wakeup_pipe(pollset); 417251875Speter rv = APR_EINTR; 418251875Speter } 419251875Speter else { 420251875Speter pollset->p->result_set[j] = fp; 421251875Speter pollset->p->result_set[j].rtnevents = 422251875Speter get_revent(pollset->p->port_set[i].portev_events); 423251875Speter 424251875Speter /* If the ring element is still on the query ring, move it 425251875Speter * to the add ring for re-association with the event port 426251875Speter * later. (It may have already been moved to the dead ring 427251875Speter * by a call to pollset_remove on another thread.) 428251875Speter */ 429251875Speter ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; 430251875Speter if (ep->on_query_ring) { 431251875Speter APR_RING_REMOVE(ep, link); 432251875Speter ep->on_query_ring = 0; 433251875Speter APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, 434251875Speter pfd_elem_t, link); 435251875Speter } 436251875Speter j++; 437251875Speter } 438251875Speter } 439251875Speter pollset_unlock_rings(); 440251875Speter if ((*num = j)) { /* any event besides wakeup pipe? */ 441251875Speter rv = APR_SUCCESS; 442251875Speter if (descriptors) { 443251875Speter *descriptors = pollset->p->result_set; 444251875Speter } 445251875Speter } 446251875Speter } 447251875Speter 448251875Speter pollset_lock_rings(); 449251875Speter 450251875Speter /* Shift all PFDs in the Dead Ring to the Free Ring */ 451251875Speter APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); 452251875Speter 453251875Speter pollset_unlock_rings(); 454251875Speter 455251875Speter return rv; 456251875Speter} 457251875Speter 458251875Speterstatic apr_pollset_provider_t impl = { 459251875Speter impl_pollset_create, 460251875Speter impl_pollset_add, 461251875Speter impl_pollset_remove, 462251875Speter impl_pollset_poll, 463251875Speter impl_pollset_cleanup, 464251875Speter "port" 465251875Speter}; 466251875Speter 467251875Speterapr_pollset_provider_t *apr_pollset_provider_port = &impl; 468251875Speter 469251875Speterstatic apr_status_t cb_cleanup(void *p_) 470251875Speter{ 471251875Speter apr_pollcb_t *pollcb = (apr_pollcb_t *) p_; 472251875Speter close(pollcb->fd); 473251875Speter return APR_SUCCESS; 474251875Speter} 475251875Speter 476251875Speterstatic apr_status_t impl_pollcb_create(apr_pollcb_t *pollcb, 477251875Speter apr_uint32_t size, 478251875Speter apr_pool_t *p, 479251875Speter apr_uint32_t flags) 480251875Speter{ 481251875Speter pollcb->fd = port_create(); 482251875Speter 483251875Speter if (pollcb->fd < 0) { 484251875Speter return apr_get_netos_error(); 485251875Speter } 486251875Speter 487251875Speter { 488251875Speter int flags; 489289166Speter apr_status_t rv; 490251875Speter 491289166Speter if ((flags = fcntl(pollcb->fd, F_GETFD)) == -1) { 492289166Speter rv = errno; 493289166Speter close(pollcb->fd); 494289166Speter pollcb->fd = -1; 495289166Speter return rv; 496289166Speter } 497251875Speter 498251875Speter flags |= FD_CLOEXEC; 499289166Speter if (fcntl(pollcb->fd, F_SETFD, flags) == -1) { 500289166Speter rv = errno; 501289166Speter close(pollcb->fd); 502289166Speter pollcb->fd = -1; 503289166Speter return rv; 504289166Speter } 505251875Speter } 506251875Speter 507251875Speter pollcb->pollset.port = apr_palloc(p, size * sizeof(port_event_t)); 508251875Speter apr_pool_cleanup_register(p, pollcb, cb_cleanup, apr_pool_cleanup_null); 509251875Speter 510251875Speter return APR_SUCCESS; 511251875Speter} 512251875Speter 513251875Speterstatic apr_status_t impl_pollcb_add(apr_pollcb_t *pollcb, 514251875Speter apr_pollfd_t *descriptor) 515251875Speter{ 516251875Speter int ret, fd; 517251875Speter 518251875Speter if (descriptor->desc_type == APR_POLL_SOCKET) { 519251875Speter fd = descriptor->desc.s->socketdes; 520251875Speter } 521251875Speter else { 522251875Speter fd = descriptor->desc.f->filedes; 523251875Speter } 524251875Speter 525251875Speter ret = port_associate(pollcb->fd, PORT_SOURCE_FD, fd, 526251875Speter get_event(descriptor->reqevents), descriptor); 527251875Speter 528251875Speter if (ret == -1) { 529251875Speter return apr_get_netos_error(); 530251875Speter } 531251875Speter 532251875Speter return APR_SUCCESS; 533251875Speter} 534251875Speter 535251875Speterstatic apr_status_t impl_pollcb_remove(apr_pollcb_t *pollcb, 536251875Speter apr_pollfd_t *descriptor) 537251875Speter{ 538251875Speter int fd, ret; 539251875Speter 540251875Speter if (descriptor->desc_type == APR_POLL_SOCKET) { 541251875Speter fd = descriptor->desc.s->socketdes; 542251875Speter } 543251875Speter else { 544251875Speter fd = descriptor->desc.f->filedes; 545251875Speter } 546251875Speter 547251875Speter ret = port_dissociate(pollcb->fd, PORT_SOURCE_FD, fd); 548251875Speter 549251875Speter if (ret < 0) { 550251875Speter return APR_NOTFOUND; 551251875Speter } 552251875Speter 553251875Speter return APR_SUCCESS; 554251875Speter} 555251875Speter 556251875Speterstatic apr_status_t impl_pollcb_poll(apr_pollcb_t *pollcb, 557251875Speter apr_interval_time_t timeout, 558251875Speter apr_pollcb_cb_t func, 559251875Speter void *baton) 560251875Speter{ 561251875Speter apr_pollfd_t *pollfd; 562251875Speter apr_status_t rv; 563251875Speter unsigned int i, nget = 1; 564251875Speter 565251875Speter rv = call_port_getn(pollcb->fd, pollcb->pollset.port, pollcb->nalloc, 566251875Speter &nget, timeout); 567251875Speter 568251875Speter if (nget) { 569251875Speter for (i = 0; i < nget; i++) { 570251875Speter pollfd = (apr_pollfd_t *)(pollcb->pollset.port[i].portev_user); 571251875Speter pollfd->rtnevents = get_revent(pollcb->pollset.port[i].portev_events); 572251875Speter 573251875Speter rv = func(baton, pollfd); 574251875Speter if (rv) { 575251875Speter return rv; 576251875Speter } 577251875Speter rv = apr_pollcb_add(pollcb, pollfd); 578251875Speter } 579251875Speter } 580251875Speter 581251875Speter return rv; 582251875Speter} 583251875Speter 584251875Speterstatic apr_pollcb_provider_t impl_cb = { 585251875Speter impl_pollcb_create, 586251875Speter impl_pollcb_add, 587251875Speter impl_pollcb_remove, 588251875Speter impl_pollcb_poll, 589251875Speter "port" 590251875Speter}; 591251875Speter 592251875Speterapr_pollcb_provider_t *apr_pollcb_provider_port = &impl_cb; 593251875Speter 594251875Speter#endif /* HAVE_PORT_CREATE */ 595