//assignment# 2
//cop6611
//compile: g++ sem.cpp
#include < iostream.h >
#include < sys/types.h >
#include < sys/ipc.h >
#include < sys/shm.h >
#include < fcntl.h >
#include < sys/sem.h >
//#include < stdlib.h >
#define SEM_MODE ( 0200 | 0400 | IPC_CREAT)
#define NUM_OF_SEM 1
union semun
{
int val ;
struct semid_ds *buf ;
ushort *array ;
};
typedef struct
{
int value ;
} SharedMemory ;
int semid ;
//using semaphores now
class Semaphore
{
public :
//init class
Semaphore( SharedMemory * sharedMemory )
{
this->sharedMemory = sharedMemory ;
this->sharedMemory->value = 0 ;
ptrsembuf = (struct sembuf*)new( struct sembuf ) ;
ptrsembuf->sem_num = 0 ;
ptrsembuf->sem_flg = 0 ;
}
//destructor
~Semaphore()
{
sharedMemory = 0 ;
//free up some memory
delete ptrsembuf ;
}
void processI( void )
{
unsigned int line = 0 ;
while( line < 50000 )
{
line++;
//p sem
pOperation() ;
//critical section
sharedMemory->value++ ;
//v sem
vOperation() ;
}//end while loop
}
void processJ( void )
{
unsigned int line = 0 ;
while( line < 50000 )
{
line++;
//p sem
pOperation() ;
//critical section
sharedMemory->value++ ;
//v sem
vOperation() ;
}//end while
}//end processJ
//return value of the shared memory
int getValue()
{
return sharedMemory->value ;
}
private :
//the shared memory
SharedMemory *sharedMemory ;
//structure for semaphore operations
struct sembuf *ptrsembuf ;
const int numelem = 1 ;
//P operation
void pOperation( void )
{
ptrsembuf->sem_op = -1 ;
if( semop( semid, ptrsembuf, numelem ) == -1 )
{
cerr << "semop" ;
exit( -1 ) ;
}
}
//V operation
void vOperation( void )
{
ptrsembuf->sem_op = 1 ;
if( semop( semid, ptrsembuf, numelem ) == -1 )
{
cerr << "semop" ;
exit( -1 ) ;
}
}
} ;
int main( void )
{
//structure which will hold shared memory variables
SharedMemory *sMemory ;
int shmid ; //shared memory ID
int pid1 ; //process id for child 1
int pid2 ; //process id for child 2
union semun initvar ;
int semnum = 0 ;
int semval ;
initvar.val = 1 ;
//get semphore
if( ( semid = semget( IPC_PRIVATE, NUM_OF_SEM, SEM_MODE ) ) == -1 )
{
cerr << "semget" ;
exit( -1 ) ;
}
//init count to 1
if( semctl( semid, semnum, SETVAL, initvar ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
//check count is = to 1
if( ( semval = semctl( semid, semnum, GETVAL, initvar ) ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
cout << "semaphore value is = " << semval << endl ;
//attempt to attach to an existing memory segment
// the size of SharedMemory structure
if( ( shmid = shmget( IPC_PRIVATE, sizeof( SharedMemory ), IPC_CREAT | 0666 ) ) < 0 )
{
cerr << "shmget" ;
exit( 1 ) ;
}
//attach the shared memory segment
//get address of sMemory
sMemory =(SharedMemory*)shmat( shmid,NULL,0 ) ;
if( sMemory ==(SharedMemory *) -1 )
{
cerr << "shmat" ;
exit( 1 );
}
//send sMemory address to pA's sharedMemory
//create object of petersonsAlgorithm class
Semaphore sPh( sMemory ) ;
//zero it, finished with pointer
sMemory = 0 ;
//create first process, processI
if( ( pid1 = fork() ) == 0 )
sPh.processI() ;
//create second process, processJ
if( ( pid1 != 0 )&&( pid2 = fork() ) == 0 )
sPh.processJ() ;
//only need one output to screen
if( ( pid1 != 0 )&&( pid2 != 0 ) )
{
//block the parent for 2 seconds
wait(NULL);
wait(NULL);
cout << "the final value is..... " << sPh.getValue() << endl ;
cout << "\t\t fin" << endl ;
//remove shared memory
if( shmctl( shmid, IPC_RMID, 0 ) == -1 )
{
cerr << "shmctl" ;
exit( -1 ) ;
}
//remove semaphore
if( semctl( semid, NUM_OF_SEM, IPC_RMID ) == -1 )
{
cerr << "semctl" ;
exit( -1 ) ;
}
}
//all done
return 0 ;
}