t-sem.c revision 147078
1147078Sgshapiro/*
2147078Sgshapiro * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3147078Sgshapiro *      All rights reserved.
4147078Sgshapiro *
5147078Sgshapiro * By using this file, you agree to the terms and conditions set
6147078Sgshapiro * forth in the LICENSE file which can be found at the top level of
7147078Sgshapiro * the sendmail distribution.
8147078Sgshapiro */
9147078Sgshapiro
10147078Sgshapiro#include <sm/gen.h>
11147078SgshapiroSM_RCSID("@(#)$Id: t-sem.c,v 1.14 2005/03/25 21:27:41 ca Exp $")
12147078Sgshapiro
13147078Sgshapiro#include <stdio.h>
14147078Sgshapiro
15147078Sgshapiro#if SM_CONF_SEM
16147078Sgshapiro# include <stdlib.h>
17147078Sgshapiro# include <unistd.h>
18147078Sgshapiro# include <sysexits.h>
19147078Sgshapiro# include <sm/heap.h>
20147078Sgshapiro# include <sm/string.h>
21147078Sgshapiro# include <sm/signal.h>
22147078Sgshapiro# include <sm/test.h>
23147078Sgshapiro# include <sm/sem.h>
24147078Sgshapiro
25147078Sgshapirostatic void
26147078Sgshapirodelay(t, s)
27147078Sgshapiro	int t;
28147078Sgshapiro	char *s;
29147078Sgshapiro{
30147078Sgshapiro	if (t > 0)
31147078Sgshapiro	{
32147078Sgshapiro#if DEBUG
33147078Sgshapiro		fprintf(stderr, "sleep(%d) before %s\n", t, s);
34147078Sgshapiro#endif /* DEBUG */
35147078Sgshapiro		sleep(t);
36147078Sgshapiro	}
37147078Sgshapiro#if DEBUG
38147078Sgshapiro	fprintf(stderr, "%s\n", s);
39147078Sgshapiro#endif /* DEBUG */
40147078Sgshapiro}
41147078Sgshapiro
42147078Sgshapiro
43147078Sgshapiro/*
44147078Sgshapiro**  SEMINTER -- interactive testing of semaphores.
45147078Sgshapiro**
46147078Sgshapiro**	Parameters:
47147078Sgshapiro**		owner -- create semaphores.
48147078Sgshapiro**
49147078Sgshapiro**	Returns:
50147078Sgshapiro**		0 on success
51147078Sgshapiro**		< 0 on failure.
52147078Sgshapiro*/
53147078Sgshapiro
54147078Sgshapirostatic int
55147078Sgshapiroseminter(owner)
56147078Sgshapiro	bool owner;
57147078Sgshapiro{
58147078Sgshapiro	int semid;
59147078Sgshapiro	int t;
60147078Sgshapiro
61147078Sgshapiro	semid = sm_sem_start(SM_SEM_KEY, SM_NSEM, 0, owner);
62147078Sgshapiro	if (semid < 0)
63147078Sgshapiro	{
64147078Sgshapiro		perror("sm_sem_start failed");
65147078Sgshapiro		return 1;
66147078Sgshapiro	}
67147078Sgshapiro
68147078Sgshapiro	while ((t = getchar()) != EOF)
69147078Sgshapiro	{
70147078Sgshapiro		switch (t)
71147078Sgshapiro		{
72147078Sgshapiro		  case 'a':
73147078Sgshapiro			delay(0, "try to acq");
74147078Sgshapiro			if (sm_sem_acq(semid, 0, 2) < 0)
75147078Sgshapiro			{
76147078Sgshapiro				perror("sm_sem_acq failed");
77147078Sgshapiro				return 1;
78147078Sgshapiro			}
79147078Sgshapiro			delay(0, "acquired");
80147078Sgshapiro			break;
81147078Sgshapiro
82147078Sgshapiro		  case 'r':
83147078Sgshapiro			delay(0, "try to rel");
84147078Sgshapiro			if (sm_sem_rel(semid, 0, 2) < 0)
85147078Sgshapiro			{
86147078Sgshapiro				perror("sm_sem_rel failed");
87147078Sgshapiro				return 1;
88147078Sgshapiro			}
89147078Sgshapiro			delay(0, "released");
90147078Sgshapiro			break;
91147078Sgshapiro
92147078Sgshapiro		  case 'v':
93147078Sgshapiro			if ((t = sm_sem_get(semid, 0)) < 0)
94147078Sgshapiro			{
95147078Sgshapiro				perror("get_sem failed");
96147078Sgshapiro				return 1;
97147078Sgshapiro			}
98147078Sgshapiro			printf("semval: %d\n", t);
99147078Sgshapiro			break;
100147078Sgshapiro
101147078Sgshapiro		}
102147078Sgshapiro	}
103147078Sgshapiro	if (owner)
104147078Sgshapiro		return sm_sem_stop(semid);
105147078Sgshapiro	return 0;
106147078Sgshapiro}
107147078Sgshapiro
108147078Sgshapiro/*
109147078Sgshapiro**  SEM_CLEANUP -- cleanup if something breaks
110147078Sgshapiro**
111147078Sgshapiro**	Parameters:
112147078Sgshapiro**		sig -- signal.
113147078Sgshapiro**
114147078Sgshapiro**	Returns:
115147078Sgshapiro**		none.
116147078Sgshapiro*/
117147078Sgshapiro
118147078Sgshapirostatic int semid_c = -1;
119147078Sgshapirovoid
120147078Sgshapirosem_cleanup(sig)
121147078Sgshapiro	int sig;
122147078Sgshapiro{
123147078Sgshapiro	if (semid_c >= 0)
124147078Sgshapiro		(void) sm_sem_stop(semid_c);
125147078Sgshapiro	exit(EX_UNAVAILABLE);
126147078Sgshapiro}
127147078Sgshapiro
128147078Sgshapiro/*
129147078Sgshapiro**  SEMTEST -- test of semaphores
130147078Sgshapiro**
131147078Sgshapiro**	Parameters:
132147078Sgshapiro**		owner -- create semaphores.
133147078Sgshapiro**
134147078Sgshapiro**	Returns:
135147078Sgshapiro**		0 on success
136147078Sgshapiro**		< 0 on failure.
137147078Sgshapiro*/
138147078Sgshapiro
139147078Sgshapiro# define MAX_CNT	10
140147078Sgshapiro
141147078Sgshapirostatic int
142147078Sgshapirosemtest(owner)
143147078Sgshapiro	int owner;
144147078Sgshapiro{
145147078Sgshapiro	int semid, r;
146147078Sgshapiro	int cnt = 0;
147147078Sgshapiro
148147078Sgshapiro	semid = sm_sem_start(SM_SEM_KEY, 1, 0, owner);
149147078Sgshapiro	if (semid < 0)
150147078Sgshapiro	{
151147078Sgshapiro		perror("sm_sem_start failed");
152147078Sgshapiro		return -1;
153147078Sgshapiro	}
154147078Sgshapiro
155147078Sgshapiro	if (owner)
156147078Sgshapiro	{
157147078Sgshapiro		/* just in case someone kills the program... */
158147078Sgshapiro		semid_c = semid;
159147078Sgshapiro		(void) sm_signal(SIGHUP, sem_cleanup);
160147078Sgshapiro		(void) sm_signal(SIGINT, sem_cleanup);
161147078Sgshapiro		(void) sm_signal(SIGTERM, sem_cleanup);
162147078Sgshapiro
163147078Sgshapiro		delay(1, "parent: acquire 1");
164147078Sgshapiro		cnt = 0;
165147078Sgshapiro		do
166147078Sgshapiro		{
167147078Sgshapiro			r = sm_sem_acq(semid, 0, 0);
168147078Sgshapiro			if (r < 0)
169147078Sgshapiro			{
170147078Sgshapiro				sleep(1);
171147078Sgshapiro				++cnt;
172147078Sgshapiro			}
173147078Sgshapiro		} while (r < 0 && cnt <= MAX_CNT);
174147078Sgshapiro		SM_TEST(r >= 0);
175147078Sgshapiro		if (r < 0)
176147078Sgshapiro			return r;
177147078Sgshapiro
178147078Sgshapiro		delay(3, "parent: release 1");
179147078Sgshapiro		cnt = 0;
180147078Sgshapiro		do
181147078Sgshapiro		{
182147078Sgshapiro			r = sm_sem_rel(semid, 0, 0);
183147078Sgshapiro			if (r < 0)
184147078Sgshapiro			{
185147078Sgshapiro				sleep(1);
186147078Sgshapiro				++cnt;
187147078Sgshapiro			}
188147078Sgshapiro		} while (r < 0 && cnt <= MAX_CNT);
189147078Sgshapiro		SM_TEST(r >= 0);
190147078Sgshapiro		if (r < 0)
191147078Sgshapiro			return r;
192147078Sgshapiro
193147078Sgshapiro		delay(1, "parent: getval");
194147078Sgshapiro		cnt = 0;
195147078Sgshapiro		do
196147078Sgshapiro		{
197147078Sgshapiro			r = sm_sem_get(semid, 0);
198147078Sgshapiro			if (r <= 0)
199147078Sgshapiro			{
200147078Sgshapiro				sleep(1);
201147078Sgshapiro				++cnt;
202147078Sgshapiro			}
203147078Sgshapiro		} while (r <= 0 && cnt <= MAX_CNT);
204147078Sgshapiro		SM_TEST(r > 0);
205147078Sgshapiro		if (r <= 0)
206147078Sgshapiro			return r;
207147078Sgshapiro
208147078Sgshapiro		delay(1, "parent: acquire 2");
209147078Sgshapiro		cnt = 0;
210147078Sgshapiro		do
211147078Sgshapiro		{
212147078Sgshapiro			r = sm_sem_acq(semid, 0, 0);
213147078Sgshapiro			if (r < 0)
214147078Sgshapiro			{
215147078Sgshapiro				sleep(1);
216147078Sgshapiro				++cnt;
217147078Sgshapiro			}
218147078Sgshapiro		} while (r < 0 && cnt <= MAX_CNT);
219147078Sgshapiro		SM_TEST(r >= 0);
220147078Sgshapiro		if (r < 0)
221147078Sgshapiro			return r;
222147078Sgshapiro
223147078Sgshapiro		cnt = 0;
224147078Sgshapiro		do
225147078Sgshapiro		{
226147078Sgshapiro			r = sm_sem_rel(semid, 0, 0);
227147078Sgshapiro			if (r < 0)
228147078Sgshapiro			{
229147078Sgshapiro				sleep(1);
230147078Sgshapiro				++cnt;
231147078Sgshapiro			}
232147078Sgshapiro		} while (r < 0 && cnt <= MAX_CNT);
233147078Sgshapiro		SM_TEST(r >= 0);
234147078Sgshapiro		if (r < 0)
235147078Sgshapiro			return r;
236147078Sgshapiro	}
237147078Sgshapiro	else
238147078Sgshapiro	{
239147078Sgshapiro		delay(1, "child: acquire 1");
240147078Sgshapiro		cnt = 0;
241147078Sgshapiro		do
242147078Sgshapiro		{
243147078Sgshapiro			r = sm_sem_acq(semid, 0, 0);
244147078Sgshapiro			if (r < 0)
245147078Sgshapiro			{
246147078Sgshapiro				sleep(1);
247147078Sgshapiro				++cnt;
248147078Sgshapiro			}
249147078Sgshapiro		} while (r < 0 && cnt <= MAX_CNT);
250147078Sgshapiro		SM_TEST(r >= 0);
251147078Sgshapiro		if (r < 0)
252147078Sgshapiro			return r;
253147078Sgshapiro
254147078Sgshapiro		delay(1, "child: release 1");
255147078Sgshapiro		cnt = 0;
256147078Sgshapiro		do
257147078Sgshapiro		{
258147078Sgshapiro			r = sm_sem_rel(semid, 0, 0);
259147078Sgshapiro			if (r < 0)
260147078Sgshapiro			{
261147078Sgshapiro				sleep(1);
262147078Sgshapiro				++cnt;
263147078Sgshapiro			}
264147078Sgshapiro		} while (r < 0 && cnt <= MAX_CNT);
265147078Sgshapiro		SM_TEST(r >= 0);
266147078Sgshapiro		if (r < 0)
267147078Sgshapiro			return r;
268147078Sgshapiro
269147078Sgshapiro	}
270147078Sgshapiro	if (owner)
271147078Sgshapiro		return sm_sem_stop(semid);
272147078Sgshapiro	return 0;
273147078Sgshapiro}
274147078Sgshapiro
275147078Sgshapiroint
276147078Sgshapiromain(argc, argv)
277147078Sgshapiro	int argc;
278147078Sgshapiro	char *argv[];
279147078Sgshapiro{
280147078Sgshapiro	bool interactive = false;
281147078Sgshapiro	bool owner = false;
282147078Sgshapiro	int ch;
283147078Sgshapiro	int r = 0;
284147078Sgshapiro
285147078Sgshapiro# define OPTIONS	"io"
286147078Sgshapiro	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
287147078Sgshapiro	{
288147078Sgshapiro		switch ((char) ch)
289147078Sgshapiro		{
290147078Sgshapiro		  case 'i':
291147078Sgshapiro			interactive = true;
292147078Sgshapiro			break;
293147078Sgshapiro
294147078Sgshapiro		  case 'o':
295147078Sgshapiro			owner = true;
296147078Sgshapiro			break;
297147078Sgshapiro
298147078Sgshapiro		  default:
299147078Sgshapiro			break;
300147078Sgshapiro		}
301147078Sgshapiro	}
302147078Sgshapiro
303147078Sgshapiro	if (interactive)
304147078Sgshapiro		r = seminter(owner);
305147078Sgshapiro	else
306147078Sgshapiro	{
307147078Sgshapiro		pid_t pid;
308147078Sgshapiro
309147078Sgshapiro		printf("This test takes about 8 seconds.\n");
310147078Sgshapiro		printf("If it takes longer than 30 second, please interrupt it\n");
311147078Sgshapiro		printf("and compile again without semaphore support, i.e.,");
312147078Sgshapiro		printf("-DSM_CONF_SEM=0\n");
313147078Sgshapiro		if ((pid = fork()) < 0)
314147078Sgshapiro		{
315147078Sgshapiro			perror("fork failed\n");
316147078Sgshapiro			return -1;
317147078Sgshapiro		}
318147078Sgshapiro
319147078Sgshapiro		sm_test_begin(argc, argv, "test semaphores");
320147078Sgshapiro		if (pid == 0)
321147078Sgshapiro		{
322147078Sgshapiro			/* give the parent the chance to setup data */
323147078Sgshapiro			sleep(1);
324147078Sgshapiro			r = semtest(false);
325147078Sgshapiro		}
326147078Sgshapiro		else
327147078Sgshapiro		{
328147078Sgshapiro			r = semtest(true);
329147078Sgshapiro		}
330147078Sgshapiro		SM_TEST(r == 0);
331147078Sgshapiro		return sm_test_end();
332147078Sgshapiro	}
333147078Sgshapiro	return r;
334147078Sgshapiro}
335147078Sgshapiro#else /* SM_CONF_SEM */
336147078Sgshapiroint
337147078Sgshapiromain(argc, argv)
338147078Sgshapiro	int argc;
339147078Sgshapiro	char *argv[];
340147078Sgshapiro{
341147078Sgshapiro	printf("No support for semaphores configured on this machine\n");
342147078Sgshapiro	return 0;
343147078Sgshapiro}
344147078Sgshapiro#endif /* SM_CONF_SEM */
345