Monday, October 18, 2010

SEMAPHORES Example

#include <unistd.h>#include <errno.h>#include <sys/stat.h>#include <string.h>#include <sys/types.h>#include <fcntl.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <stdio.h>#include <sys/sem.h># include <stdlib.h>#define SHMSZ 4 /* Good for integer */#define BUF_SZ 16#define SHM_KEY 1234#define SEM_KEY 1235#define CHILD_INCREMENT_COUNT 67787#define PARENT_INCREMENT_COUNT 84823union
semun {int val; /* value for SETVAL */struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */unsigned short *array; /* array for GETALL, SETALL *//* Linux specific part: */struct seminfo *__buf; /* buffer for IPC_INFO */};

main()
{


key_t key;







* Create the shared segment.& semaphore.
*/
int shmid;int semid;int *child_shm, *parent_shm;union semun arg;int i;struct sembuf operations[1];int status;int pid;/*
perror(
exit(1);
}

perror(
exit(1);
}

* Initialize the semaphore to value 1. The idea is multiple processes
* do semop() of -1. So only one is allowed in critical section.
* initialize the shm to 0.
*/
if ((shmid = shmget(SHM_KEY, SHMSZ, IPC_CREAT | 0666)) < 0) {"shmget");if ((semid = semget(SEM_KEY, 1, IPC_CREAT | 0666)) < 0) {"semget");/*arg.val = 1;

perror(
exit(1);
}

perror(
exit(1);
}
*parent_shm = 0;

* create a child process. The above opened shm & sem fds get
* copied to child process as a result of fork(). They both attach to the
* shared memory and use the semphore to increment the value in the shm.
*/
if (semctl(semid, 0, SETVAL, arg) < 0) {"semctl");if ((parent_shm = shmat(shmid, NULL, 0)) == (int *)-1) {"parent shmat");/*
printf(

}

* Child process attaches to shm. It fill operations to block till
* it gets -1. Since the initial value of semaphore is 1, only one
* process can do -1. The other process will see the value as 0 and
* block till it sees sem value as 1. After semop(), increment the shm
* integer by 1. Then again use the semop to set the sem value to 1, so
* that other process gets the chance to run.
* Repeat the above for a defined number of times. Later similar thing is
* done for parent process also.
*/
if ((pid = fork()) < 0) {"Child Process Creation Error:%d\n", errno);return;/*



perror(
exit(1);
}

operations[0].sem_num = 0;
operations[0].sem_op = -1;
operations[0].sem_flg = 0;

perror(
exit(1);
}
*child_shm = *child_shm + 1;

usleep(1);
if (pid == 0) {if ((child_shm = shmat(shmid, NULL, 0)) == (int *)-1) {"child shmat");for (i = 0; i < CHILD_INCREMENT_COUNT; i++) {if (semop(semid, operations, 1) < 0) {"child semop");if (i%1000 == 0) {// sleep 1 us to increase window of critical section}
operations[0].sem_num = 0;
operations[0].sem_op = 1;
operations[0].sem_flg = 0;

perror(
exit(1);
}
}
}




operations[0].sem_num = 0;
operations[0].sem_op = -1;
operations[0].sem_flg = 0;


perror(
exit(1);
}
*parent_shm = *parent_shm + 1;

usleep(1);
if (semop(semid, operations, 1) < 0) {"child semop");if (pid != 0) {for (i = 0; i < PARENT_INCREMENT_COUNT; i++) {if (semop(semid, operations, 1) < 0) {"parent semop");if (i%1500 == 0) {// sleep 1 us to increase window of critical section}
operations[0].sem_num = 0;
operations[0].sem_op = 1;
operations[0].sem_flg = 0;

perror(
exit(1);
}
}

if (semop(semid, operations, 1) < 0) {"parent semop");// wait for child to completewait(&status);


* now that parent and child are done incrementing, check the
* consistency of the shm memory.
*/
/*
printf(
CHILD_INCREMENT_COUNT, PARENT_INCREMENT_COUNT, *parent_shm);

printf(
}
printf(
}
}

exit(0);
}
"Child Incremented %d times, Parent %d times. SHM Value %d\n", if (*parent_shm == (CHILD_INCREMENT_COUNT + PARENT_INCREMENT_COUNT)) {"Total of Parent & Child matches SHM value\n");else {"BUG - Total of Parent & Child DOESNT match SHM value\n");