iconv: Suppress array out of bounds warning.
[platform/upstream/glibc.git] / nptl / DESIGN-condvar.txt
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 cond_lock;
11
12          internal mutex
13
14    uint64_t total_seq;
15
16      Total number of threads using the conditional variable.
17
18    uint64_t wakeup_seq;
19
20      sequence number for next wakeup.
21
22    uint64_t woken_seq;
23
24      sequence number of last woken thread.
25
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
37 }
38
39
40
41 cleanup_handler(cv_data)
42 {
43   cv = cv_data->cv;
44   lll_lock(cv->lock);
45
46   if (cv_data->bc_seq == cv->broadcast_seq) {
47     ++cv->wakeup_seq;
48     ++cv->woken_seq;
49   }
50
51   /* make sure no signal gets lost.  */
52   FUTEX_WAKE(cv->wakeup_seq, ALL);
53
54   lll_unlock(cv->lock);
55 }
56
57
58 cond_timedwait(cv, mutex, timeout):
59 {
60    lll_lock(cv->lock);
61    mutex_unlock(mutex);
62
63    cleanup_push
64
65    ++cv->total_seq;
66    val = seq =  cv->wakeup_seq;
67    cv_data.bc = cv->broadcast_seq;
68    cv_data.cv = cv;
69
70    while (1) {
71
72      lll_unlock(cv->lock);
73
74      enable_async(&cv_data);
75
76      ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
77
78      restore_async
79
80      lll_lock(cv->lock);
81
82      if (bc != cv->broadcast_seq)
83        goto bc_out;
84
85      val = cv->wakeup_seq;
86
87      if (val != seq && cv->woken_seq != val) {
88        ret = 0;
89        break;
90      }
91
92      if (ret == TIMEDOUT) {
93        ++cv->wakeup_seq;
94        break;
95      }
96    }
97
98    ++cv->woken_seq;
99
100  bc_out:
101    lll_unlock(cv->lock);
102
103    cleanup_pop
104
105    mutex_lock(mutex);
106
107    return ret;
108 }
109
110 cond_signal(cv)
111 {
112    lll_lock(cv->lock);
113
114    if (cv->total_seq > cv->wakeup_seq) {
115      ++cv->wakeup_seq;
116      FUTEX_WAKE(cv->wakeup_seq, 1);
117    }
118
119    lll_unlock(cv->lock);
120 }
121
122 cond_broadcast(cv)
123 {
124    lll_lock(cv->lock);
125
126    if (cv->total_seq > cv->wakeup_seq) {
127      cv->wakeup_seq = cv->total_seq;
128      cv->woken_seq = cv->total_seq;
129      ++cv->broadcast_seq;
130      FUTEX_WAKE(cv->wakeup_seq, ALL);
131    }
132
133    lll_unlock(cv->lock);
134 }