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

Перейти на страницу:

Похожие книги