7
* This file implements the "barrier" synchronization construct.
9
* A barrier causes threads to wait until a set of threads has
10
* all "reached" the barrier. The number of threads required is
11
* set when the barrier is initialized, and cannot be changed
12
* except by reinitializing.
14
* The barrier_init() and barrier_destroy() functions,
15
* respectively, allow you to initialize and destroy the
18
* The barrier_wait() function allows a thread to wait for a
19
* barrier to be completed. One thread (the one that happens to
20
* arrive last) will return from barrier_wait() with the status
21
* -1 on success -- others will return with 0. The special
22
* status makes it easy for the calling code to cause one thread
23
* to do something in a serial region before entering another
24
* parallel section of code.
32
* Initialize a barrier for use.
34
int barrier_init (barrier_t *barrier, int count)
38
barrier->threshold = barrier->counter = count;
40
status = pthread_mutex_init (&barrier->mutex, NULL);
43
status = pthread_cond_init (&barrier->cv, NULL);
45
pthread_mutex_destroy (&barrier->mutex);
48
barrier->valid = BARRIER_VALID;
53
* Destroy a barrier when done using it.
55
int barrier_destroy (barrier_t *barrier)
59
if (barrier->valid != BARRIER_VALID)
62
status = pthread_mutex_lock (&barrier->mutex);
67
* Check whether any threads are known to be waiting; report
70
if (barrier->counter != barrier->threshold) {
71
pthread_mutex_unlock (&barrier->mutex);
76
status = pthread_mutex_unlock (&barrier->mutex);
81
* If unable to destroy either 1003.1c synchronization
82
* object, return the error status.
84
status = pthread_mutex_destroy (&barrier->mutex);
85
status2 = pthread_cond_destroy (&barrier->cv);
86
return (status == 0 ? status : status2);
90
* Wait for all members of a barrier to reach the barrier. When
91
* the count (of remaining members) reaches 0, broadcast to wake
92
* all threads waiting.
94
int barrier_wait (barrier_t *barrier)
96
int status, cancel, tmp, cycle;
98
if (barrier->valid != BARRIER_VALID)
101
status = pthread_mutex_lock (&barrier->mutex);
105
cycle = barrier->cycle; /* Remember which cycle we're on */
107
if (--barrier->counter == 0) {
108
barrier->cycle = !barrier->cycle;
109
barrier->counter = barrier->threshold;
110
status = pthread_cond_broadcast (&barrier->cv);
112
* The last thread into the barrier will return status
113
* -1 rather than 0, so that it can be used to perform
114
* some special serial code following the barrier.
120
* Wait with cancellation disabled, because barrier_wait
121
* should not be a cancellation point.
123
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &cancel);
126
* Wait until the barrier's cycle changes, which means
127
* that it has been broadcast, and we don't want to wait
130
while (cycle == barrier->cycle) {
131
status = pthread_cond_wait (
132
&barrier->cv, &barrier->mutex);
133
if (status != 0) break;
136
pthread_setcancelstate (cancel, &tmp);
139
* Ignore an error in unlocking. It shouldn't happen, and
140
* reporting it here would be misleading -- the barrier wait
141
* completed, after all, whereas returning, for example,
142
* EINVAL would imply the wait had failed. The next attempt
143
* to use the barrier *will* return an error, or hang, due
144
* to whatever happened to the mutex.
146
pthread_mutex_unlock (&barrier->mutex);
147
return status; /* error, -1 for waker, or 0 */