Example #1
0
static void
cv_test_thr_fn_(void *arg)
{
  cv_testinfo_t *i = arg;
  int tid, r;

  tor_mutex_acquire(i->mutex);
  tid = i->n_threads++;
  tor_mutex_release(i->mutex);
  (void) tid;

  tor_mutex_acquire(i->mutex);
  while (1) {
    if (i->addend) {
      i->value += i->addend;
      i->addend = 0;
    }

    if (i->shutdown) {
      ++i->n_shutdown;
      i->shutdown = 0;
      tor_mutex_release(i->mutex);
      spawn_exit();
    }
    r = tor_cond_wait(i->cond, i->mutex, i->tv);
    ++i->n_wakeups;
    if (r == 1) {
      ++i->n_timeouts;
      tor_mutex_release(i->mutex);
      spawn_exit();
    }
  }
}
/**
 * Main function for the worker thread.
 */
static void
worker_thread_main(void *thread_)
{
  workerthread_t *thread = thread_;
  threadpool_t *pool = thread->in_pool;
  workqueue_entry_t *work;
  workqueue_reply_t result;

  tor_mutex_acquire(&pool->lock);
  while (1) {
    /* lock must be held at this point. */
    while (worker_thread_has_work(thread)) {
      /* lock must be held at this point. */
      if (thread->in_pool->generation != thread->generation) {
        void *arg = thread->in_pool->update_args[thread->index];
        thread->in_pool->update_args[thread->index] = NULL;
        workqueue_reply_t (*update_fn)(void*,void*) =
            thread->in_pool->update_fn;
        thread->generation = thread->in_pool->generation;
        tor_mutex_release(&pool->lock);

        workqueue_reply_t r = update_fn(thread->state, arg);

        if (r != WQ_RPL_REPLY) {
          return;
        }

        tor_mutex_acquire(&pool->lock);
        continue;
      }
      work = TOR_TAILQ_FIRST(&pool->work);
      TOR_TAILQ_REMOVE(&pool->work, work, next_work);
      work->pending = 0;
      tor_mutex_release(&pool->lock);

      /* We run the work function without holding the thread lock. This
       * is the main thread's first opportunity to give us more work. */
      result = work->fn(thread->state, work->arg);

      /* Queue the reply for the main thread. */
      queue_reply(thread->reply_queue, work);

      /* We may need to exit the thread. */
      if (result != WQ_RPL_REPLY) {
        return;
      }
      tor_mutex_acquire(&pool->lock);
    }
    /* At this point the lock is held, and there is no work in this thread's
     * queue. */

    /* TODO: support an idle-function */

    /* Okay. Now, wait till somebody has work for us. */
    if (tor_cond_wait(&pool->condition, &pool->lock, NULL) < 0) {
      log_warn(LD_GENERAL, "Fail tor_cond_wait.");
    }
  }
}