Wed Mar 7 23:31:44 2012 UTC ()
Remove libpthread's semaphore implementation and always use the kernel
one. The implementation doesn't provide an async-safe sem_post and can't
without a lot of work on the pthread primitives.

Remove bogus time out requirement in test case, it should have been
a "known failure" if anything.


(joerg)
diff -r1.21 -r1.22 src/lib/libpthread/sem.c
diff -r1.5 -r1.6 src/tests/lib/libpthread/t_sem.c

cvs diff -r1.21 -r1.22 src/lib/libpthread/Attic/sem.c (switch to unified diff)

--- src/lib/libpthread/Attic/sem.c 2008/11/14 15:49:20 1.21
+++ src/lib/libpthread/Attic/sem.c 2012/03/07 23:31:44 1.22
@@ -1,415 +1,302 @@ @@ -1,415 +1,302 @@
1/* $NetBSD: sem.c,v 1.21 2008/11/14 15:49:20 ad Exp $ */ 1/* $NetBSD: sem.c,v 1.22 2012/03/07 23:31:44 joerg Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2003, 2006, 2007 The NetBSD Foundation, Inc. 4 * Copyright (c) 2003, 2006, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran. 8 * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>. 33 * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
34 * All rights reserved. 34 * All rights reserved.
35 *  35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice(s), this list of conditions and the following disclaimer as 40 * notice(s), this list of conditions and the following disclaimer as
41 * the first lines of this file unmodified other than the possible 41 * the first lines of this file unmodified other than the possible
42 * addition of one or more copyright notices. 42 * addition of one or more copyright notices.
43 * 2. Redistributions in binary form must reproduce the above copyright 43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice(s), this list of conditions and the following disclaimer in 44 * notice(s), this list of conditions and the following disclaimer in
45 * the documentation and/or other materials provided with the 45 * the documentation and/or other materials provided with the
46 * distribution. 46 * distribution.
47 *  47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
49 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 51 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
52 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
55 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 55 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
56 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 56 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
57 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 57 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
58 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 */ 59 */
60 60
61#include <sys/cdefs.h> 61#include <sys/cdefs.h>
62__RCSID("$NetBSD: sem.c,v 1.21 2008/11/14 15:49:20 ad Exp $"); 62__RCSID("$NetBSD: sem.c,v 1.22 2012/03/07 23:31:44 joerg Exp $");
63 63
64#include <sys/types.h> 64#include <sys/types.h>
65#include <sys/ksem.h> 65#include <sys/ksem.h>
66#include <sys/queue.h> 66#include <sys/queue.h>
67#include <stdlib.h> 67#include <stdlib.h>
68#include <errno.h> 68#include <errno.h>
69#include <fcntl.h> 69#include <fcntl.h>
70#include <semaphore.h> 70#include <semaphore.h>
71#include <stdarg.h> 71#include <stdarg.h>
72 72
73#include "pthread.h" 73#include "pthread.h"
74#include "pthread_int.h" 
75 74
76struct _sem_st { 75struct _sem_st {
77 unsigned int usem_magic; 76 unsigned int ksem_magic;
78#define USEM_MAGIC 0x09fa4012 77#define KSEM_MAGIC 0x90af0421U
79 78
80 LIST_ENTRY(_sem_st) usem_list; 79 LIST_ENTRY(_sem_st) ksem_list;
81 intptr_t usem_semid; /* 0 -> user (non-shared) */ 80 intptr_t ksem_semid; /* 0 -> user (non-shared) */
82#define USEM_USER 0 /* assumes kernel does not use NULL */ 81 sem_t *ksem_identity;
83 sem_t *usem_identity; 
84 
85 /* Protects data below. */ 
86 pthread_mutex_t usem_interlock; 
87 pthread_cond_t usem_cv; 
88 unsigned int usem_count; 
89}; 82};
90 83
91static int sem_alloc(unsigned int value, intptr_t semid, sem_t *semp); 84static int sem_alloc(unsigned int value, intptr_t semid, sem_t *semp);
92static void sem_free(sem_t sem); 85static void sem_free(sem_t sem);
93 86
94static LIST_HEAD(, _sem_st) named_sems = LIST_HEAD_INITIALIZER(&named_sems); 87static LIST_HEAD(, _sem_st) named_sems = LIST_HEAD_INITIALIZER(&named_sems);
95static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER; 88static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER;
96 89
97static void 90static void
98sem_free(sem_t sem) 91sem_free(sem_t sem)
99{ 92{
100 93
101 if (sem->usem_semid == USEM_USER) { 94 sem->ksem_magic = 0;
102 pthread_cond_destroy(&sem->usem_cv); 
103 pthread_mutex_destroy(&sem->usem_interlock); 
104 } 
105 sem->usem_magic = 0; 
106 free(sem); 95 free(sem);
107} 96}
108 97
109static int 98static int
110sem_alloc(unsigned int value, intptr_t semid, sem_t *semp) 99sem_alloc(unsigned int value, intptr_t semid, sem_t *semp)
111{ 100{
112 sem_t sem; 101 sem_t sem;
113 102
114 if (value > SEM_VALUE_MAX) 103 if (value > SEM_VALUE_MAX)
115 return (EINVAL); 104 return (EINVAL);
116 105
117 if ((sem = malloc(sizeof(struct _sem_st))) == NULL) 106 if ((sem = malloc(sizeof(struct _sem_st))) == NULL)
118 return (ENOSPC); 107 return (ENOSPC);
119 108
120 sem->usem_magic = USEM_MAGIC; 109 sem->ksem_magic = KSEM_MAGIC;
121 pthread_mutex_init(&sem->usem_interlock, NULL); 110 sem->ksem_semid = semid;
122 pthread_cond_init(&sem->usem_cv, NULL); 111
123 sem->usem_count = value; 
124 sem->usem_semid = semid; 
125 
126 *semp = sem; 112 *semp = sem;
127 return (0); 113 return (0);
128} 114}
129 115
 116/* ARGSUSED */
130int 117int
131sem_init(sem_t *sem, int pshared, unsigned int value) 118sem_init(sem_t *sem, int pshared, unsigned int value)
132{ 119{
133 intptr_t semid; 120 intptr_t semid;
134 int error; 121 int error;
135 122
136 semid = USEM_USER; 123 if (_ksem_init(value, &semid) == -1)
137 
138 if (pshared && _ksem_init(value, &semid) == -1) 
139 return (-1); 124 return (-1);
140 125
141 if ((error = sem_alloc(value, semid, sem)) != 0) { 126 if ((error = sem_alloc(value, semid, sem)) != 0) {
142 if (semid != USEM_USER) 127 _ksem_destroy(semid);
143 _ksem_destroy(semid); 
144 errno = error; 128 errno = error;
145 return (-1); 129 return (-1);
146 } 130 }
147 131
148 return (0); 132 return (0);
149} 133}
150 134
151int 135int
152sem_destroy(sem_t *sem) 136sem_destroy(sem_t *sem)
153{ 137{
154 138
155#ifdef ERRORCHECK 139#ifdef ERRORCHECK
156 if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { 140 if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) {
157 errno = EINVAL; 141 errno = EINVAL;
158 return (-1); 142 return (-1);
159 } 143 }
160#endif 144#endif
161 145
162 if ((*sem)->usem_semid != USEM_USER) { 146 if (_ksem_destroy((*sem)->ksem_semid) == -1)
163 if (_ksem_destroy((*sem)->usem_semid)) 147 return (-1);
164 return (-1); 
165 } else { 
166 pthread_mutex_lock(&(*sem)->usem_interlock); 
167 if (!PTQ_EMPTY(&(*sem)->usem_cv.ptc_waiters)) { 
168 pthread_mutex_unlock(&(*sem)->usem_interlock); 
169 errno = EBUSY; 
170 return (-1); 
171 } 
172 pthread_mutex_unlock(&(*sem)->usem_interlock); 
173 } 
174 148
175 sem_free(*sem); 149 sem_free(*sem);
176 150
177 return (0); 151 return (0);
178} 152}
179 153
180sem_t * 154sem_t *
181sem_open(const char *name, int oflag, ...) 155sem_open(const char *name, int oflag, ...)
182{ 156{
183 sem_t *sem, s; 157 sem_t *sem, s;
184 intptr_t semid; 158 intptr_t semid;
185 mode_t mode; 159 mode_t mode;
186 unsigned int value; 160 unsigned int value;
187 int error; 161 int error;
188 va_list ap; 162 va_list ap;
189 163
190 mode = 0; 164 mode = 0;
191 value = 0; 165 value = 0;
192 166
193 if (oflag & O_CREAT) { 167 if (oflag & O_CREAT) {
194 va_start(ap, oflag); 168 va_start(ap, oflag);
195 mode = va_arg(ap, int); 169 mode = va_arg(ap, int);
196 value = va_arg(ap, unsigned int); 170 value = va_arg(ap, unsigned int);
197 va_end(ap); 171 va_end(ap);
198 } 172 }
199 173
200 /* 174 /*
201 * We can be lazy and let the kernel handle the oflag, 175 * We can be lazy and let the kernel handle the oflag,
202 * we'll just merge duplicate IDs into our list. 176 * we'll just merge duplicate IDs into our list.
203 */ 177 */
204 if (_ksem_open(name, oflag, mode, value, &semid) == -1) 178 if (_ksem_open(name, oflag, mode, value, &semid) == -1)
205 return (SEM_FAILED); 179 return (SEM_FAILED);
206 180
207 /* 181 /*
208 * Search for a duplicate ID, we must return the same sem_t * 182 * Search for a duplicate ID, we must return the same sem_t *
209 * if we locate one. 183 * if we locate one.
210 */ 184 */
211 pthread_mutex_lock(&named_sems_mtx); 185 pthread_mutex_lock(&named_sems_mtx);
212 LIST_FOREACH(s, &named_sems, usem_list) { 186 LIST_FOREACH(s, &named_sems, ksem_list) {
213 if (s->usem_semid == semid) { 187 if (s->ksem_semid == semid) {
214 pthread_mutex_unlock(&named_sems_mtx); 188 pthread_mutex_unlock(&named_sems_mtx);
215 return (s->usem_identity); 189 return (s->ksem_identity);
216 } 190 }
217 } 191 }
218 192
219 if ((sem = malloc(sizeof(*sem))) == NULL) { 193 if ((sem = malloc(sizeof(*sem))) == NULL) {
220 error = ENOSPC; 194 error = ENOSPC;
221 goto bad; 195 goto bad;
222 } 196 }
223 if ((error = sem_alloc(value, semid, sem)) != 0) 197 if ((error = sem_alloc(value, semid, sem)) != 0)
224 goto bad; 198 goto bad;
225 199
226 LIST_INSERT_HEAD(&named_sems, *sem, usem_list); 200 LIST_INSERT_HEAD(&named_sems, *sem, ksem_list);
227 (*sem)->usem_identity = sem; 
228 pthread_mutex_unlock(&named_sems_mtx); 201 pthread_mutex_unlock(&named_sems_mtx);
 202 (*sem)->ksem_identity = sem;
229 203
230 return (sem); 204 return (sem);
231 205
232 bad: 206 bad:
233 pthread_mutex_unlock(&named_sems_mtx); 207 pthread_mutex_unlock(&named_sems_mtx);
234 _ksem_close(semid); 208 _ksem_close(semid);
235 if (sem != NULL) { 209 if (sem != NULL) {
236 if (*sem != NULL) 210 if (*sem != NULL)
237 sem_free(*sem); 211 sem_free(*sem);
238 free(sem); 212 free(sem);
239 } 213 }
240 errno = error; 214 errno = error;
241 return (SEM_FAILED); 215 return (SEM_FAILED);
242} 216}
243 217
244int 218int
245sem_close(sem_t *sem) 219sem_close(sem_t *sem)
246{ 220{
247 221
248#ifdef ERRORCHECK 222#ifdef ERRORCHECK
249 if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { 223 if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) {
250 errno = EINVAL; 224 errno = EINVAL;
251 return (-1); 225 return (-1);
252 } 226 }
253#endif 227#endif
254 228
255 if ((*sem)->usem_semid == USEM_USER) { 
256 errno = EINVAL; 
257 return (-1); 
258 } 
259 
260 pthread_mutex_lock(&named_sems_mtx); 229 pthread_mutex_lock(&named_sems_mtx);
261 if (_ksem_close((*sem)->usem_semid) == -1) { 230 if (_ksem_close((*sem)->ksem_semid) == -1) {
262 pthread_mutex_unlock(&named_sems_mtx); 231 pthread_mutex_unlock(&named_sems_mtx);
263 return (-1); 232 return (-1);
264 } 233 }
265 LIST_REMOVE((*sem), usem_list); 234
 235 LIST_REMOVE((*sem), ksem_list);
266 pthread_mutex_unlock(&named_sems_mtx); 236 pthread_mutex_unlock(&named_sems_mtx);
267 sem_free(*sem); 237 sem_free(*sem);
268 free(sem); 238 free(sem);
269 return (0); 239 return (0);
270} 240}
271 241
272int 242int
273sem_unlink(const char *name) 243sem_unlink(const char *name)
274{ 244{
275 245
276 return (_ksem_unlink(name)); 246 return (_ksem_unlink(name));
277} 247}
278 248
279int 249int
280sem_wait(sem_t *sem) 250sem_wait(sem_t *sem)
281{ 251{
282 pthread_t self; 
283 extern int pthread__started; 
284 252
285#ifdef ERRORCHECK 253#ifdef ERRORCHECK
286 if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { 254 if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) {
287 errno = EINVAL; 255 errno = EINVAL;
288 return (-1); 256 return (-1);
289 } 257 }
290#endif 258#endif
291 259
292 self = pthread__self(); 260 return (_ksem_wait((*sem)->ksem_semid));
293 
294 if ((*sem)->usem_semid != USEM_USER) { 
295 pthread__testcancel(self); 
296 return (_ksem_wait((*sem)->usem_semid)); 
297 } 
298 
299 if (pthread__started == 0) { 
300 sigset_t set, oset; 
301 
302 sigfillset(&set); 
303 (void) sigprocmask(SIG_SETMASK, &set, &oset); 
304 for (;;) { 
305 if ((*sem)->usem_count > 0) { 
306 break; 
307 } 
308 (void) sigsuspend(&oset); 
309 } 
310 (*sem)->usem_count--; 
311 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 
312 return 0; 
313 } 
314 
315 pthread_mutex_lock(&(*sem)->usem_interlock); 
316 for (;;) { 
317 if (self->pt_cancel) { 
318 pthread_mutex_unlock(&(*sem)->usem_interlock); 
319 pthread__cancelled(); 
320 } 
321 if ((*sem)->usem_count > 0) 
322 break; 
323 (void)pthread_cond_wait(&(*sem)->usem_cv, 
324 &(*sem)->usem_interlock); 
325 } 
326 (*sem)->usem_count--; 
327 pthread_mutex_unlock(&(*sem)->usem_interlock); 
328 
329 return (0); 
330} 261}
331 262
332int 263int
333sem_trywait(sem_t *sem) 264sem_trywait(sem_t *sem)
334{ 265{
335 extern int pthread__started; 
336 266
337#ifdef ERRORCHECK 267#ifdef ERRORCHECK
338 if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { 268 if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) {
339 errno = EINVAL; 269 errno = EINVAL;
340 return (-1); 270 return (-1);
341 } 271 }
342#endif 272#endif
343 273
344 if ((*sem)->usem_semid != USEM_USER) 274 return (_ksem_trywait((*sem)->ksem_semid));
345 return (_ksem_trywait((*sem)->usem_semid)); 
346 
347 if (pthread__started == 0) { 
348 sigset_t set, oset; 
349 int rv = 0; 
350 
351 sigfillset(&set); 
352 (void) sigprocmask(SIG_SETMASK, &set, &oset); 
353 if ((*sem)->usem_count > 0) { 
354 (*sem)->usem_count--; 
355 } else { 
356 errno = EAGAIN; 
357 rv = -1; 
358 } 
359 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 
360 return rv; 
361 } 
362 
363 pthread_mutex_lock(&(*sem)->usem_interlock); 
364 if ((*sem)->usem_count == 0) { 
365 pthread_mutex_unlock(&(*sem)->usem_interlock); 
366 errno = EAGAIN; 
367 return (-1); 
368 } 
369 (*sem)->usem_count--; 
370 pthread_mutex_unlock(&(*sem)->usem_interlock); 
371 
372 return (0); 
373} 275}
374 276
375int 277int
376sem_post(sem_t *sem) 278sem_post(sem_t *sem)
377{ 279{
378 280
379#ifdef ERRORCHECK 281#ifdef ERRORCHECK
380 if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { 282 if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) {
381 errno = EINVAL; 283 errno = EINVAL;
382 return (-1); 284 return (-1);
383 } 285 }
384#endif 286#endif
385 287
386 if ((*sem)->usem_semid != USEM_USER) 288 return (_ksem_post((*sem)->ksem_semid));
387 return (_ksem_post((*sem)->usem_semid)); 
388 
389 pthread_mutex_lock(&(*sem)->usem_interlock); 
390 (*sem)->usem_count++; 
391 pthread_cond_signal(&(*sem)->usem_cv); 
392 pthread_mutex_unlock(&(*sem)->usem_interlock); 
393 
394 return (0); 
395} 289}
396 290
397int 291int
398sem_getvalue(sem_t * __restrict sem, int * __restrict sval) 292sem_getvalue(sem_t * __restrict sem, int * __restrict sval)
399{ 293{
400 294
401#ifdef ERRORCHECK 295#ifdef ERRORCHECK
402 if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { 296 if (sem == NULL || *sem == NULL || (*sem)->ksem_magic != KSEM_MAGIC) {
403 errno = EINVAL; 297 errno = EINVAL;
404 return (-1); 298 return (-1);
405 } 299 }
406#endif 300#endif
407 if ((*sem)->usem_semid != USEM_USER) 301 return (_ksem_getvalue((*sem)->ksem_semid, sval));
408 return (_ksem_getvalue((*sem)->usem_semid, sval)); 
409 
410 pthread_mutex_lock(&(*sem)->usem_interlock); 
411 *sval = (int) (*sem)->usem_count; 
412 pthread_mutex_unlock(&(*sem)->usem_interlock); 
413 
414 return (0); 
415} 302}

cvs diff -r1.5 -r1.6 src/tests/lib/libpthread/t_sem.c (switch to unified diff)

--- src/tests/lib/libpthread/t_sem.c 2010/11/03 16:10:22 1.5
+++ src/tests/lib/libpthread/t_sem.c 2012/03/07 23:31:44 1.6
@@ -1,311 +1,304 @@ @@ -1,311 +1,304 @@
1/* $NetBSD: t_sem.c,v 1.5 2010/11/03 16:10:22 christos Exp $ */ 1/* $NetBSD: t_sem.c,v 1.6 2012/03/07 23:31:44 joerg Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/*- 29/*-
30 * Copyright (c)2004 YAMAMOTO Takashi, 30 * Copyright (c)2004 YAMAMOTO Takashi,
31 * All rights reserved. 31 * All rights reserved.
32 * 32 *
33 * Redistribution and use in source and binary forms, with or without 33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions 34 * modification, are permitted provided that the following conditions
35 * are met: 35 * are met:
36 * 1. Redistributions of source code must retain the above copyright 36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer. 37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright 38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the 39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution. 40 * documentation and/or other materials provided with the distribution.
41 * 41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE. 52 * SUCH DAMAGE.
53 */ 53 */
54 54
55/**************************************************************************** 55/****************************************************************************
56 * 56 *
57 * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>. 57 * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
58 * All rights reserved. 58 * All rights reserved.
59 * 59 *
60 * Redistribution and use in source and binary forms, with or without 60 * Redistribution and use in source and binary forms, with or without
61 * modification, are permitted provided that the following conditions 61 * modification, are permitted provided that the following conditions
62 * are met: 62 * are met:
63 * 1. Redistributions of source code must retain the above copyright 63 * 1. Redistributions of source code must retain the above copyright
64 * notice(s), this list of conditions and the following disclaimer as 64 * notice(s), this list of conditions and the following disclaimer as
65 * the first lines of this file unmodified other than the possible 65 * the first lines of this file unmodified other than the possible
66 * addition of one or more copyright notices. 66 * addition of one or more copyright notices.
67 * 2. Redistributions in binary form must reproduce the above copyright 67 * 2. Redistributions in binary form must reproduce the above copyright
68 * notice(s), this list of conditions and the following disclaimer in 68 * notice(s), this list of conditions and the following disclaimer in
69 * the documentation and/or other materials provided with the 69 * the documentation and/or other materials provided with the
70 * distribution. 70 * distribution.
71 * 71 *
72 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY 72 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
73 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 73 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 74 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
75 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE 75 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
76 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 76 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
77 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 77 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
78 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 78 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
79 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 79 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
80 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 80 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
81 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 81 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
82 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 82 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
83 * 83 *
84 ****************************************************************************/ 84 ****************************************************************************/
85 85
86#include <sys/cdefs.h> 86#include <sys/cdefs.h>
87__COPYRIGHT("@(#) Copyright (c) 2008, 2010\ 87__COPYRIGHT("@(#) Copyright (c) 2008, 2010\
88 The NetBSD Foundation, inc. All rights reserved."); 88 The NetBSD Foundation, inc. All rights reserved.");
89__RCSID("$NetBSD: t_sem.c,v 1.5 2010/11/03 16:10:22 christos Exp $"); 89__RCSID("$NetBSD: t_sem.c,v 1.6 2012/03/07 23:31:44 joerg Exp $");
90 90
91#include <errno.h> 91#include <errno.h>
92#include <fcntl.h> 92#include <fcntl.h>
93#include <pthread.h> 93#include <pthread.h>
94#include <semaphore.h> 94#include <semaphore.h>
95#include <signal.h> 95#include <signal.h>
96#include <stdio.h> 96#include <stdio.h>
97#include <stdlib.h> 97#include <stdlib.h>
98#include <string.h> 98#include <string.h>
99#include <unistd.h> 99#include <unistd.h>
100 100
101#include <atf-c.h> 101#include <atf-c.h>
102#include <atf-c/config.h> 102#include <atf-c/config.h>
103 103
104#include "h_common.h" 104#include "h_common.h"
105 105
106#define NTHREADS 10 106#define NTHREADS 10
107 107
108#define _LIBC_R_ 108#define _LIBC_R_
109 109
110#define SEM_REQUIRE(x) \ 110#define SEM_REQUIRE(x) \
111 ATF_REQUIRE_EQ_MSG(x, 0, "%s", strerror(errno)) 111 ATF_REQUIRE_EQ_MSG(x, 0, "%s", strerror(errno))
112 112
113static sem_t sem; 113static sem_t sem;
114 114
115ATF_TC(named); 115ATF_TC(named);
116ATF_TC_HEAD(named, tc) 116ATF_TC_HEAD(named, tc)
117{ 117{
118 atf_tc_set_md_var(tc, "descr", "Checks named semaphores"); 118 atf_tc_set_md_var(tc, "descr", "Checks named semaphores");
119} 119}
120ATF_TC_BODY(named, tc) 120ATF_TC_BODY(named, tc)
121{ 121{
122 sem_t *semp; 122 sem_t *semp;
123 123
124 ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno)); 124 ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
125 125
126 printf("Test begin\n"); 126 printf("Test begin\n");
127 127
128 (void) sem_unlink("/foo"); 128 (void) sem_unlink("/foo");
129 semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0); 129 semp = sem_open("/foo", O_CREAT | O_EXCL, 0644, 0);
130 ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno)); 130 ATF_REQUIRE_MSG(semp != SEM_FAILED, "%s", strerror(errno));
131 SEM_REQUIRE(sem_close(semp)); 131 SEM_REQUIRE(sem_close(semp));
132 SEM_REQUIRE(sem_unlink("/foo")); 132 SEM_REQUIRE(sem_unlink("/foo"));
133 133
134 printf("Test end\n"); 134 printf("Test end\n");
135} 135}
136 136
137ATF_TC(unnamed); 137ATF_TC(unnamed);
138ATF_TC_HEAD(unnamed, tc) 138ATF_TC_HEAD(unnamed, tc)
139{ 139{
140 atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores"); 140 atf_tc_set_md_var(tc, "descr", "Checks unnamed semaphores");
141} 141}
142 142
143static void * 143static void *
144entry(void * a_arg) 144entry(void * a_arg)
145{ 145{
146 pthread_t self = pthread_self(); 146 pthread_t self = pthread_self();
147 sem_t *semp = (sem_t *) a_arg; 147 sem_t *semp = (sem_t *) a_arg;
148 148
149 printf("Thread %p waiting for semaphore...\n", self); 149 printf("Thread %p waiting for semaphore...\n", self);
150 sem_wait(semp); 150 sem_wait(semp);
151 printf("Thread %p got semaphore\n", self); 151 printf("Thread %p got semaphore\n", self);
152 152
153 return NULL; 153 return NULL;
154} 154}
155 155
156ATF_TC_BODY(unnamed, tc) 156ATF_TC_BODY(unnamed, tc)
157{ 157{
158 sem_t sem_a, sem_b; 158 sem_t sem_a, sem_b;
159 pthread_t threads[NTHREADS]; 159 pthread_t threads[NTHREADS];
160 unsigned i, j; 160 unsigned i, j;
161 int val; 161 int val;
162 162
163 ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno)); 163 ATF_REQUIRE_MSG(-1 != sysconf(_SC_SEMAPHORES), "%s", strerror(errno));
164 164
165 printf("Test begin\n"); 165 printf("Test begin\n");
166 166
167 SEM_REQUIRE(sem_init(&sem_b, 0, 0)); 167 SEM_REQUIRE(sem_init(&sem_b, 0, 0));
168 SEM_REQUIRE(sem_getvalue(&sem_b, &val)); 168 SEM_REQUIRE(sem_getvalue(&sem_b, &val));
169 ATF_REQUIRE_EQ(0, val); 169 ATF_REQUIRE_EQ(0, val);
170 170
171 SEM_REQUIRE(sem_post(&sem_b)); 171 SEM_REQUIRE(sem_post(&sem_b));
172 SEM_REQUIRE(sem_getvalue(&sem_b, &val)); 172 SEM_REQUIRE(sem_getvalue(&sem_b, &val));
173 ATF_REQUIRE_EQ(1, val); 173 ATF_REQUIRE_EQ(1, val);
174 174
175 SEM_REQUIRE(sem_wait(&sem_b)); 175 SEM_REQUIRE(sem_wait(&sem_b));
176 ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1); 176 ATF_REQUIRE_EQ(sem_trywait(&sem_b), -1);
177 ATF_REQUIRE_EQ(errno, EAGAIN); 177 ATF_REQUIRE_EQ(errno, EAGAIN);
178 SEM_REQUIRE(sem_post(&sem_b)); 178 SEM_REQUIRE(sem_post(&sem_b));
179 SEM_REQUIRE(sem_trywait(&sem_b)); 179 SEM_REQUIRE(sem_trywait(&sem_b));
180 SEM_REQUIRE(sem_post(&sem_b)); 180 SEM_REQUIRE(sem_post(&sem_b));
181 SEM_REQUIRE(sem_wait(&sem_b)); 181 SEM_REQUIRE(sem_wait(&sem_b));
182 SEM_REQUIRE(sem_post(&sem_b)); 182 SEM_REQUIRE(sem_post(&sem_b));
183 183
184 SEM_REQUIRE(sem_destroy(&sem_b)); 184 SEM_REQUIRE(sem_destroy(&sem_b));
185 185
186 SEM_REQUIRE(sem_init(&sem_a, 0, 0)); 186 SEM_REQUIRE(sem_init(&sem_a, 0, 0));
187 187
188 for (j = 0; j < 2; j++) { 188 for (j = 0; j < 2; j++) {
189 for (i = 0; i < NTHREADS; i++) { 189 for (i = 0; i < NTHREADS; i++) {
190 PTHREAD_REQUIRE(pthread_create(&threads[i], NULL, 190 PTHREAD_REQUIRE(pthread_create(&threads[i], NULL,
191 entry, (void *) &sem_a)); 191 entry, (void *) &sem_a));
192 } 192 }
193 193
194 for (i = 0; i < NTHREADS; i++) { 194 for (i = 0; i < NTHREADS; i++) {
195 usleep(10000); 195 usleep(10000);
196 printf("main loop %u: posting...\n", j+1); 196 printf("main loop %u: posting...\n", j+1);
197 SEM_REQUIRE(sem_post(&sem_a)); 197 SEM_REQUIRE(sem_post(&sem_a));
198 } 198 }
199 199
200 for (i = 0; i < NTHREADS; i++) { 200 for (i = 0; i < NTHREADS; i++) {
201 PTHREAD_REQUIRE(pthread_join(threads[i], NULL)); 201 PTHREAD_REQUIRE(pthread_join(threads[i], NULL));
202 } 202 }
203 } 203 }
204 204
205 SEM_REQUIRE(sem_destroy(&sem_a)); 205 SEM_REQUIRE(sem_destroy(&sem_a));
206 206
207 printf("Test end\n"); 207 printf("Test end\n");
208} 208}
209 209
210static void 210static void
211sighandler(int signo) 211sighandler(int signo)
212{ 212{
213 /* printf("signal %d\n", signo); */ 213 /* printf("signal %d\n", signo); */
214 214
215 ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal"); 215 ATF_REQUIRE_EQ_MSG(signo, SIGALRM, "unexpected signal");
216 SEM_REQUIRE(sem_post(&sem)); 216 SEM_REQUIRE(sem_post(&sem));
217} 217}
218 218
219static void 219static void
220alarm_ms(const int ms) 220alarm_ms(const int ms)
221{ 221{
222 struct itimerval timer; 222 struct itimerval timer;
223 timer.it_interval.tv_sec = 0; 223 timer.it_interval.tv_sec = 0;
224 timer.it_interval.tv_usec = 0; 224 timer.it_interval.tv_usec = 0;
225 timer.it_value.tv_sec = 0; 225 timer.it_value.tv_sec = 0;
226 timer.it_value.tv_usec = ms * 1000; 226 timer.it_value.tv_usec = ms * 1000;
227 ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0); 227 ATF_REQUIRE(setitimer(ITIMER_REAL, &timer, NULL) == 0);
228} 228}
229 229
230static void * 230static void *
231threadfunc(void *arg) 231threadfunc(void *arg)
232{ 232{
233 int i; 233 int i;
234 234
235 printf("Entering loop\n"); 235 printf("Entering loop\n");
236 for (i = 0; i < 500; ) { 236 for (i = 0; i < 500; ) {
237 if ((i & 1) != 0) { 237 if ((i & 1) != 0) {
238 ATF_REQUIRE(sem_wait(&sem) != -1); 238 ATF_REQUIRE(sem_wait(&sem) != -1);
239 } else { 239 } else {
240 const int ret = sem_trywait(&sem); 240 const int ret = sem_trywait(&sem);
241 if (ret == -1) { 241 if (ret == -1) {
242 ATF_REQUIRE(errno == EAGAIN); 242 ATF_REQUIRE(errno == EAGAIN);
243 continue; 243 continue;
244 } 244 }
245 } 245 }
246 printf("%s: %d\n", __func__, i); 246 printf("%s: %d\n", __func__, i);
247 alarm_ms(5); 247 alarm_ms(5);
248 i++; 248 i++;
249 } 249 }
250 250
251 return NULL; 251 return NULL;
252} 252}
253 253
254static void 254static void
255before_start_test(const bool use_pthread) 255before_start_test(const bool use_pthread)
256{ 256{
257 pthread_t t; 257 pthread_t t;
258 258
259 SEM_REQUIRE(sem_init(&sem, 0, 0)); 259 SEM_REQUIRE(sem_init(&sem, 0, 0));
260 ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler)); 260 ATF_REQUIRE(SIG_ERR != signal(SIGALRM, sighandler));
261 261
262 alarm_ms(5); 262 alarm_ms(5);
263 263
264 if (use_pthread) { 264 if (use_pthread) {
265 PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL)); 265 PTHREAD_REQUIRE(pthread_create(&t, NULL, threadfunc, NULL));
266 PTHREAD_REQUIRE(pthread_join(t, NULL)); 266 PTHREAD_REQUIRE(pthread_join(t, NULL));
267 } else { 267 } else {
268 threadfunc(NULL); 268 threadfunc(NULL);
269 } 269 }
270} 270}
271 271
272ATF_TC(before_start_no_threads); 272ATF_TC(before_start_no_threads);
273ATF_TC_HEAD(before_start_no_threads, tc) 273ATF_TC_HEAD(before_start_no_threads, tc)
274{ 274{
275 atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any " 275 atf_tc_set_md_var(tc, "descr", "Checks using semaphores without any "
276 "thread running"); 276 "thread running");
277 atf_tc_set_md_var(tc, "timeout", "40"); 277 atf_tc_set_md_var(tc, "timeout", "40");
278} 278}
279ATF_TC_BODY(before_start_no_threads, tc) 279ATF_TC_BODY(before_start_no_threads, tc)
280{ 280{
281 before_start_test(false); 281 before_start_test(false);
282} 282}
283 283
284ATF_TC(before_start_one_thread); 284ATF_TC(before_start_one_thread);
285ATF_TC_HEAD(before_start_one_thread, tc) 285ATF_TC_HEAD(before_start_one_thread, tc)
286{ 286{
287 atf_tc_set_md_var(tc, "descr", "Checks using semaphores before " 287 atf_tc_set_md_var(tc, "descr", "Checks using semaphores before "
288 "starting one thread"); 288 "starting one thread");
289 atf_tc_set_md_var(tc, "timeout", "40"); 289 atf_tc_set_md_var(tc, "timeout", "40");
290} 290}
291ATF_TC_BODY(before_start_one_thread, tc) 291ATF_TC_BODY(before_start_one_thread, tc)
292{ 292{
293 /* TODO(jmmv): This really is a race condition test. However, we can't 
294 * yet mark it as such because ATF does not provide such functionality. 
295 * Let's just mark it as an unconditional expected timeout as I haven't 
296 * got it to pass any single time. */ 
297 atf_tc_expect_timeout("Race condition; it is probably unsafe to call " 
298 "sem_post from a signal handler when using the pthread version"); 
299 
300 before_start_test(true); 293 before_start_test(true);
301} 294}
302 295
303ATF_TP_ADD_TCS(tp) 296ATF_TP_ADD_TCS(tp)
304{ 297{
305 ATF_TP_ADD_TC(tp, named); 298 ATF_TP_ADD_TC(tp, named);
306 ATF_TP_ADD_TC(tp, unnamed); 299 ATF_TP_ADD_TC(tp, unnamed);
307 ATF_TP_ADD_TC(tp, before_start_no_threads); 300 ATF_TP_ADD_TC(tp, before_start_no_threads);
308 ATF_TP_ADD_TC(tp, before_start_one_thread); 301 ATF_TP_ADD_TC(tp, before_start_one_thread);
309 302
310 return atf_no_error(); 303 return atf_no_error();
311} 304}