Merge from vendor branch GDB:
[dragonfly.git] / contrib / sendmail-8.13.4 / libsm / sem.c
1 /*
2  * Copyright (c) 2000-2001, 2005 Sendmail, Inc. and its suppliers.
3  *      All rights reserved.
4  *
5  * By using this file, you agree to the terms and conditions set
6  * forth in the LICENSE file which can be found at the top level of
7  * the sendmail distribution.
8  */
9
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: sem.c,v 1.12 2005/03/25 21:27:02 ca Exp $")
12
13 #if SM_CONF_SEM
14 # include <stdlib.h>
15 # include <unistd.h>
16 # include <sm/sem.h>
17 # include <sm/heap.h>
18
19 /*
20 **  SM_SEM_START -- initialize semaphores
21 **
22 **      Parameters:
23 **              key -- key for semaphores.
24 **              nsem -- number of semaphores.
25 **              semflg -- flag for semget(), if 0, use a default.
26 **              owner -- create semaphores.
27 **
28 **      Returns:
29 **              id for semaphores.
30 **              < 0 on failure.
31 */
32
33 int
34 sm_sem_start(key, nsem, semflg, owner)
35         key_t key;
36         int nsem;
37         int semflg;
38         bool owner;
39 {
40         int semid, i;
41         unsigned short *semvals;
42
43         semvals = NULL;
44         if (semflg == 0)
45                 semflg = (SEM_A|SEM_R)|((SEM_A|SEM_R) >> 3);
46         if (owner)
47                 semflg |= IPC_CREAT|IPC_EXCL;
48         semid = semget(key, nsem, semflg);
49         if (semid < 0)
50                 goto error;
51
52         if (owner)
53         {
54                 union semun semarg;
55
56                 semvals = (unsigned short *) sm_malloc(nsem * sizeof semvals);
57                 if (semvals == NULL)
58                         goto error;
59                 semarg.array = semvals;
60
61                 /* initialize semaphore values to be available */
62                 for (i = 0; i < nsem; i++)
63                         semvals[i] = 1;
64                 if (semctl(semid, 0, SETALL, semarg) < 0)
65                         goto error;
66         }
67         return semid;
68
69 error:
70         if (semvals != NULL)
71                 sm_free(semvals);
72         if (semid >= 0)
73                 sm_sem_stop(semid);
74         return -1;
75 }
76
77 /*
78 **  SM_SEM_STOP -- stop using semaphores.
79 **
80 **      Parameters:
81 **              semid -- id for semaphores.
82 **
83 **      Returns:
84 **              0 on success.
85 **              < 0 on failure.
86 */
87
88 int
89 sm_sem_stop(semid)
90         int semid;
91 {
92         return semctl(semid, 0, IPC_RMID, NULL);
93 }
94
95 /*
96 **  SM_SEM_ACQ -- acquire semaphore.
97 **
98 **      Parameters:
99 **              semid -- id for semaphores.
100 **              semnum -- number of semaphore.
101 **              timeout -- how long to wait for operation to succeed.
102 **
103 **      Returns:
104 **              0 on success.
105 **              < 0 on failure.
106 */
107
108 int
109 sm_sem_acq(semid, semnum, timeout)
110         int semid;
111         int semnum;
112         int timeout;
113 {
114         int r;
115         struct sembuf semops[1];
116
117         semops[0].sem_num = semnum;
118         semops[0].sem_op = -1;
119         semops[0].sem_flg = SEM_UNDO |
120                             (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT);
121         if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER)
122                 return semop(semid, semops, 1);
123         do
124         {
125                 r = semop(semid, semops, 1);
126                 if (r == 0)
127                         return r;
128                 sleep(1);
129                 --timeout;
130         } while (timeout > 0);
131         return r;
132 }
133
134 /*
135 **  SM_SEM_REL -- release semaphore.
136 **
137 **      Parameters:
138 **              semid -- id for semaphores.
139 **              semnum -- number of semaphore.
140 **              timeout -- how long to wait for operation to succeed.
141 **
142 **      Returns:
143 **              0 on success.
144 **              < 0 on failure.
145 */
146
147 int
148 sm_sem_rel(semid, semnum, timeout)
149         int semid;
150         int semnum;
151         int timeout;
152 {
153         int r;
154         struct sembuf semops[1];
155
156 #if PARANOID
157         /* XXX should we check whether the value is already 0 ? */
158         SM_REQUIRE(sm_get_sem(semid, semnum) > 0);
159 #endif /* PARANOID */
160
161         semops[0].sem_num = semnum;
162         semops[0].sem_op = 1;
163         semops[0].sem_flg = SEM_UNDO |
164                             (timeout != SM_TIME_FOREVER ? 0 : IPC_NOWAIT);
165         if (timeout == SM_TIME_IMMEDIATE || timeout == SM_TIME_FOREVER)
166                 return semop(semid, semops, 1);
167         do
168         {
169                 r = semop(semid, semops, 1);
170                 if (r == 0)
171                         return r;
172                 sleep(1);
173                 --timeout;
174         } while (timeout > 0);
175         return r;
176 }
177
178 /*
179 **  SM_SEM_GET -- get semaphore value.
180 **
181 **      Parameters:
182 **              semid -- id for semaphores.
183 **              semnum -- number of semaphore.
184 **
185 **      Returns:
186 **              value of semaphore on success.
187 **              < 0 on failure.
188 */
189
190 int
191 sm_sem_get(semid, semnum)
192         int semid;
193         int semnum;
194 {
195         int semval;
196
197         if ((semval = semctl(semid, semnum, GETVAL, NULL)) < 0)
198                 return -1;
199         return semval;
200 }
201 #endif /* SM_CONF_SEM */