// odd/even thread coordination on incrementing an global // variable. This version uses a condition variable to efficiently // notify threads of changes to the global variable. #include "odds_evens.h" int count = 0; // global variable all threads are modifiying pthread_mutex_t count_mutex; // mutex to check count pthread_cond_t count_condv; // condition variable to receive wake-ups // Run by even child threads, increment count when it is even void *even_work(void *t) { int tid = *( (int *) t); for(int i=0; i<THREAD_ITERS; i++){ pthread_mutex_lock(&count_mutex); while(count % 2 != 0){ // wait until count is even VPRINTF("%d iter %d: count %d, NOT EVEN, sleeping\n", tid, i, count); pthread_cond_wait(&count_condv, &count_mutex); // await notification to check again, gets lock on wakeup } printf("%d iter %d: count %d, IS EVEN, proceeding\n", tid, i, count); update(&count); // now have lock and condition is correct can safely increment pthread_mutex_unlock(&count_mutex); // release lock pthread_cond_broadcast(&count_condv); // notify all others waiting } printf("%d FINISHED %d iterations\n", tid, THREAD_ITERS); return NULL; } // Run by odd child threads, increment count when it is odd void *odd_work(void *t) { int tid = *( (int *) t); for(int i=0; i<THREAD_ITERS; i++){ pthread_mutex_lock(&count_mutex); while(count % 2 != 1){ // wait until count is odd VPRINTF("%d iter %d: count %d, NOT ODD, sleeping\n", tid, i, count); pthread_cond_wait(&count_condv, &count_mutex); // await notification to check again, gets lock on wakeup } printf("%d iter %d: count %d, IS ODD, proceeding\n", tid, i, count); update(&count); // now have lock can safely increment pthread_mutex_unlock(&count_mutex); // release lock pthread_cond_broadcast(&count_condv); // notify all others waiting, pthread_cond_signal() only notifies single thread } printf("%d FINISHED %d iterations\n", tid, THREAD_ITERS); return NULL; } int main(int argc, char *argv[]) { pthread_t threads[TOT_THREADS]; int tids[TOT_THREADS]; pthread_mutex_init(&count_mutex, NULL); // Initialize mutex and condition variable pthread_cond_init (&count_condv, NULL); for(int i=0; i<TOT_THREADS; i+=2){ tids[i] = i; pthread_create(&threads[i], NULL, even_work, (void *) &(tids[i])); tids[i+1] = i+1; pthread_create(&threads[i+1], NULL, odd_work, (void *) &(tids[i+1])); } for(int i=0; i<TOT_THREADS; i++) { // Wait for all threads to complete pthread_join(threads[i], NULL); } printf("main: count is %d\n",count); pthread_mutex_destroy(&count_mutex); // Clean up and exit pthread_cond_destroy(&count_condv); exit(0); }