#include <stdio.h>#include <stdlib.h>#include <pthread.h>/* these signal which thread has its turn to execute */enum{ THREAD1_OK_TO_GO, THREAD2_OK_TO_GO, THREAD3_OK_TO_GO};/* this is the wait queue variable, it needs to be set before * threads execute */int queue = THREAD1_OK_TO_GO;void *thread1_func (void*);void *thread2_func (void*);void *thread3_func (void*);/* mutex and cond for queue handling */pthread_mutex_t cond_mutex1 = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;intmain (void){ pthread_t thread1, thread2, thread3; /* we'll create the threads in reverse order to demonstrate * that the queueing works in spite of it */ pthread_create (&thread3, NULL, thread3_func, NULL); pthread_create (&thread2, NULL, thread2_func, NULL); pthread_create (&thread1, NULL, thread1_func, NULL); while (1) {}}/* notice that the thread functions are nearly identical, so the * second and third one don't need much further commenting */void*thread1_func (void *ptr){ int i; while (1) { /* lock the queue check to prevent races, then wait for our turn */ pthread_mutex_lock (&cond_mutex1); while (queue != THREAD1_OK_TO_GO) pthread_cond_wait (&cond1, &cond_mutex1); pthread_mutex_unlock (&cond_mutex1); /* notice that we don't need a separate mutex for the relevant * part because it's conveniently sandwiched in between the queue * handling code */ putchar ('1'); /* after we're done we specify who goes next */ queue = THREAD2_OK_TO_GO; /* we'll signal other threads waiting for this cond to proceed. * locking is absolutely necessary here too! */ pthread_mutex_lock (&cond_mutex1); pthread_cond_broadcast (&cond1); pthread_mutex_unlock (&cond_mutex1); }}/* the parts that differ are commented */void*thread2_func (void *ptr){ int i; while (1) { pthread_mutex_lock (&cond_mutex1); /* notice that we're now waiting for THREAD2_OK_TO_GO */ while (queue != THREAD2_OK_TO_GO) pthread_cond_wait (&cond1, &cond_mutex1); pthread_mutex_unlock (&cond_mutex1); putchar ('2'); /* notice that we're now specifying the third thread as next */ queue = THREAD3_OK_TO_GO; pthread_mutex_lock (&cond_mutex1); pthread_cond_broadcast (&cond1); pthread_mutex_unlock (&cond_mutex1); }}void*thread3_func (void *ptr){ int i; while (1) { pthread_mutex_lock (&cond_mutex1); while (queue != THREAD3_OK_TO_GO) pthread_cond_wait (&cond1, &cond_mutex1); pthread_mutex_unlock (&cond_mutex1); putchar ('3'); /* the thread is done so we'll signal the first one again */ queue = THREAD1_OK_TO_GO; pthread_mutex_lock (&cond_mutex1); pthread_cond_broadcast (&cond1); pthread_mutex_unlock (&cond_mutex1); }}