| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 | 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);}
 |