Conditional Variable pseudocode. ================================ int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex); int pthread_cond_signal (pthread_cond_t *cv); int pthread_cond_broadcast (pthread_cond_t *cv); struct pthread_cond_t { unsigned int cond_lock; internal mutex uint64_t total_seq; Total number of threads using the conditional variable. uint64_t wakeup_seq; sequence number for next wakeup. uint64_t woken_seq; sequence number of last woken thread. uint32_t broadcast_seq; } struct cv_data { pthread_cond_t *cv; uint32_t bc_seq } cleanup_handler(cv_data) { cv = cv_data->cv; lll_lock(cv->lock); if (cv_data->bc_seq == cv->broadcast_seq) { ++cv->wakeup_seq; ++cv->woken_seq; } /* make sure no signal gets lost. */ FUTEX_WAKE(cv->wakeup_seq, ALL); lll_unlock(cv->lock); } cond_timedwait(cv, mutex, timeout): { lll_lock(cv->lock); mutex_unlock(mutex); cleanup_push ++cv->total_seq; val = seq = cv->wakeup_seq; cv_data.bc = cv->broadcast_seq; cv_data.cv = cv; while (1) { lll_unlock(cv->lock); enable_async(&cv_data); ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); restore_async lll_lock(cv->lock); if (bc != cv->broadcast_seq) goto bc_out; val = cv->wakeup_seq; if (val != seq && cv->woken_seq != val) { ret = 0; break; } if (ret == TIMEDOUT) { ++cv->wakeup_seq; break; } } ++cv->woken_seq; bc_out: lll_unlock(cv->lock); cleanup_pop mutex_lock(mutex); return ret; } cond_signal(cv) { lll_lock(cv->lock); if (cv->total_seq > cv->wakeup_seq) { ++cv->wakeup_seq; FUTEX_WAKE(cv->wakeup_seq, 1); } lll_unlock(cv->lock); } cond_broadcast(cv) { lll_lock(cv->lock); if (cv->total_seq > cv->wakeup_seq) { cv->wakeup_seq = cv->total_seq; cv->woken_seq = cv->total_seq; ++cv->broadcast_seq; FUTEX_WAKE(cv->wakeup_seq, ALL); } lll_unlock(cv->lock); }