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.diff -r1.21 -r1.22 src/lib/libpthread/sem.c
(joerg)
--- 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 | |||
76 | struct _sem_st { | 75 | struct _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 | |||
91 | static int sem_alloc(unsigned int value, intptr_t semid, sem_t *semp); | 84 | static int sem_alloc(unsigned int value, intptr_t semid, sem_t *semp); | |
92 | static void sem_free(sem_t sem); | 85 | static void sem_free(sem_t sem); | |
93 | 86 | |||
94 | static LIST_HEAD(, _sem_st) named_sems = LIST_HEAD_INITIALIZER(&named_sems); | 87 | static LIST_HEAD(, _sem_st) named_sems = LIST_HEAD_INITIALIZER(&named_sems); | |
95 | static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER; | 88 | static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER; | |
96 | 89 | |||
97 | static void | 90 | static void | |
98 | sem_free(sem_t sem) | 91 | sem_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 | |||
109 | static int | 98 | static int | |
110 | sem_alloc(unsigned int value, intptr_t semid, sem_t *semp) | 99 | sem_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 */ | |||
130 | int | 117 | int | |
131 | sem_init(sem_t *sem, int pshared, unsigned int value) | 118 | sem_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 | |||
151 | int | 135 | int | |
152 | sem_destroy(sem_t *sem) | 136 | sem_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 | |||
180 | sem_t * | 154 | sem_t * | |
181 | sem_open(const char *name, int oflag, ...) | 155 | sem_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 | |||
244 | int | 218 | int | |
245 | sem_close(sem_t *sem) | 219 | sem_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 | |||
272 | int | 242 | int | |
273 | sem_unlink(const char *name) | 243 | sem_unlink(const char *name) | |
274 | { | 244 | { | |
275 | 245 | |||
276 | return (_ksem_unlink(name)); | 246 | return (_ksem_unlink(name)); | |
277 | } | 247 | } | |
278 | 248 | |||
279 | int | 249 | int | |
280 | sem_wait(sem_t *sem) | 250 | sem_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 | |||
332 | int | 263 | int | |
333 | sem_trywait(sem_t *sem) | 264 | sem_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 | |||
375 | int | 277 | int | |
376 | sem_post(sem_t *sem) | 278 | sem_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 | |||
397 | int | 291 | int | |
398 | sem_getvalue(sem_t * __restrict sem, int * __restrict sval) | 292 | sem_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 | } |
--- 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 | |||
113 | static sem_t sem; | 113 | static sem_t sem; | |
114 | 114 | |||
115 | ATF_TC(named); | 115 | ATF_TC(named); | |
116 | ATF_TC_HEAD(named, tc) | 116 | ATF_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 | } | |
120 | ATF_TC_BODY(named, tc) | 120 | ATF_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 | |||
137 | ATF_TC(unnamed); | 137 | ATF_TC(unnamed); | |
138 | ATF_TC_HEAD(unnamed, tc) | 138 | ATF_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 | |||
143 | static void * | 143 | static void * | |
144 | entry(void * a_arg) | 144 | entry(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 | |||
156 | ATF_TC_BODY(unnamed, tc) | 156 | ATF_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 | |||
210 | static void | 210 | static void | |
211 | sighandler(int signo) | 211 | sighandler(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 | |||
219 | static void | 219 | static void | |
220 | alarm_ms(const int ms) | 220 | alarm_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 | |||
230 | static void * | 230 | static void * | |
231 | threadfunc(void *arg) | 231 | threadfunc(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 | |||
254 | static void | 254 | static void | |
255 | before_start_test(const bool use_pthread) | 255 | before_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 | |||
272 | ATF_TC(before_start_no_threads); | 272 | ATF_TC(before_start_no_threads); | |
273 | ATF_TC_HEAD(before_start_no_threads, tc) | 273 | ATF_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 | } | |
279 | ATF_TC_BODY(before_start_no_threads, tc) | 279 | ATF_TC_BODY(before_start_no_threads, tc) | |
280 | { | 280 | { | |
281 | before_start_test(false); | 281 | before_start_test(false); | |
282 | } | 282 | } | |
283 | 283 | |||
284 | ATF_TC(before_start_one_thread); | 284 | ATF_TC(before_start_one_thread); | |
285 | ATF_TC_HEAD(before_start_one_thread, tc) | 285 | ATF_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 | } | |
291 | ATF_TC_BODY(before_start_one_thread, tc) | 291 | ATF_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 | |||
303 | ATF_TP_ADD_TCS(tp) | 296 | ATF_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 | } |