| /*************************************************************************** |
| * 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 */ |