diff options
Diffstat (limited to 'nptl/DESIGN-condvar.txt')
-rw-r--r-- | nptl/DESIGN-condvar.txt | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/nptl/DESIGN-condvar.txt b/nptl/DESIGN-condvar.txt index cb0f59c823..4845251c75 100644 --- a/nptl/DESIGN-condvar.txt +++ b/nptl/DESIGN-condvar.txt @@ -23,16 +23,30 @@ struct pthread_cond_t { sequence number of last woken thread. + uint32_t broadcast_seq; + +} + + +struct cv_data { + + pthread_cond_t *cv; + + uint32_t bc_seq + } -cleanup_handler(cv) +cleanup_handler(cv_data) { + cv = cv_data->cv; lll_lock(cv->lock); - ++cv->wakeup_seq; - ++cv->woken_seq; + 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); @@ -50,12 +64,14 @@ cond_timedwait(cv, mutex, timeout): ++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 + enable_async(&cv_data); ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); @@ -63,6 +79,9 @@ cond_timedwait(cv, mutex, timeout): lll_lock(cv->lock); + if (bc != cv->broadcast_seq) + goto bc_out; + val = cv->wakeup_seq; if (val != seq && cv->woken_seq != val) { @@ -78,6 +97,7 @@ cond_timedwait(cv, mutex, timeout): ++cv->woken_seq; + bc_out: lll_unlock(cv->lock); cleanup_pop @@ -105,6 +125,8 @@ cond_broadcast(cv) 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); } |