#include
#include
#include
#include
#include
#include
#include
#include
//#define DEBUG
enum {
WriterLock = 0,
ReaderCountLock = 1,
WriterCountLock = 2,
WriterCountSema = 3
};
int semid = -1;;
int shmid = -1;
struct sembuf sop;
int * ptrReaderCount = NULL;
int * ptrDataChangeCount = NULL;
void lock ( int i );
void unlock ( int i );
void waitTillNoWriter();
void getReaderLock();
void releaseReaderLock();
#ifndef DEBUG
const int bufSize = 20;
char buf[bufSize];
#endif
int main ( int argc, char * argv[] )
{
int iCount = 0;
int waitTime = 1;
int stat = -1;
if ( argc > 2 ) {
printf ( "Syntax Error : more than one arguments specified !!\n" );
exit(1);
}
if ( argc == 2 ) {
waitTime = atoi ( argv[1] );
}
else
waitTime = 5;
printf ( "Getting id of semaphore set with key 0x20...\n" );
semid = semget ( 0x20, 4, IPC_CREAT|0666);
if ( semid == -1 ) {
perror ( "semaphore id retreival failed " );
exit(1);
}
printf ( "Semaphore semid is : %d\n", semid );
key_t shKey = 0x1000;
shmid = shmget ( shKey, sizeof(int)*2, IPC_CREAT|0666 );
if ( shmid == -1 ) {
perror ( "cannot allocated shared memory " );
printf ( "\ndeleting the semaphore set id : %d\n", semid );
int stat = semctl ( semid, 0, IPC_RMID, 0 );
if ( stat == -1 ) {
perror ( "semaphore deletion failed " );
exit ( 1 );
}
printf ( "semaphore set with id : %d deleted!!\n", semid );
exit(1);
}
int * ptr = (int *) shmat ( shmid, 0, 0 );
ptrReaderCount = ptr;
ptrDataChangeCount = ptr+1;
while ( 1 )
{
printf ( "Iteration : %d\n",iCount++);
getReaderLock();
// reading data ...
printf ( " Reading Data ... DataChangeCount : %d\n", *ptrDataChangeCount);
#ifndef DEBUG
int fd = open ( "abc.dat", O_RDONLY );
if ( fd == -1 ) {
perror ( "cannot open file for reading " );
exit(1);
}
read ( fd, buf, bufSize );
for ( int i = 0 ; i < bufSize ; i++ )
printf ( "%c", buf[i] );
printf ( "\n" );
close (fd);
#endif
releaseReaderLock();
printf ( " sleeping for %d seconds, before attempting to read again ...\n", waitTime);
sleep ( waitTime );
}
}
void getReaderLock()
{
#ifdef DEBUG
printf ( " waiting till no writer ...\n" );
#endif
waitTillNoWriter();
#ifdef DEBUG
printf ( " locking ReaderCountLock ...\n" );
#endif
lock ( ReaderCountLock );
if ( *ptrReaderCount == 0 ) {
#ifdef DEBUG
printf ( " I am the First Reader hence locking WriterLock ...\n" );
#endif
lock ( WriterLock );
}
#ifdef DEBUG
printf ( " Incrementing reader count ...\n" );
#endif
(*ptrReaderCount)++;
#ifdef DEBUG
printf ( " Now ReaderCount = %d\n", *ptrReaderCount );
printf ( " unlocking ReaderCountLock ...\n" );
#endif
unlock ( ReaderCountLock );
}
void releaseReaderLock()
{
#ifdef DEBUG
printf ( " locking ReaderCountLock ...\n" );
#endif
lock ( ReaderCountLock );
#ifdef DEBUG
printf ( " Decrementing reader count\n" );
#endif
(*ptrReaderCount)--;
#ifdef DEBUG
printf ( " Now ReaderCount = %d\n", *ptrReaderCount );
#endif
if ( *ptrReaderCount == 0 ) {
#ifdef DEBUG
printf ( " I am the Last Reader hence unlocking WriterLock ...\n" );
#endif
unlock ( WriterLock );
}
#ifdef DEBUG
printf ( " unlocking ReaderCountLock ...\n" );
#endif
unlock ( ReaderCountLock );
}
void lock ( int i )
{
sop.sem_num = i;
sop.sem_op = -1;
sop.sem_flg = SEM_UNDO;
if ( semop(semid,&sop,1) == -1 ) {
perror ( "Error while decrementing semaphore " );
exit(1);
}
}
void unlock ( int i )
{
sop.sem_num = i;
sop.sem_op = 1;
sop.sem_flg = SEM_UNDO;
if ( semop(semid,&sop,1) == -1 ) {
perror ( "Error while incrementing semaphore " );
exit(1);
}
}
void waitTillNoWriter()
{
sop.sem_num = 3;
sop.sem_op = 0;
sop.sem_flg = SEM_UNDO;
if ( semop(semid,&sop,1) == -1 ) {
perror ( "Error while waiting on semaphore " );
exit(1);
}
}