#include <stdlib.h>
#include <stdio.h>
#include <sys/sem.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>

#define MAX_COUNT 50
#define Parent     1
#define Child      0

int Turn = Parent ;

void SafeSemOp(int semID, struct sembuf *sem, int nops)
{
  int result ;
  
  do {
    result = semop(semID, sem, nops);
    if (result == -1 && errno != EINTR)
    {
      perror("SafeSemOp() error! ");
      exit(1);
    }
  } while (result == -1) ;
      
}

void Wait(int semID)
{
  static struct sembuf semWait  [1] = {0, -1, 0} ;
  
  SafeSemOp(semID, semWait, 1);
}

void Signal(int semID)
{
  static struct sembuf semSignal[1] = {0,  1, 0} ;
  
  SafeSemOp(semID, semSignal, 1);
}

int main()
{
  int pid               ;
  int count = MAX_COUNT ;
  int semID, result, status ;
  
  semID = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
  if (semID == -1)
  {
    perror("Error creating semaphore! ");
    exit(1);
  }

  Signal(semID); /* initialize */

  switch (pid = fork())
  {
    case -1: // error
      perror("Fork failed! ");
      exit(1);
       
    case  0: // Child
      do {
      
        // enter critical section
        usleep(100);
        Wait(semID);
//        if (Turn == Child)
        {
          Turn = Parent ;
          fprintf(stdout, "Child executing loop #%2d\n", count);
          fflush(stdout);
          count -- ;
        }
        Signal(semID);
        
      } while (count) ;
      
      break ;
    
    default:
      do {
      
        // enter critical section
        usleep(100);
        Wait(semID);
//        if (Turn = Parent)
        {
          Turn = Child ;
          fprintf(stdout, "Parent executing loop #%2d\n", count);
          fflush(stdout);
          count -- ;
        }
        Signal(semID);
        
      } while (count) ;

      result = wait(&status);
      if (result == -1)
      {
        perror("Error in wait()! ");
      }
      if (semctl(semID, 0, IPC_RMID) == -1)
      {
        perror("Unable to remove semaphore! ");
        exit(1);
      }


      
  }

  return 0 ;
}


