Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
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);
}