#include #include #include #include #include "Semaphore.h" union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ }; /** * Constructs an array of n Unix semaphores initialized to zero * @param int semaphore quantity * */ Semaphore::Semaphore( int n ) { int status; union semun value; id = semget( 0xECC1, n, 0600 | IPC_CREAT ); this->nsems = n; value.val = 1; // Each semaphore will be initialized to one for ( int i = 0; i < this->nsems; i++ ) { status = semctl( id, i, SETVAL, value ); if ( -1 == status ) { perror( "Semaphore::Semaphore(int)" ); } } } /** * Constructs an array of n Unix semaphores initialized to zero using a base key * @param int key to be added to base key 0xECC1 * @param int semaphore quantity * */ Semaphore::Semaphore( int key, int n ) { int status; union semun value; id = semget( 0xECC1 + key, n, 0600 | IPC_CREAT ); this->nsems = n; value.val = 1; for ( int i = 0; i < this->nsems; i++ ) { status = semctl( id, i, SETVAL, value ); if ( -1 == status ) { perror( "Semaphore::Semaphore(int, int)" ); } } } /** * Destroys the semaphore array */ Semaphore::~Semaphore() { int status; status = semctl( id, 0, IPC_RMID, NULL ); if ( -1 == status ) { perror( "Semaphore::~Semaphore" ); } } /** * Signal operation on semaphore array, will try to add one to each semaphore in the array */ void Semaphore::Signal() { int status; struct sembuf V[nsems]; for ( int i = 0; i < nsems; i++ ) { V[i].sem_num = i; V[i].sem_op = 1; V[i].sem_flg = 0; } status = semop( id, V, nsems ); if ( -1 == status ) { perror( "Semaphore::Semaphore(int, int)" ); } } /** * Wait operation on semaphore array, will try to substract one to each semaphore in the array */ void Semaphore::Wait() { int status; struct sembuf P[nsems]; for ( int i = 0; i < nsems; i++ ) { P[i].sem_num = i; P[i].sem_op = -1; P[i].sem_flg = 0; } status = semop( id, P, nsems ); if ( -1 == status ) { perror( "Semaphore::Semaphore(int, int)" ); } } /** * 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 */ void Semaphore::SP( int first, int second ) { int status; struct sembuf P[ 2 ]; P[ 0 ].sem_num = first; P[ 0 ].sem_op = -1; P[ 0 ].sem_flg = 0; P[ 1 ].sem_num = second; P[ 1 ].sem_op = -1; P[ 1 ].sem_flg = 0; status = semop( this->id, P, 2 ); if ( -1 == status ) { perror( "Semaphore::SP(int, int)" ); } } /** * Do a Signal 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 */ void Semaphore::SV( int first, int second ) { int status; struct sembuf V[ 2 ]; V[ 0 ].sem_num = first; V[ 0 ].sem_op = 1; V[ 0 ].sem_flg = 0; V[ 1 ].sem_num = second; V[ 1 ].sem_op = 1; V[ 1 ].sem_flg = 0; status = semop( this->id, V, 2 ); if ( -1 == status ) { perror( "Semaphore::SV(int, int)" ); } }