#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <time.h>
#include <string.h>
#include <sys/types.h>

#define SHM_KEY 99
#define SEM_KEY 111

int seg_id,semid;

init_sem(int semid,int semnum,int val)
{
    union semun{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
    }initval;
    initval.val=val;
    if(semctl(semid,semnum,SETVAL,initval)==-1)
    {
	perror("semctl");
	exit(1);
    }
}

int get_semval(int semid,int semnum)
{
    union semun{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
    }getval;
    int val;
    if((val=semctl(semid,semnum,GETVAL,getval))==-1)
    {
	perror("semctl");
	exit(1);
    }
    return val;
}


lockforwrite(int semid)
{
    struct sembuf action[2];
    action[0].sem_num=0;
    action[0].sem_flg=SEM_UNDO;
    action[0].sem_op=0; 
    action[1].sem_num=1;
    action[1].sem_flg=SEM_UNDO;
    action[1].sem_op=+1;
    if(semop(semid,action,2)==-1)
    {
	perror("semop");
	exit(1);
    }
}

unlockafterwrite(int semid)
{
    struct sembuf action[1];
    action[0].sem_num=1;
    action[0].sem_flg=SEM_UNDO;
    action[0].sem_op=-1;
    if(semop(semid,action,1)==-1)
    {
	perror("semop");
	exit(1);
    }

}

main()
{
    char *mem_ptr;
    time_t now;
    int i=8;
    
    seg_id=shmget(SHM_KEY,100,IPC_CREAT|0777);
    if(seg_id==-1)
    {
	perror("shmget");
	exit(1);
    }
    mem_ptr=shmat(seg_id,NULL,0);
    if(mem_ptr==NULL)
    {
	perror("shmat");
	exit(1);
    }

    semid=semget(SEM_KEY,2,IPC_CREAT|IPC_EXCL|0666);
    if(semid==-1)
    {
	perror("semget");
	exit(1);
    }
    init_sem(semid,0,0);
    init_sem(semid,1,0);

    while(i>0)
    {
	time(&now);
	printf("Lock for write now ...\n");
 	lockforwrite(semid);
	    printf("**********************************************\n");
    printf("sem value of read=%d,sem_value of write=%d\n",get_semval(semid,0),get_semval(semid,1));
    printf("***********************************************\n");
 strcpy(mem_ptr,ctime(&now));
	sleep(1);
	unlockafterwrite(semid);
	printf("Unlock now\n");
	i--;
    
    printf("**********************************************\n");
    printf("sem value of read=%d,sem_value of write=%d\n",get_semval(semid,0),get_semval(semid,1));
    printf("***********************************************\n");
    }
    shmctl(seg_id,IPC_RMID,NULL);
    semctl(semid,0,IPC_RMID,NULL);
}
