
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 (__builtin_expect ((err = pthread_create (&th[i], NULL, cons, (void *) (long) i)) != 0, 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: }