/* ----------------------------------------------------------------- */
/* PROGRAM  pingpong:                                                */
/*    This program forces two threads to execute alternately.        */
/* ----------------------------------------------------------------- */

#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;

/* ----------------------------------------------------------------- */
/* FUNCTION  ThreadA()                                               */
/* ----------------------------------------------------------------- */

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");
}

/* ----------------------------------------------------------------- */
/* FUNCTION  ThreadB()                                               */
/* ----------------------------------------------------------------- */

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");
}

/* ----------------------------------------------------------------- */
/*                        The main program                           */
/* ----------------------------------------------------------------- */

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");

     /* ------------------------------------------------------------ */
     /* Wait_for_A   1: we want A gets through first than notifies B */
     /* Wait_for_B   0: B should be blocked until notified by A      */
     /* ------------------------------------------------------------ */

     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");
}