/*! * \brief Activate idle threads * * This function always returns CMP_MATCH because all workers that this * function acts on need to be seen as matches so they are unlinked from the * list of idle threads. * * Called as an ao2_callback in the threadpool's control taskprocessor thread. * \param obj The worker to activate * \param arg The pool where the worker belongs * \retval CMP_MATCH */ static int activate_thread(void *obj, void *arg, int flags) { struct worker_thread *worker = obj; struct ast_threadpool *pool = arg; if (!ao2_link(pool->active_threads, worker)) { /* If we can't link the idle thread into the active container, then * we'll just leave the thread idle and not wake it up. */ ast_log(LOG_WARNING, "Failed to activate thread %d. Remaining idle\n", worker->id); return 0; } if (worker_set_state(worker, ALIVE)) { ast_debug(1, "Failed to activate thread %d. It is dead\n", worker->id); /* The worker thread will no longer exist in the active threads or * idle threads container after this. */ ao2_unlink(pool->active_threads, worker); } return CMP_MATCH; }
/*! * \brief shut a worker thread down * * Set the worker dead and then wait for its thread * to finish executing. * * \param worker The worker thread to shut down */ static void worker_shutdown(struct worker_thread *worker) { worker_set_state(worker, DEAD); if (worker->thread != AST_PTHREADT_NULL) { pthread_join(worker->thread, NULL); worker->thread = AST_PTHREADT_NULL; } }
/*! * \brief Activate idle threads * * This function always returns CMP_MATCH because all workers that this * function acts on need to be seen as matches so they are unlinked from the * list of idle threads. * * Called as an ao2_callback in the threadpool's control taskprocessor thread. * \param obj The worker to activate * \param arg The pool where the worker belongs * \retval CMP_MATCH */ static int activate_thread(void *obj, void *arg, int flags) { struct worker_thread *worker = obj; struct ast_threadpool *pool = arg; if (!ao2_link(pool->active_threads, worker)) { /* If we can't link the idle thread into the active container, then * we'll just leave the thread idle and not wake it up. */ ast_log(LOG_WARNING, "Failed to activate thread %d. Remaining idle\n", worker->id); return 0; } worker_set_state(worker, ALIVE); return CMP_MATCH; }
/*! * \brief ao2 callback to zombify a set number of threads. * * Threads will be zombified as long as as the counter has not reached * zero. The counter is decremented with each thread that is zombified. * * Zombifying a thread involves removing it from its current container, * adding it to the zombie container, and changing the state of the * worker to a zombie * * This callback is called from the threadpool control taskprocessor thread. * * \param obj The worker thread that may be zombified * \param arg The pool to which the worker belongs * \param data The counter * \param flags Unused * \retval CMP_MATCH The zombified thread should be removed from its current container * \retval CMP_STOP Stop attempting to zombify threads */ static int zombify_threads(void *obj, void *arg, void *data, int flags) { struct worker_thread *worker = obj; struct ast_threadpool *pool = arg; int *num_to_zombify = data; if ((*num_to_zombify)-- > 0) { if (!ao2_link(pool->zombie_threads, worker)) { ast_log(LOG_WARNING, "Failed to zombify active thread %d. Thread will remain active\n", worker->id); return 0; } worker_set_state(worker, ZOMBIE); return CMP_MATCH; } else { return CMP_STOP; } }