Fri Mar 9 14:25:34 2012 UTC ()
PR 43452 no longer applies.


(joerg)
diff -r1.9 -r1.10 src/tests/lib/semaphore/sem.c

cvs diff -r1.9 -r1.10 src/tests/lib/semaphore/sem.c (switch to unified diff)

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