t-sem.c revision 147078
115103Sphk/*
215103Sphk * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
315103Sphk *      All rights reserved.
415103Sphk *
515103Sphk * By using this file, you agree to the terms and conditions set
615103Sphk * forth in the LICENSE file which can be found at the top level of
715103Sphk * the sendmail distribution.
815103Sphk */
915103Sphk
1015103Sphk#include <sm/gen.h>
1115103SphkSM_RCSID("@(#)$Id: t-sem.c,v 1.14 2005/03/25 21:27:41 ca Exp $")
1215103Sphk
1315103Sphk#include <stdio.h>
1415103Sphk
1515103Sphk#if SM_CONF_SEM
1615103Sphk# include <stdlib.h>
1715103Sphk# include <unistd.h>
1815103Sphk# include <sysexits.h>
1915103Sphk# include <sm/heap.h>
2015103Sphk# include <sm/string.h>
2115103Sphk# include <sm/signal.h>
2215103Sphk# include <sm/test.h>
2315103Sphk# include <sm/sem.h>
2415103Sphk
2515103Sphkstatic void
2615103Sphkdelay(t, s)
2715103Sphk	int t;
2815103Sphk	char *s;
2915103Sphk{
3015103Sphk	if (t > 0)
3115103Sphk	{
3215103Sphk#if DEBUG
3315103Sphk		fprintf(stderr, "sleep(%d) before %s\n", t, s);
3415103Sphk#endif /* DEBUG */
3515103Sphk		sleep(t);
3615103Sphk	}
3715103Sphk#if DEBUG
3815103Sphk	fprintf(stderr, "%s\n", s);
3915103Sphk#endif /* DEBUG */
4050477Speter}
4115103Sphk
4215103Sphk
4315103Sphk/*
4415103Sphk**  SEMINTER -- interactive testing of semaphores.
4515103Sphk**
4615103Sphk**	Parameters:
4715103Sphk**		owner -- create semaphores.
4846155Sphk**
4931990Sgpalmer**	Returns:
5028918Skato**		0 on success
5115103Sphk**		< 0 on failure.
5215103Sphk*/
5315103Sphk
5415103Sphkstatic int
5515103Sphkseminter(owner)
5615103Sphk	bool owner;
5723382Sbde{
5815103Sphk	int semid;
5915103Sphk	int t;
6015103Sphk
6115103Sphk	semid = sm_sem_start(SM_SEM_KEY, SM_NSEM, 0, owner);
6215103Sphk	if (semid < 0)
6348891Sphk	{
6448891Sphk		perror("sm_sem_start failed");
6515103Sphk		return 1;
6615103Sphk	}
6715103Sphk
6815103Sphk	while ((t = getchar()) != EOF)
6915103Sphk	{
7015103Sphk		switch (t)
7134925Sdufault		{
7234925Sdufault		  case 'a':
7334029Sdufault			delay(0, "try to acq");
7450465Smarcel			if (sm_sem_acq(semid, 0, 2) < 0)
7550465Smarcel			{
7650465Smarcel				perror("sm_sem_acq failed");
7746381Sbillf				return 1;
7846381Sbillf			}
7915103Sphk			delay(0, "acquired");
8046381Sbillf			break;
8146381Sbillf
8215103Sphk		  case 'r':
8346381Sbillf			delay(0, "try to rel");
8446381Sbillf			if (sm_sem_rel(semid, 0, 2) < 0)
8515103Sphk			{
8646381Sbillf				perror("sm_sem_rel failed");
8746381Sbillf				return 1;
8815103Sphk			}
8915103Sphk			delay(0, "released");
9046381Sbillf			break;
9146381Sbillf
9215103Sphk		  case 'v':
9346381Sbillf			if ((t = sm_sem_get(semid, 0)) < 0)
9446381Sbillf			{
9515103Sphk				perror("get_sem failed");
9646381Sbillf				return 1;
9746381Sbillf			}
9815103Sphk			printf("semval: %d\n", t);
9946381Sbillf			break;
10046381Sbillf
10115103Sphk		}
10246381Sbillf	}
10346381Sbillf	if (owner)
10415103Sphk		return sm_sem_stop(semid);
10546381Sbillf	return 0;
10646381Sbillf}
10715103Sphk
10846381Sbillf/*
10946381Sbillf**  SEM_CLEANUP -- cleanup if something breaks
11015103Sphk**
11115103Sphk**	Parameters:
11246381Sbillf**		sig -- signal.
11346381Sbillf**
11415103Sphk**	Returns:
11546381Sbillf**		none.
11646381Sbillf*/
11715103Sphk
11815103Sphkstatic int semid_c = -1;
11915103Sphkvoid
12015103Sphksem_cleanup(sig)
12146381Sbillf	int sig;
12246381Sbillf{
12315103Sphk	if (semid_c >= 0)
12431990Sgpalmer		(void) sm_sem_stop(semid_c);
12546381Sbillf	exit(EX_UNAVAILABLE);
12646381Sbillf}
12731990Sgpalmer
12846381Sbillf/*
12946381Sbillf**  SEMTEST -- test of semaphores
13031990Sgpalmer**
13115103Sphk**	Parameters:
13246381Sbillf**		owner -- create semaphores.
13346381Sbillf**
13415103Sphk**	Returns:
13546381Sbillf**		0 on success
13646381Sbillf**		< 0 on failure.
13715103Sphk*/
13828885Skato
13928885Skato# define MAX_CNT	10
14046381Sbillf
14128885Skatostatic int
14215103Sphksemtest(owner)
14315103Sphk	int owner;
14446155Sphk{
14562573Sphk	int semid, r;
14646155Sphk	int cnt = 0;
14746155Sphk
14815103Sphk	semid = sm_sem_start(SM_SEM_KEY, 1, 0, owner);
14957111Srwatson	if (semid < 0)
15057163Srwatson	{
15157111Srwatson		perror("sm_sem_start failed");
15246155Sphk		return -1;
15346155Sphk	}
15446155Sphk
15557111Srwatson	if (owner)
15646155Sphk	{
15746155Sphk		/* just in case someone kills the program... */
15846155Sphk		semid_c = semid;
15946155Sphk		(void) sm_signal(SIGHUP, sem_cleanup);
16046155Sphk		(void) sm_signal(SIGINT, sem_cleanup);
16146155Sphk		(void) sm_signal(SIGTERM, sem_cleanup);
16246155Sphk
16346381Sbillf		delay(1, "parent: acquire 1");
16446155Sphk		cnt = 0;
16515103Sphk		do
16615103Sphk		{
16715103Sphk			r = sm_sem_acq(semid, 0, 0);
16862573Sphk			if (r < 0)
16915103Sphk			{
17015103Sphk				sleep(1);
17115103Sphk				++cnt;
17215103Sphk			}
17315103Sphk		} while (r < 0 && cnt <= MAX_CNT);
17415103Sphk		SM_TEST(r >= 0);
17515103Sphk		if (r < 0)
17626923Sjoerg			return r;
17715103Sphk
17815103Sphk		delay(3, "parent: release 1");
17915103Sphk		cnt = 0;
18015103Sphk		do
18115103Sphk		{
18261370Srwatson			r = sm_sem_rel(semid, 0, 0);
18361370Srwatson			if (r < 0)
18461370Srwatson			{
18515103Sphk				sleep(1);
18617281Swollman				++cnt;
18746381Sbillf			}
18815103Sphk		} while (r < 0 && cnt <= MAX_CNT);
18915103Sphk		SM_TEST(r >= 0);
19015103Sphk		if (r < 0)
19146381Sbillf			return r;
19215103Sphk
19315103Sphk		delay(1, "parent: getval");
19415103Sphk		cnt = 0;
19515103Sphk		do
19615103Sphk		{
19715103Sphk			r = sm_sem_get(semid, 0);
19846381Sbillf			if (r <= 0)
19946381Sbillf			{
20046381Sbillf				sleep(1);
20146381Sbillf				++cnt;
20246381Sbillf			}
20346381Sbillf		} while (r <= 0 && cnt <= MAX_CNT);
20446381Sbillf		SM_TEST(r > 0);
20546381Sbillf		if (r <= 0)
20646381Sbillf			return r;
20746381Sbillf
20846381Sbillf		delay(1, "parent: acquire 2");
20946381Sbillf		cnt = 0;
21018540Sbde		do
21146381Sbillf		{
21246381Sbillf			r = sm_sem_acq(semid, 0, 0);
21346381Sbillf			if (r < 0)
21446381Sbillf			{
21546381Sbillf				sleep(1);
21646381Sbillf				++cnt;
21746381Sbillf			}
21846381Sbillf		} while (r < 0 && cnt <= MAX_CNT);
21946381Sbillf		SM_TEST(r >= 0);
22046381Sbillf		if (r < 0)
22146381Sbillf			return r;
22246381Sbillf
22346381Sbillf		cnt = 0;
22446381Sbillf		do
22546381Sbillf		{
22646381Sbillf			r = sm_sem_rel(semid, 0, 0);
22746381Sbillf			if (r < 0)
22846381Sbillf			{
22946381Sbillf				sleep(1);
23046381Sbillf				++cnt;
23146381Sbillf			}
23246381Sbillf		} while (r < 0 && cnt <= MAX_CNT);
23346381Sbillf		SM_TEST(r >= 0);
23446381Sbillf		if (r < 0)
23546381Sbillf			return r;
23646381Sbillf	}
23746381Sbillf	else
23848891Sphk	{
23948891Sphk		delay(1, "child: acquire 1");
24048891Sphk		cnt = 0;
24148891Sphk		do
24248891Sphk		{
24348891Sphk			r = sm_sem_acq(semid, 0, 0);
24448891Sphk			if (r < 0)
24548927Sphk			{
24649535Sphk				sleep(1);
24748927Sphk				++cnt;
24848927Sphk			}
24958926Sphk		} while (r < 0 && cnt <= MAX_CNT);
25060041Sphk		SM_TEST(r >= 0);
25158926Sphk		if (r < 0)
25258926Sphk			return r;
25358926Sphk
25458926Sphk		delay(1, "child: release 1");
25558926Sphk		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 second, 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