Optimize for kernels which are known to have the vfork syscall.
[glibc/pb-stable.git] / nptl / DESIGN-condvar.txt
blob749180ed4b0df9186ef7b5190c183cfdda31fca7
1 Conditional Variable pseudocode.
2 ================================
4        int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex);
5        int pthread_cond_signal    (pthread_cond_t *cv);
6        int pthread_cond_broadcast (pthread_cond_t *cv);
8 struct pthread_cond_t {
10    unsigned int cond_lock;
12          internal mutex
14    uint64_t total_seq;
16      Total number of threads using the conditional variable.
18    uint64_t wakeup_seq;
20      sequence number for next wakeup.
22    uint64_t woken_seq;
24      sequence number of last woken thread.
30 cleanup_handler(cv)
32   lll_lock(cv->lock);
34   ++cv->wakeup_seq;
35   ++cv->woken_seq;
37   lll_unlock(cv->lock);
41 cond_timedwait(cv, mutex, timeout):
43    lll_lock(cv->lock);
44    mutex_unlock(mutex);
46    cleanup_push
48    ++cv->total_seq;
49    val = seq =  cv->wakeup_seq;
51    while (1) {
53      lll_unlock(cv->lock);
55      enable_async
57      ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
59      restore_async
61      lll_lock(cv->lock);
63      val = cv->wakeup_seq;
65      if (cv->woken_seq >= seq && cv->woken_seq < val) {
66        ret = 0;
67        break;
68      }
70      if (ret == TIMEDOUT) {
71        ++cv->wakeup_seq;
72        break;
73      }
74    }
76    ++cv->woken_seq;
78    lll_unlock(cv->lock);
80    cleanup_pop
82    mutex_lock(mutex);
84    return ret;
87 cond_signal(cv)
89    lll_lock(cv->lock);
91    if (cv->total_seq > cv->wakeup_seq) {
92      ++cv->wakeup_seq;
93      FUTEX_WAKE(cv->wakeup_seq, 1);
94    }
96    lll_unlock(cv->lock);
99 cond_broadcast(cv)
101    lll_lock(cv->lock);
103    if (cv->total_seq > cv->wakeup_seq) {
104      cv->wakeup_seq = cv->total_seq;
105      FUTEX_WAKE(cv->wakeup_seq, ALL);
106    }
108    lll_unlock(cv->lock);