141 lines
3.5 KiB
C
141 lines
3.5 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.
|
|
***************************************************************************
|
|
*/
|
|
#ifdef CONFIG_IPC
|
|
|
|
#define inline inline
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <sys/sem.h>
|
|
#include <errno.h>
|
|
#include "debug.h"
|
|
#include "shm_semaph.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(sem)
|
|
#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;
|
|
|
|
TRACE(sem,"(%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)
|
|
WARN(sem,"(semid=%d,errno=%d): Failed semaphore lock for read\n",
|
|
semid, errno);
|
|
}
|
|
void shm_write_wait(shm_sem semid)
|
|
{
|
|
struct sembuf sop[3];
|
|
int ret;
|
|
|
|
TRACE(sem,"(%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 */
|
|
WARN(sem,"(semid=%d,errno=%d): Failed semaphore lock for write\n",
|
|
semid, errno);
|
|
}
|
|
void shm_write_signal(shm_sem semid)
|
|
{
|
|
struct sembuf sop[2];
|
|
int ret;
|
|
|
|
TRACE(sem,"(%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 */
|
|
WARN(sem,"(semid=%d,errno=%d): Failed semaphore unlock for write\n",
|
|
semid, errno);
|
|
}
|
|
|
|
void shm_read_signal(shm_sem semid)
|
|
{
|
|
struct sembuf sop[2];
|
|
int ret;
|
|
|
|
TRACE(sem,"(%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 */
|
|
WARN(sem,"(semid=%d,errno=%d): Failed semaphore unlock for read\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;
|
|
}
|
|
|
|
#endif /* CONFIG_IPC */
|