1 /* $FreeBSD$ */
2 
3 #include <sys/types.h>
4 #include <sys/wait.h>
5 #include <sys/mman.h>
6 #include <semaphore.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <err.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 
14 #define SEM_NAME "/semtst"
15 
16 int test_unnamed(void);
17 int test_named(void);
18 int test_named2(void);
19 
20 int
21 test_unnamed(void)
22 {
23 	sem_t *s;
24 	pid_t pid;
25 	int status;
26 
27 	printf("testing unnamed process-shared semaphore\n");
28 	s = (sem_t *)mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
29 		-1, 0);
30 	if (s == MAP_FAILED)
31 		err(1, "mmap failed");
32 	if (sem_init(s, 1, 0))
33 		err(2, "sem_init failed");
34 	if ((pid = fork()) == 0) {
35 		printf("child: sem_wait()\n");
36 		if (sem_wait(s))
37 			err(3, "sem_wait failed");
38 		printf("child: sem_wait() returned\n");
39 		exit(0);
40 	} else {
41 		sleep(1);
42 		printf("parent: sem_post()\n");
43 		if (sem_post(s))
44 			err(4, "sem_post failed");
45 		waitpid(pid, &status, 0);
46 		if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
47 			printf("OK.\n");
48 		else
49 			printf("Failure.");
50 	}
51 	return (0);
52 }
53 
54 int
55 test_named(void)
56 {
57 	sem_t *s, *s2;
58 	pid_t pid;
59 	int status;
60 
61 	printf("testing named process-shared semaphore\n");
62 	sem_unlink(SEM_NAME);
63 	s = sem_open(SEM_NAME, O_CREAT, 0777, 0);
64 	if (s == SEM_FAILED)
65 		err(1, "sem_open failed");
66 	s2 = sem_open(SEM_NAME, O_CREAT, 0777, 0);
67 	if (s2 == SEM_FAILED)
68 		err(2, "second sem_open call failed");
69 	if (s != s2)
70 		errx(3,
71 "two sem_open calls for same semaphore do not return same address");
72 	if (sem_close(s2))
73 		err(4, "sem_close failed");
74 	if ((pid = fork()) == 0) {
75 		printf("child: sem_wait()\n");
76 		if (sem_wait(s))
77 			err(5, "sem_wait failed");
78 		printf("child: sem_wait() returned\n");
79 		exit(0);
80 	} else {
81 		sleep(1);
82 		printf("parent: sem_post()\n");
83 		if (sem_post(s))
84 			err(6, "sem_post failed");
85 		waitpid(pid, &status, 0);
86 		if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
87 			printf("OK.\n");
88 		else
89 			printf("Failure.");
90 	}
91 
92 	if (sem_close(s))
93 		err(7, "sem_close failed");
94 
95 	return (0);
96 }
97 
98 int
99 test_named2(void)
100 {
101 	sem_t *s, *s2, *s3;
102 
103 	printf("testing named process-shared semaphore, O_EXCL cases\n");
104 	sem_unlink(SEM_NAME);
105 	s = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 0);
106 	if (s == SEM_FAILED)
107 		err(1, "sem_open failed");
108 	s2 = sem_open(SEM_NAME, O_CREAT | O_EXCL, 0777, 0);
109 	if (s2 != SEM_FAILED)
110 		errx(2, "second sem_open call wrongly succeeded");
111 	if (errno != EEXIST)
112 		err(3, "second sem_open call failed with wrong errno");
113 
114 	s3 = sem_open(SEM_NAME, 0);
115 	if (s3 == SEM_FAILED)
116 		err(4, "third sem_open call failed");
117 	if (s != s3)
118 		errx(5,
119 "two sem_open calls for same semaphore do not return same address");
120 	if (sem_close(s3))
121 		err(6, "sem_close failed");
122 
123 	if (sem_close(s))
124 		err(7, "sem_close failed");
125 
126 	printf("OK.\n");
127 	return (0);
128 }
129 
130 int
131 main(void)
132 {
133 	test_unnamed();
134 	test_named();
135 	test_named2();
136 	return (0);
137 }
138