Alternating Execution

The following program creates two threads and forces them to run in an alternating way. More precisely, if the threads are A and B, this program forces them to execute in an order of A, B, A, B, A, B, .... This is done using two semaphores, one for blocking each thread.

Click here to download a copy of this program.

#include  <stdio.h>
#include  <stdlib.h>
#include  <thread.h>
#include  <synch.h>

sema_t    Wait_for_A, Wait_for_B;  /* blocking semaphores */

int       Max_Run;

void *ThreadA(void *JunkPTR)
{
     int   i;

     printf("Thread A started\n");
     for (i = 1; i <= Max_Run; i++)  {
          thr_yield();
          sema_wait(&Wait_for_A);
               printf("This is from thread A\n");
          sema_post(&Wait_for_B);
     }
     printf("Thread A ends\n");
}

void *ThreadB(void *JunkPTR)
{
     int   i;

     printf("     Thread B started\n");
     for (i = 1; i <= Max_Run; i++)  {
          thr_yield();
          sema_wait(&Wait_for_B);
               printf("     This is from thread B\n");
          sema_post(&Wait_for_A);
     }
     printf("Thread B ends\n");
}

void  main(int argc,  char *argv[])
{
     thread_t  ID_A, ID_B;
     size_t    Status_A, Status_B;

          if (argc != 2) {
          printf("Use %s #-of-iterations\n", argv[0]);
          exit(0);
     }
     Max_Run = abs(atoi(argv[1]));

     printf("Parent started ...\n");

     sema_init(&Wait_for_A, 1, USYNC_THREAD, (void *) NULL);
     sema_init(&Wait_for_B, 0, USYNC_THREAD, (void *) NULL);

     thr_create(NULL, 0, ThreadA, (void *) NULL, 0, (void *) &ID_A);
     thr_create(NULL, 0, ThreadB, (void *) NULL, 0, (void *) &ID_B);

     thr_join(ID_A, 0, (void *) &Status_A);
     thr_join(ID_B, 0, (void *) &Status_B);

     printf("Parent exits ...\n");
}
This example shows an important use of semaphore. In addition to be used as locks, semaphores can block the execution of a thread until it is notified by other threads. This concept will be used in the next example, bounded buffer.