]>
Commit | Line | Data |
---|---|---|
76a50749 UD |
1 | Conditional 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 | ||
8 | struct 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 | ||
31 | struct cv_data { | |
32 | ||
33 | pthread_cond_t *cv; | |
34 | ||
35 | uint32_t bc_seq | |
36 | ||
76a50749 UD |
37 | } |
38 | ||
76a50749 | 39 | |
05df18c3 | 40 | |
893a3511 | 41 | cleanup_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 | ||
58 | cond_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 | ||
110 | cond_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 | ||
122 | cond_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 | } |