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