static void wait_on_busy_threads(apr_thread_pool_t *me, void *owner) { #ifndef NDEBUG apr_os_thread_t *os_thread; #endif struct apr_thread_list_elt *elt; apr_thread_mutex_lock(me->lock); elt = APR_RING_FIRST(me->busy_thds); while (elt != APR_RING_SENTINEL(me->busy_thds, apr_thread_list_elt, link)) { if (elt->current_owner != owner) { elt = APR_RING_NEXT(elt, link); continue; } #ifndef NDEBUG /* make sure the thread is not the one calling tasks_cancel */ apr_os_thread_get(&os_thread, elt->thd); #ifdef WIN32 /* hack for apr win32 bug */ assert(!apr_os_thread_equal(apr_os_thread_current(), os_thread)); #else assert(!apr_os_thread_equal(apr_os_thread_current(), *os_thread)); #endif #endif while (elt->current_owner == owner) { apr_thread_mutex_unlock(me->lock); apr_sleep(200 * 1000); apr_thread_mutex_lock(me->lock); } elt = APR_RING_FIRST(me->busy_thds); } apr_thread_mutex_unlock(me->lock); return; }
APR_DECLARE(apr_status_t) apr_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; pollset_lock_rings(); if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } else { fd = descriptor->desc.f->filedes; } res = port_dissociate(pollset->port_fd, PORT_SOURCE_FD, fd); if (res < 0) { 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 (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { 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 (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(); return rv; }
/** * Called by other modules to print their "jmx beans" to the response in * whatever format was requested by the client. */ static apr_status_t bmx_bean_print_text_plain(request_rec *r, const struct bmx_bean *bean) { apr_size_t objectname_strlen = bmx_objectname_strlen(bean->objectname) + 1; char *objectname_str = apr_palloc(r->pool, objectname_strlen); (void)bmx_objectname_str(bean->objectname, objectname_str, objectname_strlen); (void)ap_rputs("Name: ", r); (void)ap_rputs(objectname_str, r); (void)ap_rputs("\n", r); /* for each element in bean->bean_properties, print it */ if (!APR_RING_EMPTY(&(bean->bean_props), bmx_property, link)) { struct bmx_property *p = NULL; const char *value; for (p = APR_RING_FIRST(&(bean->bean_props)); p != APR_RING_SENTINEL(&(bean->bean_props), bmx_property, link); p = APR_RING_NEXT(p, link)) { (void)ap_rputs(p->key, r); (void)ap_rputs(": ", r); value = property_print(r->pool, p); if (value) (void)ap_rputs(value, r); (void)ap_rputs("\n", r); } } (void)ap_rputs("\n", r); return APR_SUCCESS; }
APT_DECLARE(apt_list_elem_t*) apt_list_first_elem_get(apt_obj_list_t *list) { if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) { return NULL; } return APR_RING_FIRST(&list->head); }
/* * NOTE: This function is not thread safe by itself. Caller should hold the lock */ static apr_thread_pool_task_t *task_new(apr_thread_pool_t * me, apr_thread_start_t func, void *param, apr_byte_t priority, void *owner, apr_time_t time) { apr_thread_pool_task_t *t; if (APR_RING_EMPTY(me->recycled_tasks, apr_thread_pool_task, link)) { t = apr_pcalloc(me->pool, sizeof(*t)); if (NULL == t) { return NULL; } } else { t = APR_RING_FIRST(me->recycled_tasks); APR_RING_REMOVE(t, link); } APR_RING_ELEM_INIT(t, link); t->func = func; t->param = param; t->owner = owner; if (time > 0) { t->dispatch.time = apr_time_now() + time; } else { t->dispatch.priority = priority; } return t; }
static apr_status_t remove_tasks(apr_thread_pool_t *me, void *owner) { apr_thread_pool_task_t *t_loc; apr_thread_pool_task_t *next; int seg; t_loc = APR_RING_FIRST(me->tasks); while (t_loc != APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link)) { next = APR_RING_NEXT(t_loc, link); if (t_loc->owner == owner) { --me->task_cnt; seg = TASK_PRIORITY_SEG(t_loc); if (t_loc == me->task_idx[seg]) { me->task_idx[seg] = APR_RING_NEXT(t_loc, link); if (me->task_idx[seg] == APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link) || TASK_PRIORITY_SEG(me->task_idx[seg]) != seg) { me->task_idx[seg] = NULL; } } APR_RING_REMOVE(t_loc, link); } t_loc = next; } return APR_SUCCESS; }
apr_status_t ap_mpm_end_gen_helper(void *unused) /* cleanup on pconf */ { int gen = ap_config_generation - 1; /* differs from MPM generation */ mpm_gen_info_t *cur; if (geninfo == NULL) { /* initial pconf teardown, MPM hasn't run */ return APR_SUCCESS; } 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); } if (cur == APR_RING_SENTINEL(geninfo, mpm_gen_info_t, link)) { /* last child of generation already exited */ ap_log_error(APLOG_MARK, APLOG_TRACE4, 0, ap_server_conf, "no record of generation %d", gen); } else { cur->done = 1; if (cur->active == 0) { end_gen(cur); } } return APR_SUCCESS; }
/** Get (copy) MRCP header fields */ MRCP_DECLARE(apt_bool_t) mrcp_header_fields_get(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, const mrcp_message_header_t *mask_header, apr_pool_t *pool) { apt_header_field_t *header_field; const apt_header_field_t *src_header_field; const apt_header_field_t *mask_header_field; for(mask_header_field = APR_RING_FIRST(&mask_header->header_section.ring); mask_header_field != APR_RING_SENTINEL(&mask_header->header_section.ring, apt_header_field_t, link); mask_header_field = APR_RING_NEXT(mask_header_field, link)) { header_field = apt_header_section_field_get(&header->header_section,mask_header_field->id); if(header_field) { /* this header field has already been set, skip to the next one */ continue; } src_header_field = apt_header_section_field_get(&src_header->header_section,mask_header_field->id); if(src_header_field) { /* copy the entire header field */ header_field = apt_header_field_copy(src_header_field,pool); mrcp_header_accessor_value_duplicate(header,header_field,src_header,src_header_field,pool); } else { /* copy only the name of the header field */ header_field = apt_header_field_copy(mask_header_field,pool); } /* add the header field to the header section */ apt_header_section_field_add(&header->header_section,header_field); } return TRUE; }
/** * Grab a resource from the front of the resource list. * Assumes: that the reslist is locked. */ static apr_res_t *pop_resource(apr_reslist_t *reslist) { apr_res_t *res; res = APR_RING_FIRST(&reslist->avail_list); APR_RING_REMOVE(res, link); reslist->nidle--; return res; }
APT_DECLARE(void*) apt_list_head(apt_obj_list_t *list) { apt_list_elem_t *elem; if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) { return NULL; } elem = APR_RING_FIRST(&list->head); return elem->obj; }
MPF_DECLARE(void) mpf_context_factory_destroy(mpf_context_factory_t *factory) { mpf_context_t *context; while(!APR_RING_EMPTY(&factory->head, mpf_context_t, link)) { context = APR_RING_FIRST(&factory->head); mpf_context_destroy(context); APR_RING_REMOVE(context, link); } }
static APR_INLINE mpf_chunk_t* mpf_buffer_chunk_read(mpf_buffer_t *buffer) { mpf_chunk_t *chunk = NULL; if(!APR_RING_EMPTY(&buffer->head,mpf_chunk_t,link)) { chunk = APR_RING_FIRST(&buffer->head); APR_RING_REMOVE(chunk,link); } return chunk; }
/** * Retrieves the next available socket from the queue. If there are no * sockets available, it will block until one becomes available. * Once retrieved, the socket is placed into the address specified by * 'sd'. */ apr_status_t ap_queue_pop_something(fd_queue_t * queue, apr_socket_t ** sd, event_conn_state_t ** ecs, apr_pool_t ** p, timer_event_t ** te_out) { fd_queue_elem_t *elem; apr_status_t rv; if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) { return rv; } /* Keep waiting until we wake up and find that the queue is not empty. */ if (ap_queue_empty(queue)) { if (!queue->terminated) { apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex); } /* If we wake up and it's still empty, then we were interrupted */ if (ap_queue_empty(queue)) { rv = apr_thread_mutex_unlock(queue->one_big_mutex); if (rv != APR_SUCCESS) { return rv; } if (queue->terminated) { return APR_EOF; /* no more elements ever again */ } else { return APR_EINTR; } } } *te_out = NULL; if (!APR_RING_EMPTY(&queue->timers, timer_event_t, link)) { *te_out = APR_RING_FIRST(&queue->timers); APR_RING_REMOVE(*te_out, link); } else { elem = &queue->data[queue->out]; queue->out++; if (queue->out >= queue->bounds) queue->out -= queue->bounds; queue->nelts--; *sd = elem->sd; *ecs = elem->ecs; *p = elem->p; #ifdef AP_DEBUG elem->sd = NULL; elem->p = NULL; #endif /* AP_DEBUG */ } rv = apr_thread_mutex_unlock(queue->one_big_mutex); return rv; }
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; apr_status_t rv = APR_SUCCESS; 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; 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(&pollset->p->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem); if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { rv = apr_get_netos_error(); } } if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem); if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) == -1) { rv = apr_get_netos_error(); } } if (rv == APR_SUCCESS) { APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); } else { APR_RING_INSERT_TAIL(&(pollset->p->free_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); return rv; }
/** Generate header section */ APT_DECLARE(apt_bool_t) apt_header_section_generate(const apt_header_section_t *header, apt_text_stream_t *stream) { apt_header_field_t *header_field; for(header_field = APR_RING_FIRST(&header->ring); header_field != APR_RING_SENTINEL(&header->ring, apt_header_field_t, link); header_field = APR_RING_NEXT(header_field, link)) { apt_header_field_generate(header_field,stream); } return apt_text_eol_insert(stream); }
static apr_interval_time_t waiting_time(apr_thread_pool_t * me) { apr_thread_pool_task_t *task = NULL; task = APR_RING_FIRST(me->scheduled_tasks); assert(task != NULL); assert(task != APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task, link)); return task->dispatch.time - apr_time_now(); }
/** * Get an empty resource container from the free list. */ static apr_res_t *get_container(apr_reslist_t *reslist) { apr_res_t *res; assert(!APR_RING_EMPTY(&reslist->free_list, apr_res_t, link)); res = APR_RING_FIRST(&reslist->free_list); APR_RING_REMOVE(res, link); return res; }
/** * Get an resource container from the free list or create a new one. */ static apr_res_t *get_container(apr_reslist_t *reslist) { apr_res_t *res; if (!APR_RING_EMPTY(&reslist->free_list, apr_res_t, link)) { res = APR_RING_FIRST(&reslist->free_list); APR_RING_REMOVE(res, link); } else res = apr_pcalloc(reslist->pool, sizeof(*res)); return res; }
static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { pfd_elem_t *ep; apr_status_t rv = APR_SUCCESS; #ifdef HAVE_MTCP struct mtcp_epoll_event ev = {0}; #else struct epoll_event ev = {0}; /* ignored, but must be passed with * kernel < 2.6.9 */ #endif int ret = -1; 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_DEL, descriptor->desc.s->socketdes, &ev); #else ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL, descriptor->desc.s->socketdes, &ev); #endif } else { ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_DEL, descriptor->desc.f->filedes, &ev); } if (ret < 0) { rv = APR_NOTFOUND; } if (!(pollset->flags & APR_POLLSET_NOCOPY)) { pollset_lock_rings(); 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); APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), ep, pfd_elem_t, link); break; } } pollset_unlock_rings(); } return rv; }
MPF_DECLARE(apt_bool_t) mpf_context_factory_process(mpf_context_factory_t *factory) { mpf_context_t *context; for(context = APR_RING_FIRST(&factory->head); context != APR_RING_SENTINEL(&factory->head, mpf_context_t, link); context = APR_RING_NEXT(context, link)) { mpf_context_process(context); } return TRUE; }
/* * NOTE: This function is not thread safe by itself. Caller should hold the lock */ static apr_thread_pool_task_t *pop_task(apr_thread_pool_t * me) { apr_thread_pool_task_t *task = NULL; int seg; /* check for scheduled tasks */ if (me->scheduled_task_cnt > 0) { task = APR_RING_FIRST(me->scheduled_tasks); assert(task != NULL); assert(task != APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task, link)); /* if it's time */ if (task->dispatch.time <= apr_time_now()) { --me->scheduled_task_cnt; APR_RING_REMOVE(task, link); return task; } } /* check for normal tasks if we're not returning a scheduled task */ if (me->task_cnt == 0) { return NULL; } task = APR_RING_FIRST(me->tasks); assert(task != NULL); assert(task != APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link)); --me->task_cnt; seg = TASK_PRIORITY_SEG(task); if (task == me->task_idx[seg]) { me->task_idx[seg] = APR_RING_NEXT(task, link); if (me->task_idx[seg] == APR_RING_SENTINEL(me->tasks, apr_thread_pool_task, link) || TASK_PRIORITY_SEG(me->task_idx[seg]) != seg) { me->task_idx[seg] = NULL; } } APR_RING_REMOVE(task, link); return task; }
/** Execute the filters. */ int kdfilter_exec(kdfilter *self, struct filter_params *params, struct filter_result *res) { struct filter_driver * en; memset(res, 0, sizeof(struct filter_result)); for (en = APR_RING_FIRST(&self->filter_drv_list); en != APR_RING_SENTINEL(&self->filter_drv_list, filter_driver, link); en = APR_RING_NEXT(en, link)) { kerror_reset(); INFO(_log_filter_, "Filtering message with filter: %s", en->filter_name); /* Filter test phase. */ DEBUG(_log_filter_, "Filter %s test phase.", en->filter_name); if ((en->p_test)(self, en->private_data) < 0) { if (kerror_has_error()) KERROR_PUSH(_filter_, 0, "filter %s failed test phase", en->filter_name); else KERROR_SET(_filter_, 0, "filter %s failed test phase", en->filter_name); return -1; } /* Proceed to filtering. */ DEBUG(_log_filter_, "Filter %s scan phase.", en->filter_name); if ((en->p_scan)(self, en->private_data, params, res) < 0) { if (kerror_has_error()) KERROR_PUSH(_filter_, 0, "filter %s failed scan", en->filter_name); else KERROR_SET(_filter_, 0, "filter %s failed scan", en->filter_name); return -1; } if (res->msg_state) INFO(_log_filter_, "Filter %s report: %s", en->filter_name, res->msg); else INFO(_log_filter_, "Filter %s returned an empty report.", en->filter_name); DEBUG(_log_filter_, "Filter %s rating: %d.", en->filter_name, res->rating); /* * If one of those bit is set, that means we need to interrupt the filtering * and go back to the main loop for confirmation. */ if ((res->rating & FILTER_EXEC_DENY) != 0 || (res->rating & FILTER_EXEC_CHALLENGE) != 0) return 0; } return 0; }
static apr_status_t impl_pollset_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { pfd_elem_t *ep; apr_status_t rv; apr_os_sock_t fd; pollset_lock_rings(); if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } else { fd = descriptor->desc.f->filedes; } rv = APR_NOTFOUND; /* unless at least one of the specified conditions is */ if (descriptor->reqevents & APR_POLLIN) { EV_SET(&pollset->p->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) != -1) { rv = APR_SUCCESS; } } if (descriptor->reqevents & APR_POLLOUT) { EV_SET(&pollset->p->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); if (kevent(pollset->p->kqueue_fd, &pollset->p->kevent, 1, NULL, 0, NULL) != -1) { rv = APR_SUCCESS; } } 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); APR_RING_INSERT_TAIL(&(pollset->p->dead_ring), ep, pfd_elem_t, link); break; } } pollset_unlock_rings(); return rv; }
static apr_status_t impl_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor) { struct epoll_event ev = {0}; 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) { ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD, descriptor->desc.s->socketdes, &ev); } else { ret = epoll_ctl(pollset->p->epoll_fd, EPOLL_CTL_ADD, descriptor->desc.f->filedes, &ev); } 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; }
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; int res; apr_status_t rv = APR_SUCCESS; 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->on_query_ring = 0; } elem->pfd = *descriptor; if (descriptor->desc_type == APR_POLL_SOCKET) { fd = descriptor->desc.s->socketdes; } else { fd = descriptor->desc.f->filedes; } /* If another thread is polling, notify the kernel immediately; otherwise, * wait until the next call to apr_pollset_poll(). */ 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->p->free_ring), elem, pfd_elem_t, link); } else { elem->on_query_ring = 1; APR_RING_INSERT_TAIL(&(pollset->p->query_ring), elem, pfd_elem_t, link); } } else { APR_RING_INSERT_TAIL(&(pollset->p->add_ring), elem, pfd_elem_t, link); } pollset_unlock_rings(); return rv; }
/* * schedule a task to run in "time" microseconds. Find the spot in the ring where * the time fits. Adjust the short_time so the thread wakes up when the time is reached. */ static apr_status_t schedule_task(apr_thread_pool_t *me, apr_thread_start_t func, void *param, void *owner, apr_interval_time_t time) { apr_thread_pool_task_t *t; apr_thread_pool_task_t *t_loc; apr_thread_t *thd; apr_status_t rv = APR_SUCCESS; apr_thread_mutex_lock(me->lock); t = task_new(me, func, param, 0, owner, time); if (NULL == t) { apr_thread_mutex_unlock(me->lock); return APR_ENOMEM; } t_loc = APR_RING_FIRST(me->scheduled_tasks); while (NULL != t_loc) { /* if the time is less than the entry insert ahead of it */ if (t->dispatch.time < t_loc->dispatch.time) { ++me->scheduled_task_cnt; APR_RING_INSERT_BEFORE(t_loc, t, link); break; } else { t_loc = APR_RING_NEXT(t_loc, link); if (t_loc == APR_RING_SENTINEL(me->scheduled_tasks, apr_thread_pool_task, link)) { ++me->scheduled_task_cnt; APR_RING_INSERT_TAIL(me->scheduled_tasks, t, apr_thread_pool_task, link); break; } } } /* there should be at least one thread for scheduled tasks */ if (0 == me->thd_cnt) { rv = apr_thread_create(&thd, NULL, thread_pool_func, me, me->pool); if (APR_SUCCESS == rv) { ++me->thd_cnt; if (me->thd_cnt > me->thd_high) me->thd_high = me->thd_cnt; } } apr_thread_mutex_unlock(me->lock); apr_thread_mutex_lock(me->cond_lock); apr_thread_cond_signal(me->cond); apr_thread_mutex_unlock(me->cond_lock); return rv; }
/* Cleanup function. */ static apr_status_t kdfilter_delete(void *data) { kdfilter *self = (kdfilter *)data; struct filter_driver *drv; /* Call the close method of each filters. */ for (drv = APR_RING_FIRST(&self->filter_drv_list); drv != APR_RING_SENTINEL(&self->filter_drv_list, filter_driver, link); drv = APR_RING_NEXT(drv, link)) { DEBUG(_log_filter_, "Unregistering filter: %s.", drv->filter_name); (drv->p_close)(self, drv->private_data); } return APR_SUCCESS; }
/* * This function stop extra idle threads to the cnt. * @return the number of threads stopped * NOTE: There could be busy threads become idle during this function */ static struct apr_thread_list_elt *trim_threads(apr_thread_pool_t *me, apr_size_t *cnt, int idle) { struct apr_thread_list *thds; apr_size_t n, n_dbg, i; struct apr_thread_list_elt *head, *tail, *elt; apr_thread_mutex_lock(me->lock); if (idle) { thds = me->idle_thds; n = me->idle_cnt; } else { thds = me->busy_thds; n = me->thd_cnt - me->idle_cnt; } if (n <= *cnt) { apr_thread_mutex_unlock(me->lock); *cnt = 0; return NULL; } n -= *cnt; head = APR_RING_FIRST(thds); for (i = 0; i < *cnt; i++) { head = APR_RING_NEXT(head, link); } tail = APR_RING_LAST(thds); if (idle) { APR_RING_UNSPLICE(head, tail, link); me->idle_cnt = *cnt; } n_dbg = 0; for (elt = head; elt != tail; elt = APR_RING_NEXT(elt, link)) { elt->state = TH_STOP; n_dbg++; } elt->state = TH_STOP; n_dbg++; assert(n == n_dbg); *cnt = n; apr_thread_mutex_unlock(me->lock); APR_RING_PREV(head, link) = NULL; APR_RING_NEXT(tail, link) = NULL; return head; }
APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) { struct waiter_t *wake; acquire_sem(cond->lock); while (! APR_RING_EMPTY(&cond->alist, waiter_t, link)) { wake = APR_RING_FIRST(&cond->alist); APR_RING_REMOVE(wake, link); release_sem(wake->sem); APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link); } release_sem(cond->lock); return APR_SUCCESS; }
/** Parse MRCP channel-identifier */ MRCP_DECLARE(apt_bool_t) mrcp_channel_id_parse(mrcp_channel_id *channel_id, mrcp_message_header_t *header, apr_pool_t *pool) { apt_header_field_t *header_field; for(header_field = APR_RING_FIRST(&header->header_section.ring); header_field != APR_RING_SENTINEL(&header->header_section.ring, apt_header_field_t, link); header_field = APR_RING_NEXT(header_field, link)) { if(header_field->value.length && strncasecmp(header_field->name.buf,MRCP_CHANNEL_ID,MRCP_CHANNEL_ID_LENGTH) == 0) { apt_id_resource_parse(&header_field->value,'@',&channel_id->session_id,&channel_id->resource_name,pool); apt_header_section_field_remove(&header->header_section,header_field); return TRUE; } } return FALSE; }