/*! * \brief Idle function for worker threads * * The worker waits here until it gets told by the threadpool * to wake up. * * worker is locked before entering this function. * * \param worker The idle worker * \retval 0 The thread is being woken up so that it can conclude. * \retval non-zero The thread is being woken up to do more work. */ static int worker_idle(struct worker_thread *worker) { struct timeval start = ast_tvnow(); struct timespec end = { .tv_sec = start.tv_sec + worker->options.idle_timeout, .tv_nsec = start.tv_usec * 1000, }; while (!worker->wake_up) { if (worker->options.idle_timeout <= 0) { ast_cond_wait(&worker->cond, &worker->lock); } else if (ast_cond_timedwait(&worker->cond, &worker->lock, &end) == ETIMEDOUT) { break; } } if (!worker->wake_up) { ast_debug(1, "Worker thread idle timeout reached. Dying.\n"); threadpool_idle_thread_dead(worker->pool, worker); worker->state = DEAD; } worker->wake_up = 0; return worker->state == ALIVE; } /*! * \brief Change a worker's state * * The threadpool calls into this function in order to let a worker know * how it should proceed. * * \retval -1 failure (state transition not permitted) * \retval 0 success */ static int worker_set_state(struct worker_thread *worker, enum worker_state state) { SCOPED_MUTEX(lock, &worker->lock); switch (state) { case ALIVE: /* This can occur due to a race condition between being told to go active * and an idle timeout happening. */ if (worker->state == DEAD) { return -1; } ast_assert(worker->state != ZOMBIE); break; case DEAD: break; case ZOMBIE: ast_assert(worker->state != DEAD); break; } worker->state = state; worker->wake_up = 1; ast_cond_signal(&worker->cond); return 0; }
/*! * \brief Idle function for worker threads * * The worker waits here until it gets told by the threadpool * to wake up. * * worker is locked before entering this function. * * \param worker The idle worker * \retval 0 The thread is being woken up so that it can conclude. * \retval non-zero The thread is being woken up to do more work. */ static int worker_idle(struct worker_thread *worker) { struct timeval start = ast_tvnow(); struct timespec end = { .tv_sec = start.tv_sec + worker->options.idle_timeout, .tv_nsec = start.tv_usec * 1000, }; while (!worker->wake_up) { if (worker->options.idle_timeout <= 0) { ast_cond_wait(&worker->cond, &worker->lock); } else if (ast_cond_timedwait(&worker->cond, &worker->lock, &end) == ETIMEDOUT) { break; } } if (!worker->wake_up) { ast_debug(1, "Worker thread idle timeout reached. Dying.\n"); threadpool_idle_thread_dead(worker->pool, worker); worker->state = DEAD; } worker->wake_up = 0; return worker->state == ALIVE; } /*! * \brief Change a worker's state * * The threadpool calls into this function in order to let a worker know * how it should proceed. */ static void worker_set_state(struct worker_thread *worker, enum worker_state state) { SCOPED_MUTEX(lock, &worker->lock); worker->state = state; worker->wake_up = 1; ast_cond_signal(&worker->cond); }