1 #include <pthread.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <atomic.h>
8 
9 static pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
10 static pthread_mutex_t mut1 = PTHREAD_MUTEX_INITIALIZER;
11 
12 static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
13 static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
14 
15 static bool last_round;
16 static int ntogo;
17 static bool alldone;
18 
19 
20 static void *
cons(void * arg)21 cons (void *arg)
22 {
23   pthread_mutex_lock (&mut1);
24 
25   do
26     {
27       if (atomic_decrement_and_test (&ntogo))
28 	{
29 	  pthread_mutex_lock (&mut2);
30 	  alldone = true;
31 	  pthread_cond_signal (&cond2);
32 	  pthread_mutex_unlock (&mut2);
33 	}
34 
35       pthread_cond_wait (&cond1, &mut1);
36     }
37   while (! last_round);
38 
39   pthread_mutex_unlock (&mut1);
40 
41   return NULL;
42 }
43 
44 
45 int
main(int argc,char * argv[])46 main (int argc, char *argv[])
47 {
48   int opt;
49   int err;
50   int nthreads = 10;
51   int nrounds = 100;
52   bool keeplock = false;
53 
54   while ((opt = getopt (argc, argv, "n:r:k")) != -1)
55     switch (opt)
56       {
57       case 'n':
58 	nthreads = atol (optarg);
59 	break;
60       case 'r':
61 	nrounds = atol (optarg);
62 	break;
63       case 'k':
64 	keeplock = true;
65 	break;
66       }
67 
68   ntogo = nthreads;
69 
70   pthread_t th[nthreads];
71   int i;
72   for (i = 0; __builtin_expect (i < nthreads, 1); ++i)
73     if (__glibc_unlikely ((err = pthread_create (&th[i], NULL, cons, (void *) (long) i)) != 0))
74       printf ("pthread_create: %s\n", strerror (err));
75 
76   for (i = 0; __builtin_expect (i < nrounds, 1); ++i)
77     {
78       pthread_mutex_lock (&mut2);
79       while (! alldone)
80 	pthread_cond_wait (&cond2, &mut2);
81       pthread_mutex_unlock (&mut2);
82 
83       pthread_mutex_lock (&mut1);
84       if (! keeplock)
85 	pthread_mutex_unlock (&mut1);
86 
87       ntogo = nthreads;
88       alldone = false;
89       if (i + 1 >= nrounds)
90 	last_round = true;
91 
92       pthread_cond_broadcast (&cond1);
93 
94       if (keeplock)
95 	pthread_mutex_unlock (&mut1);
96     }
97 
98   for (i = 0; i < nthreads; ++i)
99     if ((err = pthread_join (th[i], NULL)) != 0)
100       printf ("pthread_create: %s\n", strerror (err));
101 
102   return 0;
103 }
104