static apt_bool_t mrcp_client_agent_channel_add(mrcp_connection_agent_t *agent, mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor) { if(agent->offer_new_connection == TRUE) { descriptor->connection_type = MRCP_CONNECTION_TYPE_NEW; } else { descriptor->connection_type = MRCP_CONNECTION_TYPE_EXISTING; if(APR_RING_EMPTY(&agent->connection_list, mrcp_connection_t, link)) { /* offer new connection if there is no established connection yet */ descriptor->connection_type = MRCP_CONNECTION_TYPE_NEW; } } /* send response */ return mrcp_control_channel_add_respond(agent->vtable,channel,descriptor,TRUE); }
/** Kill timer */ MPF_DECLARE(apt_bool_t) mpf_timer_kill(mpf_timer_t *timer) { if(!timer->scheduled_time) { return FALSE; } apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Kill Timer 0x%x [%lu]",timer,timer->scheduled_time); /* remove node (timer) from the list */ APR_RING_REMOVE(timer,link); timer->scheduled_time = 0; if(APR_RING_EMPTY(&timer->manager->head, mpf_timer_t, link)) { /* reset elapsed time if no timers set */ timer->manager->elapsed_time = 0; } return TRUE; }
/** Get current timeout */ APT_DECLARE(apt_bool_t) apt_timer_queue_timeout_get(const apt_timer_queue_t *timer_queue, apr_uint32_t *timeout) { apt_timer_t *timer; /* is queue empty */ if(APR_RING_EMPTY(&timer_queue->head, apt_timer_t, link)) { return FALSE; } /* get first node (timer) */ timer = APR_RING_FIRST(&timer_queue->head); if(!timer) { return FALSE; } *timeout = timer->scheduled_time - timer_queue->elapsed_time; return TRUE; }
APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { apr_os_sock_t fd; pfd_elem_t *elem; int res; apr_status_t rv = APR_SUCCESS; pollset_lock_rings(); 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; if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } else { fd = descriptor->desc.f->filedes; } 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); } else { pollset->nelts++; APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); return rv; }
/** Set one-shot timer */ MPF_DECLARE(apt_bool_t) mpf_timer_set(mpf_timer_t *timer, apr_uint32_t timeout) { mpf_timer_manager_t *manager = timer->manager; if(timeout <= 0 || !timer->proc) { return FALSE; } /* calculate time to elapse */ timer->scheduled_time = manager->elapsed_time + timeout; apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Set Timer 0x%x [%lu]",timer,timer->scheduled_time); if(APR_RING_EMPTY(&timer->manager->head, mpf_timer_t, link)) { APR_RING_INSERT_TAIL(&manager->head,timer,mpf_timer_t,link); return TRUE; } /* insert new node (timer) to sorted by scheduled time list */ return mpf_timer_insert(manager,timer); }
/** Kill timer */ APT_DECLARE(apt_bool_t) apt_timer_kill(apt_timer_t *timer) { apt_timer_queue_t *queue = timer->queue; if(!timer->scheduled_time) { return FALSE; } #ifdef APT_TIMER_DEBUG apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Kill Timer 0x%x [%u]",timer,timer->scheduled_time); #endif /* remove node (timer) from the list */ APR_RING_REMOVE(timer,link); timer->scheduled_time = 0; if(APR_RING_EMPTY(&queue->head, apt_timer_t, link)) { /* reset elapsed time if no timers set */ queue->elapsed_time = 0; } return TRUE; }
/* * NOTE: This function is not thread safe by itself. Caller should hold the lock */ static struct apr_thread_list_elt *elt_new(apr_thread_pool_t * me, apr_thread_t * t) { struct apr_thread_list_elt *elt; if (APR_RING_EMPTY(me->recycled_thds, apr_thread_list_elt, link)) { elt = apr_pcalloc(me->pool, sizeof(*elt)); if (NULL == elt) { return NULL; } } else { elt = APR_RING_FIRST(me->recycled_thds); APR_RING_REMOVE(elt, link); } APR_RING_ELEM_INIT(elt, link); elt->thd = t; elt->current_owner = NULL; elt->state = TH_RUN; return elt; }
/** Set one-shot timer */ APT_DECLARE(apt_bool_t) apt_timer_set(apt_timer_t *timer, apr_uint32_t timeout) { apt_timer_queue_t *queue = timer->queue; if(timeout <= 0 || !timer->proc) { return FALSE; } /* calculate time to elapse */ timer->scheduled_time = queue->elapsed_time + timeout; #ifdef APT_TIMER_DEBUG apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Set Timer 0x%x [%u]",timer,timer->scheduled_time); #endif if(APR_RING_EMPTY(&queue->head, apt_timer_t, link)) { APR_RING_INSERT_TAIL(&queue->head,timer,apt_timer_t,link); return TRUE; } /* insert new node (timer) to sorted by scheduled time list */ return apt_timer_insert(queue,timer); }
/* * purge cache entries */ static void purge(char *path, apr_pool_t *pool, apr_off_t max) { apr_off_t sum, total, entries, etotal; ENTRY *e, *n, *oldest; sum = 0; entries = 0; for (e = APR_RING_FIRST(&root); e != APR_RING_SENTINEL(&root, _entry, link); e = APR_RING_NEXT(e, link)) { sum += e->hsize; sum += e->dsize; entries++; } total = sum; etotal = entries; if (sum <= max) { printstats(total, sum, max, etotal, entries); return; } /* process all entries with a timestamp in the future, this may * happen if a wrong system time is corrected */ for (e = APR_RING_FIRST(&root); e != APR_RING_SENTINEL(&root, _entry, link) && !interrupted;) { n = APR_RING_NEXT(e, link); if (e->response_time > now || e->htime > now || e->dtime > now) { delete_entry(path, e->basename, pool); sum -= e->hsize; sum -= e->dsize; entries--; APR_RING_REMOVE(e, link); if (sum <= max) { if (!interrupted) { printstats(total, sum, max, etotal, entries); } return; } } e = n; } if (interrupted) { return; } /* process all entries with are expired */ for (e = APR_RING_FIRST(&root); e != APR_RING_SENTINEL(&root, _entry, link) && !interrupted;) { n = APR_RING_NEXT(e, link); if (e->expire != APR_DATE_BAD && e->expire < now) { delete_entry(path, e->basename, pool); sum -= e->hsize; sum -= e->dsize; entries--; APR_RING_REMOVE(e, link); if (sum <= max) { if (!interrupted) { printstats(total, sum, max, etotal, entries); } return; } } e = n; } if (interrupted) { return; } /* process remaining entries oldest to newest, the check for an emtpy * ring actually isn't necessary except when the compiler does * corrupt 64bit arithmetics which happend to me once, so better safe * than sorry */ while (sum > max && !interrupted && !APR_RING_EMPTY(&root, _entry, link)) { oldest = APR_RING_FIRST(&root); for (e = APR_RING_NEXT(oldest, link); e != APR_RING_SENTINEL(&root, _entry, link); e = APR_RING_NEXT(e, link)) { if (e->dtime < oldest->dtime) { oldest = e; } } delete_entry(path, oldest->basename, pool); sum -= oldest->hsize; sum -= oldest->dsize; entries--; APR_RING_REMOVE(oldest, link); } if (!interrupted) { printstats(total, sum, max, etotal, entries); } }
APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors) { apr_os_sock_t fd; int ret, i; unsigned int nget; pfd_elem_t *ep; struct timespec tv, *tvptr; apr_status_t rv = APR_SUCCESS; if (timeout < 0) { tvptr = NULL; } else { tv.tv_sec = (long) apr_time_sec(timeout); tv.tv_nsec = (long) apr_time_usec(timeout) * 1000; tvptr = &tv; } nget = 1; pollset_lock_rings(); while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { ep = APR_RING_FIRST(&(pollset->add_ring)); APR_RING_REMOVE(ep, link); if (ep->pfd.desc_type == APR_POLL_SOCKET) { fd = ep->pfd.desc.s->socketdes; } else { fd = ep->pfd.desc.f->filedes; } port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, get_event(ep->pfd.reqevents), ep); APR_RING_INSERT_TAIL(&(pollset->query_ring), ep, pfd_elem_t, link); } pollset_unlock_rings(); ret = port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc, &nget, tvptr); (*num) = nget; if (ret == -1) { (*num) = 0; if (errno == ETIME || errno == EINTR) { rv = APR_TIMEUP; } else { rv = APR_EGENERAL; } } else if (nget == 0) { rv = APR_TIMEUP; } else { pollset_lock_rings(); for (i = 0; i < nget; i++) { pollset->result_set[i] = (((pfd_elem_t*)(pollset->port_set[i].portev_user))->pfd); pollset->result_set[i].rtnevents = get_revent(pollset->port_set[i].portev_events); APR_RING_REMOVE((pfd_elem_t*)pollset->port_set[i].portev_user, link); APR_RING_INSERT_TAIL(&(pollset->add_ring), (pfd_elem_t*)pollset->port_set[i].portev_user, pfd_elem_t, link); } pollset_unlock_rings(); if (descriptors) { *descriptors = pollset->result_set; } } pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to be Free Ring */ APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); return rv; }
/* core's child-status hook * tracks number of remaining children per generation and * runs the end-generation hook when the last child of * a generation exits */ void ap_core_child_status(server_rec *s, pid_t pid, ap_generation_t gen, int slot, mpm_child_status status) { mpm_gen_info_t *cur; const char *status_msg = "unknown status"; if (!gen_head_init) { /* where to run this? */ gen_head_init = 1; geninfo = apr_pcalloc(s->process->pool, sizeof *geninfo); unused_geninfo = apr_pcalloc(s->process->pool, sizeof *unused_geninfo); APR_RING_INIT(geninfo, mpm_gen_info_t, link); APR_RING_INIT(unused_geninfo, mpm_gen_info_t, link); } cur = APR_RING_FIRST(geninfo); while (cur != APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link) && cur->gen != gen) { cur = APR_RING_NEXT(cur, link); } switch(status) { case MPM_CHILD_STARTED: status_msg = "started"; if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { /* first child for this generation */ if (!APR_RING_EMPTY(unused_geninfo, mpm_gen_info_t, link)) { cur = APR_RING_FIRST(unused_geninfo); APR_RING_REMOVE(cur, link); cur->active = cur->done = 0; } else { cur = apr_pcalloc(s->process->pool, sizeof *cur); } cur->gen = gen; APR_RING_ELEM_INIT(cur, link); APR_RING_INSERT_HEAD(geninfo, cur, mpm_gen_info_t, link); } ap_random_parent_after_fork(); ++cur->active; break; case MPM_CHILD_EXITED: ap_update_global_status(); status_msg = "exited"; if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(00546) "no record of generation %d of exiting child %" APR_PID_T_FMT, gen, pid); } else { --cur->active; if (!cur->active && cur->done) { /* no children, server has stopped/restarted */ end_gen(cur); } } break; case MPM_CHILD_LOST_SLOT: status_msg = "lost slot"; /* we don't track by slot, so it doesn't matter */ break; } ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, s, "mpm child %" APR_PID_T_FMT " (gen %d/slot %d) %s", pid, gen, slot, status_msg); }
/** Is timer queue empty */ APT_DECLARE(apt_bool_t) apt_timer_queue_is_empty(const apt_timer_queue_t *timer_queue) { return APR_RING_EMPTY(&timer_queue->head, apt_timer_t, link) ? TRUE : FALSE; }
static apr_status_t impl_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors) { apr_os_sock_t fd; int ret, i, j; unsigned int nget; pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; apr_pollfd_t fp; nget = 1; pollset_lock_rings(); apr_atomic_inc32(&pollset->p->waiting); while (!APR_RING_EMPTY(&(pollset->p->add_ring), pfd_elem_t, link)) { ep = APR_RING_FIRST(&(pollset->p->add_ring)); APR_RING_REMOVE(ep, link); if (ep->pfd.desc_type == APR_POLL_SOCKET) { fd = ep->pfd.desc.s->socketdes; } else { fd = ep->pfd.desc.f->filedes; } ret = port_associate(pollset->p->port_fd, PORT_SOURCE_FD, fd, get_event(ep->pfd.reqevents), ep); if (ret < 0) { rv = apr_get_netos_error(); APR_RING_INSERT_TAIL(&(pollset->p->free_ring), ep, pfd_elem_t, link); break; } ep->on_query_ring = 1; APR_RING_INSERT_TAIL(&(pollset->p->query_ring), ep, pfd_elem_t, link); } pollset_unlock_rings(); if (rv != APR_SUCCESS) { apr_atomic_dec32(&pollset->p->waiting); return rv; } rv = call_port_getn(pollset->p->port_fd, pollset->p->port_set, pollset->nalloc, &nget, timeout); /* decrease the waiting ASAP to reduce the window for calling port_associate within apr_pollset_add() */ apr_atomic_dec32(&pollset->p->waiting); (*num) = nget; if (nget) { pollset_lock_rings(); for (i = 0, j = 0; i < nget; i++) { fp = (((pfd_elem_t*)(pollset->p->port_set[i].portev_user))->pfd); if ((pollset->flags & APR_POLLSET_WAKEABLE) && fp.desc_type == APR_POLL_FILE && fp.desc.f == pollset->wakeup_pipe[0]) { apr_pollset_drain_wakeup_pipe(pollset); rv = APR_EINTR; } else { pollset->p->result_set[j] = fp; pollset->p->result_set[j].rtnevents = get_revent(pollset->p->port_set[i].portev_events); /* If the ring element is still on the query ring, move it * to the add ring for re-association with the event port * later. (It may have already been moved to the dead ring * by a call to pollset_remove on another thread.) */ ep = (pfd_elem_t *)pollset->p->port_set[i].portev_user; if (ep->on_query_ring) { APR_RING_REMOVE(ep, link); ep->on_query_ring = 0; APR_RING_INSERT_TAIL(&(pollset->p->add_ring), ep, pfd_elem_t, link); } j++; } } pollset_unlock_rings(); if ((*num = j)) { /* any event besides wakeup pipe? */ rv = APR_SUCCESS; if (descriptors) { *descriptors = pollset->p->result_set; } } } pollset_lock_rings(); /* Shift all PFDs in the Dead Ring to the Free Ring */ APR_RING_CONCAT(&(pollset->p->free_ring), &(pollset->p->dead_ring), pfd_elem_t, link); pollset_unlock_rings(); return rv; }
static apr_status_t impl_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { #ifdef HAVE_MTCP struct mtcp_epoll_event ev = {0}; #else struct epoll_event ev = {0}; #endif int ret = -1; pfd_elem_t *elem = NULL; apr_status_t rv = APR_SUCCESS; ev.events = get_epoll_event(descriptor->reqevents); if (pollset->flags & APR_POLLSET_NOCOPY) { ev.data.ptr = (void *)descriptor; } else { pollset_lock_rings(); 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->pfd = *descriptor; ev.data.ptr = elem; } if (descriptor->desc_type == APR_POLL_SOCKET) { #ifdef HAVE_MTCP int cpu = sched_getcpu(); ret = mtcp_epoll_ctl(g_mctx[cpu], pollset->p->epoll_fd, EPOLL_CTL_ADD, descriptor->desc.s->socketdes, &ev); if(ret!=0 && errno != EEXIST) perror("mtcp_epoll_ctl"); #else ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD, descriptor->desc.s->socketdes, &ev); #endif } else { /* TODO: Non-socket fd? */ #ifndef HAVE_MTCP ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD, descriptor->desc.f->filedes, &ev); #endif } if (0 != ret) { rv = apr_get_netos_error(); } if (!(pollset->flags & APR_POLLSET_NOCOPY)) { if (rv != APR_SUCCESS) { APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); } else { APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); } return rv; }