glibc/nptl/DESIGN-condvar.txt
Ulrich Drepper 5778033ffc Update.
* localedata/en_ZA: Changed %x for LC_TIME to use dd/mm/ccyy.
2003-03-17 10:16:36 +00:00

113 lines
1.7 KiB
Plaintext

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.
}
cleanup_handler(cv)
{
lll_lock(cv->lock);
++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;
while (1) {
lll_unlock(cv->lock);
enable_async
ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
restore_async
lll_lock(cv->lock);
val = cv->wakeup_seq;
if (val > seq && cv->woken_seq < val) {
ret = 0;
break;
}
if (ret == TIMEDOUT) {
++cv->wakeup_seq;
break;
}
}
++cv->woken_seq;
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;
FUTEX_WAKE(cv->wakeup_seq, ALL);
}
lll_unlock(cv->lock);
}