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