Release 950901
[wine] / ipc / shm_semaph.c
1 /***************************************************************************
2  * Copyright 1995, Technion, Israel Institute of Technology
3  * Electrical Eng, Software Lab.
4  * Author:    Michael Veksler.
5  ***************************************************************************
6  * File:      shm_semaph.c
7  * Purpose:   Handle semaphores for shared memory operations.
8  ***************************************************************************
9  */
10 #ifdef CONFIG_IPC
11
12 #define inline __inline__
13 #include <assert.h>
14 #include <unistd.h>
15 #include <sys/sem.h>
16 #include <stdio.h>
17 #include <errno.h>
18 #include <stddebug.h>
19 #include <debug.h>
20 #include "shm_semaph.h"
21 #define SEM_READ  0
22 #define SEM_WRITE 1
23
24 /* IMPORTANT: Make sure that killed process will not lock everything.
25  *            If possible, restrict usage of these functions.
26  */
27 void shm_read_wait(shm_sem semid)
28 {
29   struct sembuf sop[2];
30   int ret;
31   
32   dprintf_sem(stddeb,"shm_read_wait(%d)\n",semid);
33   sop[0].sem_num=SEM_READ;
34   sop[0].sem_op=1;                 /* add this read instance */
35   sop[0].sem_flg=SEM_UNDO;         /* undo in case process dies */
36   
37   sop[1].sem_num=SEM_WRITE;
38   sop[1].sem_op=0;                 /* wait until no writing instance exists */
39   sop[1].sem_flg=SEM_UNDO;
40
41   do {
42      ret=semop (semid,sop , 2);
43   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
44   
45   if (ret<0) 
46      fprintf(stderr,"failed semaphore lock for read. semid=%d,errno=%d\n",
47              semid, errno);
48 }
49 void shm_write_wait(shm_sem semid)
50 {
51   struct sembuf sop[3];
52   int ret;
53   
54   dprintf_sem(stddeb,"shm_write_wait(%d)\n",semid);
55   sop[0].sem_num=SEM_READ;
56   sop[0].sem_op=0;                 /* wait until no reading instance exist */
57   sop[0].sem_flg=SEM_UNDO;                 
58
59   sop[1].sem_num=SEM_WRITE;
60   sop[1].sem_op=1;                 /* writing is in progress - disable read */
61   sop[1].sem_flg=SEM_UNDO;         /* undo if process dies */
62
63   sop[2].sem_num=SEM_READ;
64   sop[2].sem_op=1;                 /* disable new writes */
65   sop[2].sem_flg=SEM_UNDO;
66   
67   do {
68      ret=semop (semid,sop , 3);
69   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
70
71   if (ret<0)                       /* test for the error */
72      fprintf(stderr,"failed semaphore lock for write. semid=%d,errno=%d\n",
73              semid, errno);
74 }
75 void shm_write_signal(shm_sem semid)
76 {
77   struct sembuf sop[2];
78   int ret;
79
80   dprintf_sem(stddeb,"shm_write_signal(%d)\n",semid);
81   sop[0].sem_num=SEM_READ;
82   sop[0].sem_op=-1;     
83   sop[0].sem_flg=IPC_NOWAIT | SEM_UNDO; /* no reason to wait */
84
85   sop[1].sem_num=SEM_WRITE;
86   sop[1].sem_op=-1;                
87   sop[1].sem_flg=IPC_NOWAIT | SEM_UNDO; /* no reason to wait */
88
89   do {
90      ret=semop (semid,sop , 2);
91   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
92
93   if (ret<0)                       /* test for the error */
94      fprintf(stderr,"failed semaphore unlock for write. semid=%d,errno=%d\n",
95              semid, errno);
96 }
97
98 void shm_read_signal(shm_sem semid)
99 {
100   struct sembuf sop[2];
101   int ret;
102
103   dprintf_sem(stddeb,"shm_read_signal(%d)\n",semid);
104   sop[0].sem_num=SEM_READ;
105   sop[0].sem_op=-1;     
106   sop[0].sem_flg=IPC_NOWAIT | SEM_UNDO; /* no reason to wait */
107
108   do {
109      ret=semop (semid,sop , 1);
110   } while (ret<0 && errno==EINTR);  /* interrupted system call? */
111
112   if (ret<0)                       /* test for the error */
113      fprintf(stderr,"failed semaphore unlock for read. semid=%d,errno=%d\n",
114              semid, errno);
115 }
116
117 void shm_sem_init(shm_sem *sptr)
118 {
119   shm_sem semid;
120   union semun arg;
121
122   semid=semget (IPC_PRIVATE, 2, 0700 | IPC_CREAT);
123
124   arg.val=0;
125   semctl (semid, 0, SETVAL, arg);
126   semctl (semid, 1, SETVAL, arg);
127   *sptr=semid;
128 }
129
130 void shm_sem_done(shm_sem *semptr)
131 {
132   union semun arg;
133
134   semctl (*semptr, 0, IPC_RMID , arg);
135   semctl (*semptr, 1, IPC_RMID , arg);
136
137   *semptr= -1;
138 }
139
140 #endif  /* CONFIG_IPC */