26 * some special serial code following the barrier.
27 */
28 if (status == 0)
29 status = -1;
30 } else {
31 /*
32 * Wait with cancellation disabled, because barrier_wait
33 * should not be a cancellation point.
34 */
35 pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &cancel); 36
37 /*
38 * Wait until the barrier's cycle changes, which means
39 * that it has been broadcast, and we don't want to wait
40 * anymore.
41 */
42 while (cycle == barrier->cycle) {
43 status = pthread_cond_wait (
44 &barrier->cv, &barrier->mutex);
45 if (status != 0) break;
46 }
47
48 pthread_setcancelstate (cancel, &tmp);
49 }
50 /*
51 * Ignore an error in unlocking. It shouldn't happen, and
52 * reporting it here would be misleading — the barrier wait
53 * completed, after all, whereas returning, for example,
54 * EINVAL would imply the wait had failed. The next attempt
55 * to use the barrier *will* return an error, or hang, due
56 * to whatever happened to the mutex.
57 */
58 pthread_mutex_unlock (&barrier->mutex);
59 return status; /* error, -1 for waker, or 0 */
60 }
Finally, barrier_main.c is a simple program that uses barriers. Each thread
loops on calculations within a private array. 35,47 At the beginning and end of each iteration, the threads, running function
thread_routine, all wait on a barrier to synchronize the operation. 56-61 At the end of each iteration, the "lead thread" (the one receiving a -1 result
from barrier_wait) will modify the data of all threads, preparing them for the next iteration. The others go directly to the top of the loop and wait on the barrier at line 35.
■ barrier_main.c
1 #include
2 #include "barrier.h"
3 #include "errors.h"
4
5 #define THREADS 5
6 #define ARRAY 6
7 #define INLOOPS 1000
8 #define OUTLOOPS 10
9
10 /*
11 * Keep track of each thread.
12 */
13 typedef struct thread_tag {
14 pthread_t thread_id;
15 int number;
16 int increment;
17 int array[ARRAY];
18 } thread_t;
19
20 barrier_t barrier;
21 thread_t thread[THREADS];
22
23 /*
24 * Start routine for threads.
25 */
26 void *thread_routine (void *arg)
27 {
28 thread_t *self = (thread_t*)arg; /* Thread's thread_t */
29 int in_loop, out_loop, count, status;
30
31 /*
32 * Loop through OUTLOOPS barrier cycles.
33 */
34 for (out_loop = 0; out_loop < OUTLOOPS; out_loop++) {
35 status = barrier_wait (&barrier);
36 if (status > 0)
37 err_abort (status, "Wait on barrier");
38
39 /*
40 * This inner loop just adds a value to each element in
41 * the working array.
42 */
43 for (in_loop = 0; in_loop < INLOOPS; in_loop++)
44 for (count = 0; count < ARRAY; count++)
45 self->array[count] += self->increment; 46
47 status = barrier_wait (&barrier);
48 if (status > 0)
49 err_abort (status, "Wait on barrier");
50
51 /*
52 * The barrier causes one thread to return with the
53 * special return status -1. The thread receiving this