
1: Conditional 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: 8: struct 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: 31: struct cv_data { 32: 33: pthread_cond_t *cv; 34: 35: uint32_t bc_seq 36: 37: } 38: 39: 40: 41: cleanup_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: 58: cond_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: 110: cond_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: 122: cond_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: }