t-sem.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sm/gen.h>
SM_RCSID("@(#)$Id: t-sem.c,v 1.14 2005/03/25 21:27:41 ca Exp $")
#include <stdio.h>
#if SM_CONF_SEM
# include <stdlib.h>
# include <unistd.h>
# include <sysexits.h>
# include <sm/heap.h>
# include <sm/string.h>
# include <sm/signal.h>
# include <sm/test.h>
# include <sm/sem.h>
static void
delay(t, s)
int t;
char *s;
{
if (t > 0)
{
#if DEBUG
fprintf(stderr, "sleep(%d) before %s\n", t, s);
#endif /* DEBUG */
sleep(t);
}
#if DEBUG
fprintf(stderr, "%s\n", s);
#endif /* DEBUG */
}
/*
** SEMINTER -- interactive testing of semaphores.
**
** Parameters:
** owner -- create semaphores.
**
** Returns:
** 0 on success
** < 0 on failure.
*/
static int
seminter(owner)
bool owner;
{
int semid;
int t;
semid = sm_sem_start(SM_SEM_KEY, SM_NSEM, 0, owner);
if (semid < 0)
{
perror("sm_sem_start failed");
return 1;
}
while ((t = getchar()) != EOF)
{
switch (t)
{
case 'a':
delay(0, "try to acq");
if (sm_sem_acq(semid, 0, 2) < 0)
{
perror("sm_sem_acq failed");
return 1;
}
delay(0, "acquired");
break;
case 'r':
delay(0, "try to rel");
if (sm_sem_rel(semid, 0, 2) < 0)
{
perror("sm_sem_rel failed");
return 1;
}
delay(0, "released");
break;
case 'v':
if ((t = sm_sem_get(semid, 0)) < 0)
{
perror("get_sem failed");
return 1;
}
printf("semval: %d\n", t);
break;
}
}
if (owner)
return sm_sem_stop(semid);
return 0;
}
/*
** SEM_CLEANUP -- cleanup if something breaks
**
** Parameters:
** sig -- signal.
**
** Returns:
** none.
*/
static int semid_c = -1;
void
sem_cleanup(sig)
int sig;
{
if (semid_c >= 0)
(void) sm_sem_stop(semid_c);
exit(EX_UNAVAILABLE);
}
/*
** SEMTEST -- test of semaphores
**
** Parameters:
** owner -- create semaphores.
**
** Returns:
** 0 on success
** < 0 on failure.
*/
# define MAX_CNT 10
static int
semtest(owner)
int owner;
{
int semid, r;
int cnt = 0;
semid = sm_sem_start(SM_SEM_KEY, 1, 0, owner);
if (semid < 0)
{
perror("sm_sem_start failed");
return -1;
}
if (owner)
{
/* just in case someone kills the program... */
semid_c = semid;
(void) sm_signal(SIGHUP, sem_cleanup);
(void) sm_signal(SIGINT, sem_cleanup);
(void) sm_signal(SIGTERM, sem_cleanup);
delay(1, "parent: acquire 1");
cnt = 0;
do
{
r = sm_sem_acq(semid, 0, 0);
if (r < 0)
{
sleep(1);
++cnt;
}
} while (r < 0 && cnt <= MAX_CNT);
SM_TEST(r >= 0);
if (r < 0)
return r;
delay(3, "parent: release 1");
cnt = 0;
do
{
r = sm_sem_rel(semid, 0, 0);
if (r < 0)
{
sleep(1);
++cnt;
}
} while (r < 0 && cnt <= MAX_CNT);
SM_TEST(r >= 0);
if (r < 0)
return r;
delay(1, "parent: getval");
cnt = 0;
do
{
r = sm_sem_get(semid, 0);
if (r <= 0)
{
sleep(1);
++cnt;
}
} while (r <= 0 && cnt <= MAX_CNT);
SM_TEST(r > 0);
if (r <= 0)
return r;
delay(1, "parent: acquire 2");
cnt = 0;
do
{
r = sm_sem_acq(semid, 0, 0);
if (r < 0)
{
sleep(1);
++cnt;
}
} while (r < 0 && cnt <= MAX_CNT);
SM_TEST(r >= 0);
if (r < 0)
return r;
cnt = 0;
do
{
r = sm_sem_rel(semid, 0, 0);
if (r < 0)
{
sleep(1);
++cnt;
}
} while (r < 0 && cnt <= MAX_CNT);
SM_TEST(r >= 0);
if (r < 0)
return r;
}
else
{
delay(1, "child: acquire 1");
cnt = 0;
do
{
r = sm_sem_acq(semid, 0, 0);
if (r < 0)
{
sleep(1);
++cnt;
}
} while (r < 0 && cnt <= MAX_CNT);
SM_TEST(r >= 0);
if (r < 0)
return r;
delay(1, "child: release 1");
cnt = 0;
do
{
r = sm_sem_rel(semid, 0, 0);
if (r < 0)
{
sleep(1);
++cnt;
}
} while (r < 0 && cnt <= MAX_CNT);
SM_TEST(r >= 0);
if (r < 0)
return r;
}
if (owner)
return sm_sem_stop(semid);
return 0;
}
int
main(argc, argv)
int argc;
char *argv[];
{
bool interactive = false;
bool owner = false;
int ch;
int r = 0;
# define OPTIONS "io"
while ((ch = getopt(argc, argv, OPTIONS)) != -1)
{
switch ((char) ch)
{
case 'i':
interactive = true;
break;
case 'o':
owner = true;
break;
default:
break;
}
}
if (interactive)
r = seminter(owner);
else
{
pid_t pid;
printf("This test takes about 8 seconds.\n");
printf("If it takes longer than 30 second, please interrupt it\n");
printf("and compile again without semaphore support, i.e.,");
printf("-DSM_CONF_SEM=0\n");
if ((pid = fork()) < 0)
{
perror("fork failed\n");
return -1;
}
sm_test_begin(argc, argv, "test semaphores");
if (pid == 0)
{
/* give the parent the chance to setup data */
sleep(1);
r = semtest(false);
}
else
{
r = semtest(true);
}
SM_TEST(r == 0);
return sm_test_end();
}
return r;
}
#else /* SM_CONF_SEM */
int
main(argc, argv)
int argc;
char *argv[];
{
printf("No support for semaphores configured on this machine\n");
return 0;
}
#endif /* SM_CONF_SEM */