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