/* * 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 #include #include #include #include #include #include #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 ); } } }