From 0b3366f6a93ac0f7e2028745ea557c0acd8722c6 Mon Sep 17 00:00:00 2001 From: "\"Steven J. Hill\"" Date: Sat, 7 May 2005 02:04:55 +0000 Subject: Import in NPTL code from glibc. For further information please consult the 'README.NPTL' file. --- libpthread/nptl/DESIGN-condvar.txt | 134 +++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 libpthread/nptl/DESIGN-condvar.txt (limited to 'libpthread/nptl/DESIGN-condvar.txt') 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); +} -- cgit v1.2.3