Universidad de Costa Rica

Escuela de Ciencias de la Computación e Informática

CI-0122 Sistemas Operativos

Temas

CI0122 / Temas revisados / Semana-06 / ForkAndSems / H2O


/*
 *  C++ class to encapsulate Unix semaphore intrinsic structures and system calls
 *  Author: Programacion Concurrente (Francisco Arroyo)
 *  Version: 2020/Ago/04
 *
 *  En esta nueva versión vamos a construir un arreglo de semáforos,
 *  el tamaño es indicado por el constructor (cantidad)
 *  Las operaciones Wait y Signal reciben el parámetro sobre el cual se pretende
 *  realizar esa operación
 *  Además, vamos a agregar dos métodos nuevos para poder operar sobre dos
 *  semáforos simultáneamente y resolver el problema de los filósofos
 *
 */

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

#include "Semaphore.h"


Semaphore::Semaphore( int cantidad, int valorInicial ) {
   int status;
   union semun {
      int              val;
      struct semid_ds *buf;
      unsigned short  *array;
      struct seminfo  *__buf;
   } value;

   status = semget( IPC_PRIVATE, cantidad, 0600 | IPC_CREAT | IPC_EXCL );
   if ( -1 == status ) {
       perror( "Semaphore::Semaphore(int, int) creator" );
       exit( 23 );
   }
   this->semId = status;
   this->nsems = cantidad;
   this->creador = getpid();

   value.val = valorInicial;	// Each semaphore will be initialized to this value
   for ( int i = 0; i < this->nsems; i++ ) {
       status = semctl( this->semId, i, SETVAL, value );
       if ( -1 == status ) {
          perror( "Semaphore::Semaphore(int, int) initializer" );
          exit( 23 );
       }
   }

}


Semaphore::~Semaphore() {
   int resultado;

   if ( this->creador == getpid() ) {
      resultado = semctl( this->semId, IPC_RMID, 0 );
   }

}

int Semaphore::Signal( int cual ) {
   int status = -1;
   struct sembuf S;

   S.sem_num = cual;
   S.sem_op  = 1;
   S.sem_flg = 0;

   status = semop( this->semId, &S, 1 );
   if ( -1 == status ) {
      perror( "Semaphore::Signal" );
      exit( 23 );
   }

   return status;

}

int Semaphore::Wait( int cual ) {
   int status = -1;
   struct sembuf P;

   P.sem_num = cual;
   P.sem_op  = -1;
   P.sem_flg = 0;
   status = semop( this->semId, &P, 1 );
   if ( -1 == status ) {
      perror( "Semaphore::Wait" );
      exit( 23 );
   }

   return status;

}

/*
 * Do a Wait operation on two semaphores, will try to substract one to each semaphore
 * This operation must be atomic, not allowed to block one semaphore
 * and try to block the other
 * The block operation must occur on both semaphores atomically
 * It will try to get the lock on two semaphores from the group,
 * especified by parameters
 *
 */
void Semaphore::SP( int primero, int segundo ) {
   int resultado;
   struct sembuf P[ 2 ];

   P[ 0 ].sem_num = primero;
   P[ 0 ].sem_op  = -1;
   P[ 0 ].sem_flg = 0;

   P[ 1 ].sem_num = segundo;
   P[ 1 ].sem_op  = -1;
   P[ 1 ].sem_flg = 0;

   // resultado = semop( ... );

}


/*
 *
 */
void Semaphore::SV( int primero, int segundo ) {
}


/*
 *
 */
void Semaphore::setInitialValue( int valorInicial ) {
   int resultado;
   union semun {
      int              val;
      struct semid_ds *buf;
      unsigned short  *array;
      struct seminfo  *__buf;
   } value;

   value.val = valorInicial;	// Each semaphore will be initialized to this value
   for ( int i = 0; i < this->nsems; i++ ) {
       resultado = semctl( semId, i, SETVAL, value );
       if ( -1 == resultado ) {
          perror( "Semaphore::Semaphore(int)" );
          exit( 23 );
       }
   }

}