]>
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 | ||
10 | unsigned int lock: | |
11 | ||
12 | internal mutex | |
13 | ||
14 | unsigned int nr_wakers: | |
15 | ||
16 | number of threads signalled to be woken up. | |
17 | ||
18 | unsigned int nr_sleepers: | |
19 | ||
20 | number of threads waiting for the cv. | |
21 | ||
22 | } | |
23 | ||
24 | #define ALL_THREADS (1 << (BITS_PER_LONG-1)) | |
25 | ||
26 | cond_wait_timeout(cv, mutex, timeout): | |
27 | { | |
28 | lll_lock(cv->lock); | |
29 | mutex_unlock(mutex); | |
30 | ||
31 | cv->nr_sleepers++; | |
32 | for (;;) { | |
33 | ||
34 | if (cv->nr_wakers) { | |
35 | cv->nr_wakers--; | |
36 | break; | |
37 | } | |
38 | val = cv->nr_wakers; | |
39 | ||
40 | lll_unlock(cv->lock); | |
41 | ||
42 | ret = FUTEX WAIT (cv->nr_wakers, val, timeout) | |
43 | ||
44 | lll_lock(cv->lock); | |
45 | ||
46 | if (ret == TIMEOUT) | |
47 | break; | |
48 | ret = 0; | |
49 | } | |
50 | if (!--cv->nr_sleepers) | |
51 | cv->nr_wakers = 0; /* no memory of wakeups */ | |
52 | lll_unlock(cv->lock); | |
53 | mutex_lock(mutex); | |
54 | ||
55 | return ret; | |
56 | } | |
57 | ||
58 | cond_signal(cv) | |
59 | { | |
60 | int do_wakeup = 0; | |
61 | ||
62 | lll_lock(cv->lock); | |
63 | if (cv->nr_sleepers) { | |
64 | if (!++cv->nr_wakers) /* overflow detection for the nutcase */ | |
65 | cv->nr_wakers = ALL_THREADS; | |
66 | do_wakeup = 1; | |
67 | } | |
68 | lll_unlock(cv->lock); | |
69 | if (do_wakeup) | |
70 | FUTEX WAKE (cv->nr_wakers, 1) | |
71 | } | |
72 | ||
73 | cond_broadcast(cv) | |
74 | { | |
75 | int do_wakeup = 0; | |
76 | ||
77 | lll_lock(cv->lock); | |
78 | if (cv->nr_sleepers) { | |
79 | cv->nr_wakers |= ALL_THREADS; | |
80 | do_wakeup = 1; | |
81 | } | |
82 | lll_unlock(cv->lock); | |
83 | if (do_wakeup) | |
84 | FUTEX WAKE (cv->nr_wakers, ALL_THREADS); | |
85 | } | |
86 | ||
87 | weaknesses of the implementation: | |
88 | ||
89 | it might generate spurious wakeups in the broadcast case, but those are | |
90 | allowed by POSIX. |