Example #1
0
/* Lock MUTEX for thread LOCKER, setting its lock count to COUNT, if
   non-zero, or to 1 otherwise.

   If MUTEX is locked by LOCKER, COUNT must be zero, and the MUTEX's
   lock count will be incremented.

   If MUTEX is locked by another thread, this function will release
   the global lock, giving other threads a chance to run, and will
   wait for the MUTEX to become unlocked; when MUTEX becomes unlocked,
   and will then re-acquire the global lock.

   Return value is 1 if the function waited for the MUTEX to become
   unlocked (meaning other threads could have run during the wait),
   zero otherwise.  */
static int
lisp_mutex_lock_for_thread (lisp_mutex_t *mutex, struct thread_state *locker,
			    int new_count)
{
  struct thread_state *self;

  if (mutex->owner == NULL)
    {
      mutex->owner = locker;
      mutex->count = new_count == 0 ? 1 : new_count;
      return 0;
    }
  if (mutex->owner == locker)
    {
      eassert (new_count == 0);
      ++mutex->count;
      return 0;
    }

  self = locker;
  self->wait_condvar = &mutex->condition;
  while (mutex->owner != NULL && (new_count != 0
				  || NILP (self->error_symbol)))
    sys_cond_wait (&mutex->condition, &global_lock);
  self->wait_condvar = NULL;

  if (new_count == 0 && !NILP (self->error_symbol))
    return 1;

  mutex->owner = self;
  mutex->count = new_count == 0 ? 1 : new_count;

  return 1;
}
void *router_core_thread(void *arg)
{
    qdr_core_t        *core = (qdr_core_t*) arg;
    qdr_action_list_t  action_list;
    qdr_action_t      *action;

    qdr_forwarder_setup_CT(core);
    qdr_route_table_setup_CT(core);
    qdr_agent_setup_CT(core);

    qd_log(core->log, QD_LOG_INFO, "Router Core thread running. %s/%s", core->router_area, core->router_id);
    while (core->running) {
        //
        // Use the lock only to protect the condition variable and the action list
        //
        sys_mutex_lock(core->action_lock);

        //
        // Block on the condition variable when there is no action to do
        //
        while (core->running && DEQ_IS_EMPTY(core->action_list))
            sys_cond_wait(core->action_cond, core->action_lock);

        //
        // Move the entire action list to a private list so we can process it without
        // holding the lock
        //
        DEQ_MOVE(core->action_list, action_list);
        sys_mutex_unlock(core->action_lock);

        //
        // Process and free all of the action items in the list
        //
        action = DEQ_HEAD(action_list);
        while (action) {
            DEQ_REMOVE_HEAD(action_list);
            if (action->label)
                qd_log(core->log, QD_LOG_TRACE, "Core action '%s'%s", action->label, core->running ? "" : " (discard)");
            action->action_handler(core, action, !core->running);
            free_qdr_action_t(action);
            action = DEQ_HEAD(action_list);
        }
    }

    qd_log(core->log, QD_LOG_INFO, "Router Core thread exited");
    return 0;
}