| lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame] | 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 * | 
 | 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 | 
 | 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 | } |