sem.c revision 1.9 1 1.9 joerg /* $NetBSD: sem.c,v 1.9 2012/03/08 21:59:32 joerg Exp $ */
2 1.1 pooka
3 1.1 pooka /*
4 1.1 pooka * Common code for semaphore tests. This can be included both into
5 1.1 pooka * programs using librt and libpthread.
6 1.1 pooka */
7 1.1 pooka
8 1.1 pooka #include <sys/types.h>
9 1.1 pooka
10 1.1 pooka #include <rump/rump.h>
11 1.1 pooka #include <rump/rump_syscalls.h>
12 1.1 pooka
13 1.1 pooka #include <atf-c.h>
14 1.1 pooka #include <errno.h>
15 1.1 pooka #include <fcntl.h>
16 1.1 pooka #include <pthread.h>
17 1.1 pooka #include <semaphore.h>
18 1.1 pooka #include <sched.h>
19 1.1 pooka #include <stdint.h>
20 1.1 pooka #include <stdio.h>
21 1.1 pooka #include <stdlib.h>
22 1.1 pooka #include <unistd.h>
23 1.1 pooka
24 1.1 pooka #include "../../h_macros.h"
25 1.1 pooka
26 1.1 pooka ATF_TC(postwait);
27 1.1 pooka ATF_TC_HEAD(postwait, tc)
28 1.1 pooka {
29 1.1 pooka
30 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests post and wait from a "
31 1.1 pooka "single thread (%s)", LIBNAME);
32 1.1 pooka }
33 1.1 pooka
34 1.1 pooka ATF_TC_BODY(postwait, tc)
35 1.1 pooka {
36 1.1 pooka sem_t sem;
37 1.1 pooka int rv;
38 1.1 pooka
39 1.1 pooka rump_init();
40 1.1 pooka
41 1.1 pooka ATF_REQUIRE_EQ(sem_init(&sem, 1, 0), 0);
42 1.1 pooka
43 1.1 pooka sem_post(&sem);
44 1.1 pooka sem_post(&sem);
45 1.1 pooka
46 1.1 pooka sem_wait(&sem);
47 1.1 pooka sem_wait(&sem);
48 1.1 pooka rv = sem_trywait(&sem);
49 1.1 pooka ATF_REQUIRE(errno == EAGAIN);
50 1.1 pooka ATF_REQUIRE(rv == -1);
51 1.1 pooka }
52 1.1 pooka
53 1.1 pooka ATF_TC(initvalue);
54 1.1 pooka ATF_TC_HEAD(initvalue, tc)
55 1.1 pooka {
56 1.1 pooka
57 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests initialization with a non-zero "
58 1.1 pooka "value (%s)", LIBNAME);
59 1.1 pooka }
60 1.1 pooka
61 1.1 pooka ATF_TC_BODY(initvalue, tc)
62 1.1 pooka {
63 1.1 pooka sem_t sem;
64 1.1 pooka
65 1.1 pooka rump_init();
66 1.1 pooka sem_init(&sem, 1, 4);
67 1.1 pooka
68 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0);
69 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0);
70 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0);
71 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0);
72 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), -1);
73 1.1 pooka }
74 1.1 pooka
75 1.1 pooka ATF_TC(destroy);
76 1.1 pooka ATF_TC_HEAD(destroy, tc)
77 1.1 pooka {
78 1.1 pooka
79 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests sem_destroy works (%s)", LIBNAME);
80 1.1 pooka }
81 1.1 pooka
82 1.1 pooka ATF_TC_BODY(destroy, tc)
83 1.1 pooka {
84 1.1 pooka sem_t sem;
85 1.1 pooka int rv, i;
86 1.1 pooka
87 1.1 pooka rump_init();
88 1.1 pooka for (i = 0; i < 2; i++) {
89 1.1 pooka sem_init(&sem, 1, 1);
90 1.1 pooka
91 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0);
92 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), -1);
93 1.1 pooka ATF_REQUIRE_EQ(sem_destroy(&sem), 0);
94 1.1 pooka rv = sem_trywait(&sem);
95 1.1 pooka ATF_REQUIRE_EQ(errno, EINVAL);
96 1.1 pooka ATF_REQUIRE_EQ(rv, -1);
97 1.1 pooka }
98 1.1 pooka }
99 1.1 pooka
100 1.1 pooka ATF_TC(busydestroy);
101 1.1 pooka ATF_TC_HEAD(busydestroy, tc)
102 1.1 pooka {
103 1.1 pooka
104 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests sem_destroy report EBUSY for "
105 1.1 pooka "a busy semaphore (%s)", LIBNAME);
106 1.1 pooka }
107 1.1 pooka
108 1.1 pooka static void *
109 1.1 pooka hthread(void *arg)
110 1.1 pooka {
111 1.1 pooka sem_t *semmarit = arg;
112 1.1 pooka
113 1.1 pooka for (;;) {
114 1.1 pooka sem_post(&semmarit[2]);
115 1.1 pooka sem_wait(&semmarit[1]);
116 1.1 pooka sem_wait(&semmarit[0]);
117 1.1 pooka }
118 1.3 pooka
119 1.3 pooka return NULL;
120 1.1 pooka }
121 1.1 pooka
122 1.1 pooka ATF_TC_BODY(busydestroy, tc)
123 1.1 pooka {
124 1.1 pooka sem_t semmarit[3];
125 1.1 pooka pthread_t pt;
126 1.1 pooka int i;
127 1.1 pooka
128 1.1 pooka /* use a unicpu rump kernel. this means less chance for race */
129 1.1 pooka setenv("RUMP_NCPU", "1", 1);
130 1.1 pooka
131 1.1 pooka rump_init();
132 1.1 pooka sem_init(&semmarit[0], 1, 0);
133 1.1 pooka sem_init(&semmarit[1], 1, 0);
134 1.1 pooka sem_init(&semmarit[2], 1, 0);
135 1.1 pooka
136 1.1 pooka pthread_create(&pt, NULL, hthread, semmarit);
137 1.1 pooka
138 1.1 pooka /*
139 1.1 pooka * Make a best-effort to catch the other thread with its pants down.
140 1.1 pooka * We can't do this for sure, can we? Although, we could reach
141 1.1 pooka * inside the rump kernel and inquire about the thread's sleep
142 1.1 pooka * status.
143 1.1 pooka */
144 1.1 pooka for (i = 0; i < 1000; i++) {
145 1.1 pooka sem_wait(&semmarit[2]);
146 1.1 pooka usleep(1);
147 1.1 pooka if (sem_destroy(&semmarit[1]) == -1)
148 1.1 pooka if (errno == EBUSY)
149 1.1 pooka break;
150 1.1 pooka
151 1.1 pooka /*
152 1.1 pooka * Didn't catch it? ok, recreate and post to make the
153 1.1 pooka * other thread run
154 1.1 pooka */
155 1.1 pooka sem_init(&semmarit[1], 1, 0);
156 1.1 pooka sem_post(&semmarit[0]);
157 1.1 pooka sem_post(&semmarit[1]);
158 1.1 pooka
159 1.1 pooka }
160 1.1 pooka if (i == 1000)
161 1.1 pooka atf_tc_fail("sem destroy not reporting EBUSY");
162 1.8 joerg
163 1.8 joerg pthread_cancel(pt);
164 1.8 joerg pthread_join(pt, NULL);
165 1.1 pooka }
166 1.1 pooka
167 1.1 pooka ATF_TC(blockwait);
168 1.1 pooka ATF_TC_HEAD(blockwait, tc)
169 1.1 pooka {
170 1.1 pooka
171 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests sem_wait can handle blocking "
172 1.1 pooka "(%s)", LIBNAME);
173 1.5 pooka atf_tc_set_md_var(tc, "timeout", "2");
174 1.1 pooka }
175 1.1 pooka
176 1.1 pooka ATF_TC_BODY(blockwait, tc)
177 1.1 pooka {
178 1.1 pooka sem_t semmarit[3];
179 1.1 pooka pthread_t pt;
180 1.1 pooka int i;
181 1.1 pooka
182 1.1 pooka rump_init();
183 1.1 pooka sem_init(&semmarit[0], 1, 0);
184 1.1 pooka sem_init(&semmarit[1], 1, 0);
185 1.1 pooka sem_init(&semmarit[2], 1, 0);
186 1.1 pooka
187 1.1 pooka pthread_create(&pt, NULL, hthread, semmarit);
188 1.1 pooka
189 1.1 pooka /*
190 1.1 pooka * Make a best-effort. Unless we're extremely unlucky, we should
191 1.1 pooka * at least one blocking wait.
192 1.1 pooka */
193 1.1 pooka for (i = 0; i < 10; i++) {
194 1.1 pooka sem_wait(&semmarit[2]);
195 1.1 pooka usleep(1);
196 1.1 pooka sem_post(&semmarit[0]);
197 1.1 pooka sem_post(&semmarit[1]);
198 1.1 pooka
199 1.1 pooka }
200 1.8 joerg
201 1.8 joerg pthread_cancel(pt);
202 1.8 joerg pthread_join(pt, NULL);
203 1.1 pooka }
204 1.1 pooka
205 1.9 joerg ATF_TC(blocktimedwait);
206 1.9 joerg ATF_TC_HEAD(blocktimedwait, tc)
207 1.9 joerg {
208 1.9 joerg
209 1.9 joerg atf_tc_set_md_var(tc, "descr", "tests sem_timedwait can handle blocking"
210 1.9 joerg " (%s)", LIBNAME);
211 1.9 joerg atf_tc_set_md_var(tc, "timeout", "2");
212 1.9 joerg }
213 1.9 joerg
214 1.9 joerg ATF_TC_BODY(blocktimedwait, tc)
215 1.9 joerg {
216 1.9 joerg sem_t semid;
217 1.9 joerg struct timespec tp;
218 1.9 joerg
219 1.9 joerg rump_init();
220 1.9 joerg
221 1.9 joerg clock_gettime(CLOCK_REALTIME, &tp);
222 1.9 joerg tp.tv_nsec += 50000000;
223 1.9 joerg tp.tv_sec += tp.tv_nsec / 1000000000;
224 1.9 joerg tp.tv_nsec %= 1000000000;
225 1.9 joerg
226 1.9 joerg ATF_REQUIRE_EQ(sem_init(&semid, 1, 0), 0);
227 1.9 joerg ATF_REQUIRE_ERRNO(ETIMEDOUT, sem_timedwait(&semid, &tp) == -1);
228 1.9 joerg }
229 1.9 joerg
230 1.1 pooka ATF_TC(named);
231 1.1 pooka ATF_TC_HEAD(named, tc)
232 1.1 pooka {
233 1.1 pooka
234 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests named semaphores (%s)", LIBNAME);
235 1.1 pooka }
236 1.1 pooka
237 1.1 pooka /*
238 1.1 pooka * Wow, easy naming rules. it's these times i'm really happy i can
239 1.1 pooka * single-step into the kernel.
240 1.1 pooka */
241 1.7 pooka #define SEM1 "/precious_sem"
242 1.1 pooka #define SEM2 "/justsem"
243 1.1 pooka ATF_TC_BODY(named, tc)
244 1.1 pooka {
245 1.1 pooka sem_t *sem1, *sem2;
246 1.1 pooka void *rv;
247 1.1 pooka
248 1.1 pooka rump_init();
249 1.1 pooka sem1 = sem_open(SEM1, 0);
250 1.1 pooka ATF_REQUIRE_EQ(errno, ENOENT);
251 1.1 pooka ATF_REQUIRE_EQ(sem1, NULL);
252 1.1 pooka
253 1.1 pooka sem1 = sem_open(SEM1, O_CREAT, 0444, 1);
254 1.1 pooka if (sem1 == NULL)
255 1.1 pooka atf_tc_fail_errno("sem_open O_CREAT");
256 1.1 pooka
257 1.1 pooka rv = sem_open(SEM1, O_CREAT | O_EXCL);
258 1.1 pooka ATF_REQUIRE_EQ(errno, EEXIST);
259 1.1 pooka ATF_REQUIRE_EQ(rv, NULL);
260 1.1 pooka
261 1.1 pooka sem2 = sem_open(SEM2, O_CREAT, 0444, 0);
262 1.1 pooka if (sem2 == NULL)
263 1.1 pooka atf_tc_fail_errno("sem_open O_CREAT");
264 1.1 pooka
265 1.1 pooka /* check that semaphores are independent */
266 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), -1);
267 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), 0);
268 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), -1);
269 1.1 pooka
270 1.1 pooka /* check that unlinked remains valid */
271 1.1 pooka sem_unlink(SEM2);
272 1.1 pooka ATF_REQUIRE_EQ(sem_post(sem2), 0);
273 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), 0);
274 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), -1);
275 1.1 pooka ATF_REQUIRE_EQ(errno, EAGAIN);
276 1.1 pooka
277 1.1 pooka #if 0 /* see unlink */
278 1.1 pooka /* close it and check that it's gone */
279 1.1 pooka if (sem_close(sem2) != 0)
280 1.1 pooka atf_tc_fail_errno("sem close");
281 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), -1);
282 1.1 pooka ATF_REQUIRE_EQ(errno, EINVAL);
283 1.1 pooka #endif
284 1.1 pooka
285 1.1 pooka /* check that we still have sem1 */
286 1.1 pooka sem_post(sem1);
287 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), 0);
288 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), -1);
289 1.1 pooka ATF_REQUIRE_EQ(errno, EAGAIN);
290 1.1 pooka }
291 1.1 pooka
292 1.1 pooka ATF_TC(unlink);
293 1.1 pooka ATF_TC_HEAD(unlink, tc)
294 1.1 pooka {
295 1.1 pooka
296 1.1 pooka /* this is currently broken. i'll append the PR number soon */
297 1.2 pooka atf_tc_set_md_var(tc, "descr", "tests unlinked semaphores can be "
298 1.4 pooka "closed (%s)", LIBNAME);
299 1.1 pooka }
300 1.1 pooka
301 1.1 pooka #define SEM "/thesem"
302 1.1 pooka ATF_TC_BODY(unlink, tc)
303 1.1 pooka {
304 1.1 pooka sem_t *sem;
305 1.1 pooka
306 1.1 pooka rump_init();
307 1.1 pooka sem = sem_open(SEM, O_CREAT, 0444, 0);
308 1.1 pooka ATF_REQUIRE(sem);
309 1.1 pooka
310 1.1 pooka if (sem_unlink(SEM) == -1)
311 1.1 pooka atf_tc_fail_errno("unlink");
312 1.6 jmmv atf_tc_expect_fail("PR kern/43452");
313 1.1 pooka if (sem_close(sem) == -1)
314 1.1 pooka atf_tc_fail_errno("close unlinked semaphore");
315 1.1 pooka }
316 1.1 pooka
317 1.1 pooka /* use rump calls for libpthread _ksem_foo() calls */
318 1.1 pooka #define F1(name, a) int _ksem_##name(a); \
319 1.1 pooka int _ksem_##name(a v1) {return rump_sys__ksem_##name(v1);}
320 1.1 pooka #define F2(name, a, b) int _ksem_##name(a, b); \
321 1.1 pooka int _ksem_##name(a v1, b v2) {return rump_sys__ksem_##name(v1, v2);}
322 1.1 pooka F2(init, unsigned int, intptr_t *);
323 1.1 pooka F1(close, intptr_t);
324 1.1 pooka F1(destroy, intptr_t);
325 1.1 pooka F1(post, intptr_t);
326 1.1 pooka F1(unlink, const char *);
327 1.1 pooka F1(trywait, intptr_t);
328 1.1 pooka F1(wait, intptr_t);
329 1.1 pooka F2(getvalue, intptr_t, unsigned int *);
330 1.9 joerg F2(timedwait, intptr_t, const struct timespec *);
331 1.1 pooka int _ksem_open(const char *, int, mode_t, unsigned int, intptr_t *);
332 1.1 pooka int _ksem_open(const char *a, int b, mode_t c, unsigned int d, intptr_t *e)
333 1.1 pooka {return rump_sys__ksem_open(a,b,c,d,e);}
334