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. } cleanup_handler(cv) { lll_lock(cv->lock); ++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; while (1) { lll_unlock(cv->lock); enable_async ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); restore_async lll_lock(cv->lock); val = cv->wakeup_seq; if (val != seq && cv->woken_seq != val) { ret = 0; break; } if (ret == TIMEDOUT) { ++cv->wakeup_seq; break; } } ++cv->woken_seq; 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; FUTEX_WAKE(cv->wakeup_seq, ALL); } lll_unlock(cv->lock); }