137 lines
3.6 KiB
C
137 lines
3.6 KiB
C
|
/***************************************************************************
|
||
|
* Copyright 1995, Technion, Israel Institute of Technology
|
||
|
* Electrical Eng, Software Lab.
|
||
|
* Author: Michael Veksler.
|
||
|
***************************************************************************
|
||
|
* File: shm_semaph.c
|
||
|
* Purpose: Handle semaphores for shared memory operations.
|
||
|
***************************************************************************
|
||
|
*/
|
||
|
#define inline __inline__
|
||
|
#include <assert.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/sem.h>
|
||
|
#include <stdio.h>
|
||
|
#include <errno.h>
|
||
|
#include <stddebug.h>
|
||
|
#include <debug.h>
|
||
|
#include "shm_semaph.h"
|
||
|
#define SEM_READ 0
|
||
|
#define SEM_WRITE 1
|
||
|
|
||
|
/* IMPORTANT: Make sure that killed process will not lock everything.
|
||
|
* If possible, restrict usage of these functions.
|
||
|
*/
|
||
|
void shm_read_wait(shm_sem semid)
|
||
|
{
|
||
|
struct sembuf sop[2];
|
||
|
int ret;
|
||
|
|
||
|
dprintf_sem(stddeb,"shm_read_wait(%d)\n",semid);
|
||
|
sop[0].sem_num=SEM_READ;
|
||
|
sop[0].sem_op=1; /* add this read instance */
|
||
|
sop[0].sem_flg=SEM_UNDO; /* undo in case process dies */
|
||
|
|
||
|
sop[1].sem_num=SEM_WRITE;
|
||
|
sop[1].sem_op=0; /* wait until no writing instance exists */
|
||
|
sop[1].sem_flg=SEM_UNDO;
|
||
|
|
||
|
do {
|
||
|
ret=semop (semid,sop , 2);
|
||
|
} while (ret<0 && errno==EINTR); /* interrupted system call? */
|
||
|
|
||
|
if (ret<0)
|
||
|
fprintf(stderr,"failed semaphore lock for read. semid=%d,errno=%d\n",
|
||
|
semid, errno);
|
||
|
}
|
||
|
void shm_write_wait(shm_sem semid)
|
||
|
{
|
||
|
struct sembuf sop[3];
|
||
|
int ret;
|
||
|
|
||
|
dprintf_sem(stddeb,"shm_write_wait(%d)\n",semid);
|
||
|
sop[0].sem_num=SEM_READ;
|
||
|
sop[0].sem_op=0; /* wait until no reading instance exist */
|
||
|
sop[0].sem_flg=SEM_UNDO;
|
||
|
|
||
|
sop[1].sem_num=SEM_WRITE;
|
||
|
sop[1].sem_op=1; /* writing is in progress - disable read */
|
||
|
sop[1].sem_flg=SEM_UNDO; /* undo if process dies */
|
||
|
|
||
|
sop[2].sem_num=SEM_READ;
|
||
|
sop[2].sem_op=1; /* disable new writes */
|
||
|
sop[2].sem_flg=SEM_UNDO;
|
||
|
|
||
|
do {
|
||
|
ret=semop (semid,sop , 3);
|
||
|
} while (ret<0 && errno==EINTR); /* interrupted system call? */
|
||
|
|
||
|
if (ret<0) /* test for the error */
|
||
|
fprintf(stderr,"failed semaphore lock for write. semid=%d,errno=%d\n",
|
||
|
semid, errno);
|
||
|
}
|
||
|
void shm_write_signal(shm_sem semid)
|
||
|
{
|
||
|
struct sembuf sop[2];
|
||
|
int ret;
|
||
|
|
||
|
dprintf_sem(stddeb,"shm_write_signal(%d)\n",semid);
|
||
|
sop[0].sem_num=SEM_READ;
|
||
|
sop[0].sem_op=-1;
|
||
|
sop[0].sem_flg=IPC_NOWAIT | SEM_UNDO; /* no reason to wait */
|
||
|
|
||
|
sop[1].sem_num=SEM_WRITE;
|
||
|
sop[1].sem_op=-1;
|
||
|
sop[1].sem_flg=IPC_NOWAIT | SEM_UNDO; /* no reason to wait */
|
||
|
|
||
|
do {
|
||
|
ret=semop (semid,sop , 2);
|
||
|
} while (ret<0 && errno==EINTR); /* interrupted system call? */
|
||
|
|
||
|
if (ret<0) /* test for the error */
|
||
|
fprintf(stderr,"failed semaphore unlock for write. semid=%d,errno=%d\n",
|
||
|
semid, errno);
|
||
|
}
|
||
|
|
||
|
void shm_read_signal(shm_sem semid)
|
||
|
{
|
||
|
struct sembuf sop[2];
|
||
|
int ret;
|
||
|
|
||
|
dprintf_sem(stddeb,"shm_read_signal(%d)\n",semid);
|
||
|
sop[0].sem_num=SEM_READ;
|
||
|
sop[0].sem_op=-1;
|
||
|
sop[0].sem_flg=IPC_NOWAIT | SEM_UNDO; /* no reason to wait */
|
||
|
|
||
|
do {
|
||
|
ret=semop (semid,sop , 1);
|
||
|
} while (ret<0 && errno==EINTR); /* interrupted system call? */
|
||
|
|
||
|
if (ret<0) /* test for the error */
|
||
|
fprintf(stderr,"failed semaphore unlock for read. semid=%d,errno=%d\n",
|
||
|
semid, errno);
|
||
|
}
|
||
|
|
||
|
void shm_sem_init(shm_sem *sptr)
|
||
|
{
|
||
|
shm_sem semid;
|
||
|
union semun arg;
|
||
|
|
||
|
semid=semget (IPC_PRIVATE, 2, 0700 | IPC_CREAT);
|
||
|
|
||
|
arg.val=0;
|
||
|
semctl (semid, 0, SETVAL, arg);
|
||
|
semctl (semid, 1, SETVAL, arg);
|
||
|
*sptr=semid;
|
||
|
}
|
||
|
|
||
|
void shm_sem_done(shm_sem *semptr)
|
||
|
{
|
||
|
union semun arg;
|
||
|
|
||
|
semctl (*semptr, 0, IPC_RMID , arg);
|
||
|
semctl (*semptr, 1, IPC_RMID , arg);
|
||
|
|
||
|
*semptr= -1;
|
||
|
}
|