summaryrefslogtreecommitdiff
path: root/contrib/sendmail/libsm/t-sem.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/libsm/t-sem.c')
-rw-r--r--contrib/sendmail/libsm/t-sem.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/t-sem.c b/contrib/sendmail/libsm/t-sem.c
new file mode 100644
index 000000000000..3964327017e3
--- /dev/null
+++ b/contrib/sendmail/libsm/t-sem.c
@@ -0,0 +1,344 @@
+/*
+ * 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.
+ */
+
+#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 */