Ejemplo n.º 1
0
/*!
 * \brief Change the size of the threadpool
 *
 * This can either result in shrinking or growing the threadpool depending
 * on the new desired size and the current size.
 *
 * This function is run from the threadpool control taskprocessor thread
 *
 * \param data A set_size_data used for determining how to act
 * \return 0
 */
static int queued_set_size(void *data)
{
	RAII_VAR(struct set_size_data *, ssd, data, ao2_cleanup);
	struct ast_threadpool *pool = ssd->pool;
	unsigned int num_threads = ssd->size;

	/* We don't count zombie threads as being "live" when potentially resizing */
	unsigned int current_size = ao2_container_count(pool->active_threads) +
			ao2_container_count(pool->idle_threads);

	if (current_size == num_threads) {
		ast_debug(3, "Not changing threadpool size since new size %u is the same as current %u\n",
			  num_threads, current_size);
		return 0;
	}

	if (current_size < num_threads) {
		ao2_callback(pool->idle_threads, OBJ_UNLINK | OBJ_NOLOCK | OBJ_NODATA | OBJ_MULTIPLE,
				activate_thread, pool);

		/* As the above may have altered the number of current threads update it */
		current_size = ao2_container_count(pool->active_threads) +
				ao2_container_count(pool->idle_threads);
		grow(pool, num_threads - current_size);
		ao2_callback(pool->idle_threads, OBJ_UNLINK | OBJ_NOLOCK | OBJ_NODATA | OBJ_MULTIPLE,
				activate_thread, pool);
	} else {
		shrink(pool, current_size - num_threads);
	}

	threadpool_send_state_changed(pool);
	return 0;
}
Ejemplo n.º 2
0
static int queued_idle_thread_dead(void *data)
{
	struct thread_worker_pair *pair = data;

	ao2_unlink(pair->pool->idle_threads, pair->worker);
	threadpool_send_state_changed(pair->pool);

	ao2_ref(pair, -1);
	return 0;
}
Ejemplo n.º 3
0
/*!
 * \brief Queued task called when tasks are pushed into the threadpool
 *
 * This function first calls into the threadpool's listener to let it know
 * that a task has been pushed. It then wakes up all idle threads and moves
 * them into the active thread container.
 * \param data A task_pushed_data
 * \return 0
 */
static int queued_task_pushed(void *data)
{
	struct task_pushed_data *tpd = data;
	struct ast_threadpool *pool = tpd->pool;
	int was_empty = tpd->was_empty;

	if (pool->listener && pool->listener->callbacks->task_pushed) {
		pool->listener->callbacks->task_pushed(pool, pool->listener, was_empty);
	}
	if (ao2_container_count(pool->idle_threads) == 0) {
		if (!pool->options.auto_increment) {
			return 0;
		}
		grow(pool, pool->options.auto_increment);
	}

	ao2_callback(pool->idle_threads, OBJ_UNLINK | OBJ_NOLOCK | OBJ_NODATA,
			activate_thread, pool);

	threadpool_send_state_changed(pool);
	ao2_ref(tpd, -1);
	return 0;
}
Ejemplo n.º 4
0
/*!
 * \brief Queued task called when tasks are pushed into the threadpool
 *
 * This function first calls into the threadpool's listener to let it know
 * that a task has been pushed. It then wakes up all idle threads and moves
 * them into the active thread container.
 * \param data A task_pushed_data
 * \return 0
 */
static int queued_task_pushed(void *data)
{
	struct task_pushed_data *tpd = data;
	struct ast_threadpool *pool = tpd->pool;
	int was_empty = tpd->was_empty;
	unsigned int existing_active;

	if (pool->listener && pool->listener->callbacks->task_pushed) {
		pool->listener->callbacks->task_pushed(pool, pool->listener, was_empty);
	}

	existing_active = ao2_container_count(pool->active_threads);

	/* The first pass transitions any existing idle threads to be active, and
	 * will also remove any worker threads that have recently entered the dead
	 * state.
	 */
	ao2_callback(pool->idle_threads, OBJ_UNLINK | OBJ_NOLOCK | OBJ_NODATA,
			activate_thread, pool);

	/* If no idle threads could be transitioned to active grow the pool as permitted. */
	if (ao2_container_count(pool->active_threads) == existing_active) {
		if (!pool->options.auto_increment) {
			ao2_ref(tpd, -1);
			return 0;
		}
		grow(pool, pool->options.auto_increment);
		/* An optional second pass transitions any newly added threads. */
		ao2_callback(pool->idle_threads, OBJ_UNLINK | OBJ_NOLOCK | OBJ_NODATA,
				activate_thread, pool);
	}

	threadpool_send_state_changed(pool);
	ao2_ref(tpd, -1);
	return 0;
}