diff options
author | Austin Foxley <austinf@cetoncorp.com> | 2010-02-16 12:27:18 -0800 |
---|---|---|
committer | Austin Foxley <austinf@cetoncorp.com> | 2010-02-16 12:27:18 -0800 |
commit | a032a6587011cbdac8c2f7e11f15dc4e592bbb55 (patch) | |
tree | b8d8dfc6abf0168e098223c2134a3e4bd7640942 /libpthread/nptl/DESIGN-condvar.txt | |
parent | 70f1d42b13a741f603472f405299e5d2938aa728 (diff) |
mass sync with glibc nptl
Signed-off-by: Austin Foxley <austinf@cetoncorp.com>
Diffstat (limited to 'libpthread/nptl/DESIGN-condvar.txt')
-rw-r--r-- | libpthread/nptl/DESIGN-condvar.txt | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/libpthread/nptl/DESIGN-condvar.txt b/libpthread/nptl/DESIGN-condvar.txt new file mode 100644 index 000000000..4845251c7 --- /dev/null +++ b/libpthread/nptl/DESIGN-condvar.txt @@ -0,0 +1,134 @@ +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); +} |