/* barrier.c From Robbins & Robbins Sets up a barrier blocking n threads. If more than n arrive, the rest can go through. Interesting to consider what it takes to reuse safely. Need to know that all waiting threads have gone through... */ #include #include static pthread_cond_t bcond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t bmutex = PTHREAD_MUTEX_INITIALIZER; static int limit = 0; // How many have to arrive before the barrier is open. static int count = 0; // How many have arrived. // initialize the barrier to be size n int initbarrier(int n) { int error; // Safely, modify the limit. if ((error = pthread_mutex_lock(&bmutex))) // Failed to execute mutex_lock return error; limit = n; count = 0; // Not in R&R return pthread_mutex_unlock(&bmutex); } // wait at the barrier until all n threads arrive int waitbarrier(void) { int berror = 0; // Holds the return values from the pthread_cond_ functions int error; // Holds the return values from pthread_mutex_lock / unlock. // Safely, access the barrier value if ((error = pthread_mutex_lock(&bmutex))) return error; // locking failed! // make sure barrier initialized if (limit <= 0) { // Looks like no one initialized the barrier or else they did // it poorly. Release the lock pthread_mutex_unlock(&bmutex); // and report that it was invalid return EINVAL; } count++; // We're in! while ((count < limit) && !berror) berror = pthread_cond_wait(&bcond, &bmutex); if (!berror) // wake up everyone! // The count has hit the limit. berror = pthread_cond_broadcast(&bcond); error = pthread_mutex_unlock(&bmutex); if (berror) return berror; return error; }