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