Code:
#define BIGCOUNT 888 // initial value of process counter
#define SEM_POST_LIMIT 3
int sem_create_V(char *semfilepath, int seminterval , char semprojectid)
{
key_t key ;
int semid ;
int fileId;
FILE *fp;
if ((fp = fopen (semfilepath,"wb")) == NULL )
{
perror("fopen");
return -1;
}
fclose (fp);
if ( (key = ftok(semfilepath , semprojectid)) < 0 )
{
perror("ftok");
return -1;
}
if ( (semid = Sem_Create(key,seminterval)) < 0 )
return -1;
return semid ;
}
int Sem_Create(key_t key,int intval)
{
int id,semval;
union semnum{
int val;
struct semid_ds *buf;
ushort *array;
} semctl_arg;
op_lock[0].sem_num = 2;
op_lock[0].sem_op = 0;
op_lock[0].sem_flg = 0;
op_lock[1].sem_num = 2;
op_lock[1].sem_op = 1;
op_lock[1].sem_flg = 0;
op_endcreate[0].sem_num = 1;
op_endcreate[0].sem_op = -1;
op_endcreate[0].sem_flg = 0;
op_endcreate[1].sem_num = 2;
op_endcreate[1].sem_op = -1;
op_endcreate[1].sem_flg = 0;
if (key== IPC_PRIVATE)
return -1;
else
if (key == (key_t)-1)
return -1;
if ((id=semget(key,3,0666|IPC_CREAT))<0)
// if ((id=semget(key,3,IPC_CREAT))<0)
{
perror("semget create");
return -1;
}
again:;
if (semop(id,&op_lock[0],2)<0) {
if (errno== EINVAL)
goto again;
perror("semop create");
return -1;
}
// get the value of the process counter,if it equal 0,then no one has initialize the semaphore
if ((semval =semctl(id,1,GETVAL,0)) <0)
{
perror("semctl create GETVAL");
return -1;
}
if (semval == 0) {
semctl_arg.val = intval;
if ( semctl(id,0,SETVAL,semctl_arg) < 0)
{
perror("semctl create SETVAL");
return -1;
}
semctl_arg.val = BIGCOUNT;
if (semctl(id,1,SETVAL,semctl_arg) < 0)
{
perror("semctl create SETVAL");
return -1;
}
}
if (semop(id,&op_endcreate[0],2) < 0)
{
perror("semop create");
return -1;
}
return id;
}
int sem_wait_V(int id, struct sembuf *sem_pv)
{
sem_pv = new struct sembuf [1] ;
if (sem_op(id,-1, sem_pv)<0)
{
// perror("sem_op waiting");
// printf("sem_wait_V: %d,%d !\n",id,errno) ;
delete sem_pv ;
return -1;
}
delete sem_pv ;
return 0;
}
int sem_post_V(int id, int sem_post_value_V, struct sembuf *sem_pv)
{
if ((sem_post_value_V = semctl(id,0,GETVAL,0)) <0)
{
return -1;
}
if( sem_post_value_V > SEM_POST_LIMIT )
{
if( sem_post_value_V == SEM_POST_LIMIT + 1 ) return -1 ;
return -1 ;
}
sem_pv = new struct sembuf [1] ;
if (sem_op(id,1,sem_pv)<0)
{
delete sem_pv ;
return -1;
}
delete sem_pv ;
return 0;
}
int sem_op(int id,int value, struct sembuf sem_pv1[1] )
{
int sem_value ,sem_value1;
struct sembuf sem_pv[1];
sem_pv[0].sem_num = 0 ;
sem_pv[0].sem_flg = 0 ;
if ((sem_pv[0].sem_op =value) == 0)
{
printf("sem_op error: operator is zero !!!!!!!(%d)\n",id) ;
return -1;
}
if ((sem_value = semctl(id,0,GETVAL,0)) <0)
{
perror("semctl create GETVAL");
return -1;
}
again:;
if (semop(id,&sem_pv[0],1)<0)
{
sched_yield() ;
if(errno==EINTR)
{
if ((sem_value1 = semctl(id,0,GETVAL,0)) <0)
{
perror("semctl create GETVAL");
return -1;
}
else
{
if (sem_value != sem_value1 )
return -1;
else
goto again;
}
}
return -1;
}
return 1;
}