xref: /illumos-gate/usr/src/cmd/sendmail/libsm/t-sem.c (revision 4aac33d31b41cc7e3ac6fb66747ff2cae63d08cf)
1 /*
2  * Copyright (c) 2000-2001, 2005-2007 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
11 
12 #include <sm/gen.h>
13 SM_RCSID("@(#)$Id: t-sem.c,v 1.16 2007/03/21 23:22:10 ca Exp $")
14 
15 #include <stdio.h>
16 
17 #if SM_CONF_SEM
18 # include <stdlib.h>
19 # include <unistd.h>
20 # include <sysexits.h>
21 # include <sm/heap.h>
22 # include <sm/string.h>
23 # include <sm/signal.h>
24 # include <sm/test.h>
25 # include <sm/sem.h>
26 
27 # define T_SM_SEM_KEY (4321L)
28 
29 static void
30 delay(t, s)
31 	int t;
32 	char *s;
33 {
34 	if (t > 0)
35 	{
36 #if DEBUG
37 		fprintf(stderr, "sleep(%d) before %s\n", t, s);
38 #endif /* DEBUG */
39 		sleep(t);
40 	}
41 #if DEBUG
42 	fprintf(stderr, "%s\n", s);
43 #endif /* DEBUG */
44 }
45 
46 
47 /*
48 **  SEMINTER -- interactive testing of semaphores.
49 **
50 **	Parameters:
51 **		owner -- create semaphores.
52 **
53 **	Returns:
54 **		0 on success
55 **		< 0 on failure.
56 */
57 
58 static int
59 seminter(owner)
60 	bool owner;
61 {
62 	int semid;
63 	int t;
64 
65 	semid = sm_sem_start(T_SM_SEM_KEY, SM_NSEM, 0, owner);
66 	if (semid < 0)
67 	{
68 		perror("sm_sem_start failed");
69 		return 1;
70 	}
71 
72 	while ((t = getchar()) != EOF)
73 	{
74 		switch (t)
75 		{
76 		  case 'a':
77 			delay(0, "try to acq");
78 			if (sm_sem_acq(semid, 0, 2) < 0)
79 			{
80 				perror("sm_sem_acq failed");
81 				return 1;
82 			}
83 			delay(0, "acquired");
84 			break;
85 
86 		  case 'r':
87 			delay(0, "try to rel");
88 			if (sm_sem_rel(semid, 0, 2) < 0)
89 			{
90 				perror("sm_sem_rel failed");
91 				return 1;
92 			}
93 			delay(0, "released");
94 			break;
95 
96 		  case 'v':
97 			if ((t = sm_sem_get(semid, 0)) < 0)
98 			{
99 				perror("get_sem failed");
100 				return 1;
101 			}
102 			printf("semval: %d\n", t);
103 			break;
104 
105 		}
106 	}
107 	if (owner)
108 		return sm_sem_stop(semid);
109 	return 0;
110 }
111 
112 /*
113 **  SEM_CLEANUP -- cleanup if something breaks
114 **
115 **	Parameters:
116 **		sig -- signal.
117 **
118 **	Returns:
119 **		none.
120 */
121 
122 static int semid_c = -1;
123 void
124 sem_cleanup(sig)
125 	int sig;
126 {
127 	if (semid_c >= 0)
128 		(void) sm_sem_stop(semid_c);
129 	exit(EX_UNAVAILABLE);
130 }
131 
132 /*
133 **  SEMTEST -- test of semaphores
134 **
135 **	Parameters:
136 **		owner -- create semaphores.
137 **
138 **	Returns:
139 **		0 on success
140 **		< 0 on failure.
141 */
142 
143 # define MAX_CNT	10
144 
145 static int
146 semtest(owner)
147 	int owner;
148 {
149 	int semid, r;
150 	int cnt = 0;
151 
152 	semid = sm_sem_start(T_SM_SEM_KEY, 1, 0, owner);
153 	if (semid < 0)
154 	{
155 		perror("sm_sem_start failed");
156 		return -1;
157 	}
158 
159 	if (owner)
160 	{
161 		/* just in case someone kills the program... */
162 		semid_c = semid;
163 		(void) sm_signal(SIGHUP, sem_cleanup);
164 		(void) sm_signal(SIGINT, sem_cleanup);
165 		(void) sm_signal(SIGTERM, sem_cleanup);
166 
167 		delay(1, "parent: acquire 1");
168 		cnt = 0;
169 		do
170 		{
171 			r = sm_sem_acq(semid, 0, 0);
172 			if (r < 0)
173 			{
174 				sleep(1);
175 				++cnt;
176 			}
177 		} while (r < 0 && cnt <= MAX_CNT);
178 		SM_TEST(r >= 0);
179 		if (r < 0)
180 			return r;
181 
182 		delay(3, "parent: release 1");
183 		cnt = 0;
184 		do
185 		{
186 			r = sm_sem_rel(semid, 0, 0);
187 			if (r < 0)
188 			{
189 				sleep(1);
190 				++cnt;
191 			}
192 		} while (r < 0 && cnt <= MAX_CNT);
193 		SM_TEST(r >= 0);
194 		if (r < 0)
195 			return r;
196 
197 		delay(1, "parent: getval");
198 		cnt = 0;
199 		do
200 		{
201 			r = sm_sem_get(semid, 0);
202 			if (r <= 0)
203 			{
204 				sleep(1);
205 				++cnt;
206 			}
207 		} while (r <= 0 && cnt <= MAX_CNT);
208 		SM_TEST(r > 0);
209 		if (r <= 0)
210 			return r;
211 
212 		delay(1, "parent: acquire 2");
213 		cnt = 0;
214 		do
215 		{
216 			r = sm_sem_acq(semid, 0, 0);
217 			if (r < 0)
218 			{
219 				sleep(1);
220 				++cnt;
221 			}
222 		} while (r < 0 && cnt <= MAX_CNT);
223 		SM_TEST(r >= 0);
224 		if (r < 0)
225 			return r;
226 
227 		cnt = 0;
228 		do
229 		{
230 			r = sm_sem_rel(semid, 0, 0);
231 			if (r < 0)
232 			{
233 				sleep(1);
234 				++cnt;
235 			}
236 		} while (r < 0 && cnt <= MAX_CNT);
237 		SM_TEST(r >= 0);
238 		if (r < 0)
239 			return r;
240 	}
241 	else
242 	{
243 		delay(1, "child: acquire 1");
244 		cnt = 0;
245 		do
246 		{
247 			r = sm_sem_acq(semid, 0, 0);
248 			if (r < 0)
249 			{
250 				sleep(1);
251 				++cnt;
252 			}
253 		} while (r < 0 && cnt <= MAX_CNT);
254 		SM_TEST(r >= 0);
255 		if (r < 0)
256 			return r;
257 
258 		delay(1, "child: release 1");
259 		cnt = 0;
260 		do
261 		{
262 			r = sm_sem_rel(semid, 0, 0);
263 			if (r < 0)
264 			{
265 				sleep(1);
266 				++cnt;
267 			}
268 		} while (r < 0 && cnt <= MAX_CNT);
269 		SM_TEST(r >= 0);
270 		if (r < 0)
271 			return r;
272 
273 	}
274 	if (owner)
275 		return sm_sem_stop(semid);
276 	return 0;
277 }
278 
279 int
280 main(argc, argv)
281 	int argc;
282 	char *argv[];
283 {
284 	bool interactive = false;
285 	bool owner = false;
286 	int ch;
287 	int r = 0;
288 
289 # define OPTIONS	"io"
290 	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
291 	{
292 		switch ((char) ch)
293 		{
294 		  case 'i':
295 			interactive = true;
296 			break;
297 
298 		  case 'o':
299 			owner = true;
300 			break;
301 
302 		  default:
303 			break;
304 		}
305 	}
306 
307 	if (interactive)
308 		r = seminter(owner);
309 	else
310 	{
311 		pid_t pid;
312 
313 		printf("This test takes about 8 seconds.\n");
314 		printf("If it takes longer than 30 seconds, please interrupt it\n");
315 		printf("and compile again without semaphore support, i.e.,");
316 		printf("-DSM_CONF_SEM=0\n");
317 		if ((pid = fork()) < 0)
318 		{
319 			perror("fork failed\n");
320 			return -1;
321 		}
322 
323 		sm_test_begin(argc, argv, "test semaphores");
324 		if (pid == 0)
325 		{
326 			/* give the parent the chance to setup data */
327 			sleep(1);
328 			r = semtest(false);
329 		}
330 		else
331 		{
332 			r = semtest(true);
333 		}
334 		SM_TEST(r == 0);
335 		return sm_test_end();
336 	}
337 	return r;
338 }
339 #else /* SM_CONF_SEM */
340 int
341 main(argc, argv)
342 	int argc;
343 	char *argv[];
344 {
345 	printf("No support for semaphores configured on this machine\n");
346 	return 0;
347 }
348 #endif /* SM_CONF_SEM */
349