]> sourceware.org Git - glibc.git/blame - nptl/DESIGN-condvar.txt
Add minimal test suite changes for elision enabled kernels
[glibc.git] / nptl / DESIGN-condvar.txt
CommitLineData
76a50749
UD
1Conditional Variable pseudocode.
2================================
3
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);
7
8struct pthread_cond_t {
9
05df18c3 10 unsigned int cond_lock;
76a50749
UD
11
12 internal mutex
13
05df18c3 14 uint64_t total_seq;
76a50749 15
05df18c3 16 Total number of threads using the conditional variable.
76a50749 17
05df18c3 18 uint64_t wakeup_seq;
76a50749 19
05df18c3
UD
20 sequence number for next wakeup.
21
22 uint64_t woken_seq;
23
24 sequence number of last woken thread.
76a50749 25
893a3511
UD
26 uint32_t broadcast_seq;
27
28}
29
30
31struct cv_data {
32
33 pthread_cond_t *cv;
34
35 uint32_t bc_seq
36
76a50749
UD
37}
38
76a50749 39
05df18c3 40
893a3511 41cleanup_handler(cv_data)
05df18c3 42{
893a3511 43 cv = cv_data->cv;
05df18c3
UD
44 lll_lock(cv->lock);
45
893a3511
UD
46 if (cv_data->bc_seq == cv->broadcast_seq) {
47 ++cv->wakeup_seq;
48 ++cv->woken_seq;
49 }
05df18c3 50
3e976b96
UD
51 /* make sure no signal gets lost. */
52 FUTEX_WAKE(cv->wakeup_seq, ALL);
53
05df18c3
UD
54 lll_unlock(cv->lock);
55}
56
57
58cond_timedwait(cv, mutex, timeout):
76a50749
UD
59{
60 lll_lock(cv->lock);
61 mutex_unlock(mutex);
62
05df18c3
UD
63 cleanup_push
64
65 ++cv->total_seq;
66 val = seq = cv->wakeup_seq;
893a3511
UD
67 cv_data.bc = cv->broadcast_seq;
68 cv_data.cv = cv;
05df18c3
UD
69
70 while (1) {
71
72 lll_unlock(cv->lock);
73
893a3511 74 enable_async(&cv_data);
76a50749 75
05df18c3 76 ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
76a50749 77
05df18c3 78 restore_async
76a50749 79
05df18c3 80 lll_lock(cv->lock);
76a50749 81
893a3511
UD
82 if (bc != cv->broadcast_seq)
83 goto bc_out;
84
05df18c3 85 val = cv->wakeup_seq;
76a50749 86
cff08c81 87 if (val != seq && cv->woken_seq != val) {
76a50749 88 ret = 0;
05df18c3
UD
89 break;
90 }
91
92 if (ret == TIMEDOUT) {
93 ++cv->wakeup_seq;
94 break;
95 }
76a50749 96 }
05df18c3
UD
97
98 ++cv->woken_seq;
99
893a3511 100 bc_out:
76a50749 101 lll_unlock(cv->lock);
05df18c3
UD
102
103 cleanup_pop
104
76a50749
UD
105 mutex_lock(mutex);
106
107 return ret;
108}
109
110cond_signal(cv)
111{
76a50749 112 lll_lock(cv->lock);
05df18c3
UD
113
114 if (cv->total_seq > cv->wakeup_seq) {
115 ++cv->wakeup_seq;
116 FUTEX_WAKE(cv->wakeup_seq, 1);
76a50749 117 }
05df18c3 118
76a50749 119 lll_unlock(cv->lock);
76a50749
UD
120}
121
122cond_broadcast(cv)
123{
76a50749 124 lll_lock(cv->lock);
05df18c3
UD
125
126 if (cv->total_seq > cv->wakeup_seq) {
127 cv->wakeup_seq = cv->total_seq;
893a3511
UD
128 cv->woken_seq = cv->total_seq;
129 ++cv->broadcast_seq;
05df18c3 130 FUTEX_WAKE(cv->wakeup_seq, ALL);
76a50749 131 }
05df18c3 132
76a50749 133 lll_unlock(cv->lock);
76a50749 134}
This page took 0.316969 seconds and 5 git commands to generate.