1Conditional Variable pseudocode. 2================================ 3 4 int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex); 5 int pthread_cond_signal (pthread_cond_t *cv); 6 int pthread_cond_broadcast (pthread_cond_t *cv); 7 8struct pthread_cond_t { 9 10 unsigned int cond_lock; 11 12 internal mutex 13 14 uint64_t total_seq; 15 16 Total number of threads using the conditional variable. 17 18 uint64_t wakeup_seq; 19 20 sequence number for next wakeup. 21 22 uint64_t woken_seq; 23 24 sequence number of last woken thread. 25 26 uint32_t broadcast_seq; 27 28} 29 30 31struct cv_data { 32 33 pthread_cond_t *cv; 34 35 uint32_t bc_seq 36 37} 38 39 40 41cleanup_handler(cv_data) 42{ 43 cv = cv_data->cv; 44 lll_lock(cv->lock); 45 46 if (cv_data->bc_seq == cv->broadcast_seq) { 47 ++cv->wakeup_seq; 48 ++cv->woken_seq; 49 } 50 51 /* make sure no signal gets lost. */ 52 FUTEX_WAKE(cv->wakeup_seq, ALL); 53 54 lll_unlock(cv->lock); 55} 56 57 58cond_timedwait(cv, mutex, timeout): 59{ 60 lll_lock(cv->lock); 61 mutex_unlock(mutex); 62 63 cleanup_push 64 65 ++cv->total_seq; 66 val = seq = cv->wakeup_seq; 67 cv_data.bc = cv->broadcast_seq; 68 cv_data.cv = cv; 69 70 while (1) { 71 72 lll_unlock(cv->lock); 73 74 enable_async(&cv_data); 75 76 ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); 77 78 restore_async 79 80 lll_lock(cv->lock); 81 82 if (bc != cv->broadcast_seq) 83 goto bc_out; 84 85 val = cv->wakeup_seq; 86 87 if (val != seq && cv->woken_seq != val) { 88 ret = 0; 89 break; 90 } 91 92 if (ret == TIMEDOUT) { 93 ++cv->wakeup_seq; 94 break; 95 } 96 } 97 98 ++cv->woken_seq; 99 100 bc_out: 101 lll_unlock(cv->lock); 102 103 cleanup_pop 104 105 mutex_lock(mutex); 106 107 return ret; 108} 109 110cond_signal(cv) 111{ 112 lll_lock(cv->lock); 113 114 if (cv->total_seq > cv->wakeup_seq) { 115 ++cv->wakeup_seq; 116 FUTEX_WAKE(cv->wakeup_seq, 1); 117 } 118 119 lll_unlock(cv->lock); 120} 121 122cond_broadcast(cv) 123{ 124 lll_lock(cv->lock); 125 126 if (cv->total_seq > cv->wakeup_seq) { 127 cv->wakeup_seq = cv->total_seq; 128 cv->woken_seq = cv->total_seq; 129 ++cv->broadcast_seq; 130 FUTEX_WAKE(cv->wakeup_seq, ALL); 131 } 132 133 lll_unlock(cv->lock); 134} 135