/* 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; }