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