We currently use 1 semaphore for each piece of data in the shared memory.
The problems is that there is heavy semaphore usage, and our current
simple implementation allows only one process to look at a piece of
data at 1 time.
What I think we need to move towards is a 'read-lock & write-lock'
semaphore(s), so that many reader's could read at the same time, while
only 1 writer would be allowed to update the particular data and
every other reader/writer would be blocked.
Does anyone have some C source code that does this that they would
be willing to send me? Or does anyone know where I could download
some source like this?
thanks,
Curtis Siemens (sie...@mprgate.mpr.ca)
Try this. This also will fail lock requests if an exclusive holder of
the lock terminates abnormally possibly leaving the data in an inconsistent
state.
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/mode.h>
int initialize(int *semid, char *path, char id) {
key_t key;
unsigned short val[3]={1, 0, 0};
if ((key=ftok(path, id))<0)
return -1;
if ((*semid=semget(key, 3, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR))>=0) {
semctl(*semid, 0, SETALL, val);
}
else
if (errno==EEXIST) {
if ((*semid=semget(key, 3, S_IRUSR|S_IWUSR))<0) {
return -1;
}
}
else {
return -1;
}
return 0;
}
int acquire_shared(int semid) {
struct sembuf sb[4];
sb[0].sem_flg= 0; sb[0].sem_num=0; sb[0].sem_op=-1;
sb[1].sem_flg= SEM_UNDO; sb[1].sem_num=1; sb[1].sem_op=+1;
sb[2].sem_flg= 0; sb[2].sem_num=0; sb[2].sem_op=+1;
sb[3].sem_flg=IPC_NOWAIT; sb[3].sem_num=2; sb[3].sem_op= 0;
return semop(semid, sb, 4);
}
int release_shared(int semid) {
struct sembuf sb[1];
sb[0].sem_flg=SEM_UNDO; sb[0].sem_num=1; sb[0].sem_op=-1;
return semop(semid, sb, 1);
}
int acquire_exclusive(int semid) {
struct sembuf sb[2];
int rc;
sb[0].sem_flg= SEM_UNDO; sb[0].sem_num=0; sb[0].sem_op=-1;
sb[1].sem_flg=IPC_NOWAIT; sb[1].sem_num=2; sb[1].sem_op= 0;
if ((rc=semop(semid, sb, 2))<0)
return rc;
sb[0].sem_flg= 0; sb[0].sem_num=1; sb[0].sem_op= 0;
sb[1].sem_flg= 0; sb[1].sem_num=2; sb[1].sem_op=+1;
if ((rc=semop(semid, sb, 2))<0 && errno!=EIDRM) {
sb[0].sem_flg= SEM_UNDO; sb[0].sem_num=0; sb[0].sem_op=+1;
if (semop(semid, sb, 1)<0)
abort();
}
return rc;
}
int release_exclusive(int semid) {
struct sembuf sb[2];
/* reset flag */
sb[0].sem_flg=SEM_UNDO; sb[0].sem_num=0; sb[0].sem_op=+1;
sb[1].sem_flg= 0; sb[1].sem_num=2; sb[1].sem_op=-1;
return semop(semid, sb, 2);
}
int cleanup(int semid) {
return semctl(semid,0,IPC_RMID,0);
}
--
Joe Seigh