xref: /freebsd/lib/libc/gen/sem.c (revision ddb4fb5b4456fd60b65d4cfd671ad987aa5a8547)
1bf4dc877SAlfred Perlstein /*
2bf4dc877SAlfred Perlstein  * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
3bf4dc877SAlfred Perlstein  * All rights reserved.
4bf4dc877SAlfred Perlstein  *
5bf4dc877SAlfred Perlstein  * Redistribution and use in source and binary forms, with or without
6bf4dc877SAlfred Perlstein  * modification, are permitted provided that the following conditions
7bf4dc877SAlfred Perlstein  * are met:
8bf4dc877SAlfred Perlstein  * 1. Redistributions of source code must retain the above copyright
9bf4dc877SAlfred Perlstein  *    notice(s), this list of conditions and the following disclaimer as
10bf4dc877SAlfred Perlstein  *    the first lines of this file unmodified other than the possible
11bf4dc877SAlfred Perlstein  *    addition of one or more copyright notices.
12bf4dc877SAlfred Perlstein  * 2. Redistributions in binary form must reproduce the above copyright
13bf4dc877SAlfred Perlstein  *    notice(s), this list of conditions and the following disclaimer in
14bf4dc877SAlfred Perlstein  *    the documentation and/or other materials provided with the
15bf4dc877SAlfred Perlstein  *    distribution.
16bf4dc877SAlfred Perlstein  *
17bf4dc877SAlfred Perlstein  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18bf4dc877SAlfred Perlstein  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19bf4dc877SAlfred Perlstein  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20bf4dc877SAlfred Perlstein  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
21bf4dc877SAlfred Perlstein  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22bf4dc877SAlfred Perlstein  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23bf4dc877SAlfred Perlstein  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24bf4dc877SAlfred Perlstein  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25bf4dc877SAlfred Perlstein  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26bf4dc877SAlfred Perlstein  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27bf4dc877SAlfred Perlstein  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28bf4dc877SAlfred Perlstein  *
29bf4dc877SAlfred Perlstein  * $FreeBSD$
30bf4dc877SAlfred Perlstein  */
31bf4dc877SAlfred Perlstein 
32bf4dc877SAlfred Perlstein #include <stdlib.h>
33bf4dc877SAlfred Perlstein #include <errno.h>
34bf4dc877SAlfred Perlstein #include <fcntl.h>
35bf4dc877SAlfred Perlstein #include <semaphore.h>
36bf4dc877SAlfred Perlstein #include <stdarg.h>
37bf4dc877SAlfred Perlstein #include <pthread.h>
38bf4dc877SAlfred Perlstein #include <sys/queue.h>
39bf4dc877SAlfred Perlstein #include <_semaphore.h>
40bf4dc877SAlfred Perlstein 
41bf4dc877SAlfred Perlstein #define _SEM_CHECK_VALIDITY(sem)		\
42bf4dc877SAlfred Perlstein 	if ((*(sem))->magic != SEM_MAGIC) {	\
43bf4dc877SAlfred Perlstein 		errno = EINVAL;			\
44bf4dc877SAlfred Perlstein 		retval = -1;			\
45bf4dc877SAlfred Perlstein 		goto RETURN;			\
46bf4dc877SAlfred Perlstein 	}
47bf4dc877SAlfred Perlstein 
48bf4dc877SAlfred Perlstein static sem_t sem_alloc(unsigned int value, semid_t semid, int system_sem);
49bf4dc877SAlfred Perlstein static void sem_free(sem_t sem);
50bf4dc877SAlfred Perlstein 
51bf4dc877SAlfred Perlstein static LIST_HEAD(, sem) named_sems = LIST_HEAD_INITIALIZER(&named_sems);
52bf4dc877SAlfred Perlstein static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER;
53bf4dc877SAlfred Perlstein 
54bf4dc877SAlfred Perlstein static void
55bf4dc877SAlfred Perlstein sem_free(sem_t sem)
56bf4dc877SAlfred Perlstein {
57bf4dc877SAlfred Perlstein 
58bf4dc877SAlfred Perlstein 	_pthread_mutex_destroy(&sem->lock);
59bf4dc877SAlfred Perlstein 	_pthread_cond_destroy(&sem->gtzero);
60bf4dc877SAlfred Perlstein 	sem->magic = 0;
61bf4dc877SAlfred Perlstein 	free(sem);
62bf4dc877SAlfred Perlstein }
63bf4dc877SAlfred Perlstein 
64bf4dc877SAlfred Perlstein static sem_t
65bf4dc877SAlfred Perlstein sem_alloc(unsigned int value, semid_t semid, int system_sem)
66bf4dc877SAlfred Perlstein {
67bf4dc877SAlfred Perlstein 	sem_t sem;
68bf4dc877SAlfred Perlstein 
69bf4dc877SAlfred Perlstein 	if (value > SEM_VALUE_MAX) {
70bf4dc877SAlfred Perlstein 		errno = EINVAL;
71bf4dc877SAlfred Perlstein 		return (NULL);
72bf4dc877SAlfred Perlstein 	}
73bf4dc877SAlfred Perlstein 
74bf4dc877SAlfred Perlstein 	sem = (sem_t)malloc(sizeof(struct sem));
75bf4dc877SAlfred Perlstein 	if (sem == NULL) {
76bf4dc877SAlfred Perlstein 		errno = ENOSPC;
77bf4dc877SAlfred Perlstein 		return (NULL);
78bf4dc877SAlfred Perlstein 	}
79bf4dc877SAlfred Perlstein 
80bf4dc877SAlfred Perlstein 	/*
81bf4dc877SAlfred Perlstein 	 * Initialize the semaphore.
82bf4dc877SAlfred Perlstein 	 */
83bf4dc877SAlfred Perlstein 	if (_pthread_mutex_init(&sem->lock, NULL) != 0) {
84bf4dc877SAlfred Perlstein 		free(sem);
85bf4dc877SAlfred Perlstein 		errno = ENOSPC;
86bf4dc877SAlfred Perlstein 		return (NULL);
87bf4dc877SAlfred Perlstein 	}
88bf4dc877SAlfred Perlstein 
89bf4dc877SAlfred Perlstein 	if (_pthread_cond_init(&sem->gtzero, NULL) != 0) {
90bf4dc877SAlfred Perlstein 		_pthread_mutex_destroy(&sem->lock);
91bf4dc877SAlfred Perlstein 		free(sem);
92bf4dc877SAlfred Perlstein 		errno = ENOSPC;
93bf4dc877SAlfred Perlstein 		return (NULL);
94bf4dc877SAlfred Perlstein 	}
95bf4dc877SAlfred Perlstein 
96bf4dc877SAlfred Perlstein 	sem->count = (u_int32_t)value;
97bf4dc877SAlfred Perlstein 	sem->nwaiters = 0;
98bf4dc877SAlfred Perlstein 	sem->magic = SEM_MAGIC;
99bf4dc877SAlfred Perlstein 	sem->semid = semid;
100bf4dc877SAlfred Perlstein 	sem->syssem = system_sem;
101bf4dc877SAlfred Perlstein 	return (sem);
102bf4dc877SAlfred Perlstein }
103bf4dc877SAlfred Perlstein 
104bf4dc877SAlfred Perlstein int
105bf4dc877SAlfred Perlstein sem_init(sem_t *sem, int pshared, unsigned int value)
106bf4dc877SAlfred Perlstein {
107bf4dc877SAlfred Perlstein 	int	retval, got_system_sem;
108bf4dc877SAlfred Perlstein 	semid_t	semid;
109bf4dc877SAlfred Perlstein 
110bf4dc877SAlfred Perlstein 	got_system_sem = 0;
111bf4dc877SAlfred Perlstein 	semid = SEM_USER;
112bf4dc877SAlfred Perlstein 	/*
113bf4dc877SAlfred Perlstein 	 * Range check the arguments.
114bf4dc877SAlfred Perlstein 	 */
115bf4dc877SAlfred Perlstein 	if (pshared != 0) {
116bf4dc877SAlfred Perlstein 		retval = ksem_init(&semid, value);
117bf4dc877SAlfred Perlstein 		if (retval == -1)
118bf4dc877SAlfred Perlstein 			goto RETURN;
119bf4dc877SAlfred Perlstein 		got_system_sem = 1;
120bf4dc877SAlfred Perlstein 	}
121bf4dc877SAlfred Perlstein 
122bf4dc877SAlfred Perlstein 	(*sem) = sem_alloc(value, semid, got_system_sem);
123bf4dc877SAlfred Perlstein 	if ((*sem) == NULL)
124bf4dc877SAlfred Perlstein 		retval = -1;
125bf4dc877SAlfred Perlstein 	else
126bf4dc877SAlfred Perlstein 		retval = 0;
127bf4dc877SAlfred Perlstein   RETURN:
128bf4dc877SAlfred Perlstein 	if (retval != 0 && got_system_sem)
129bf4dc877SAlfred Perlstein 		ksem_destroy(semid);
130bf4dc877SAlfred Perlstein 	return retval;
131bf4dc877SAlfred Perlstein }
132bf4dc877SAlfred Perlstein 
133bf4dc877SAlfred Perlstein int
134bf4dc877SAlfred Perlstein sem_destroy(sem_t *sem)
135bf4dc877SAlfred Perlstein {
136bf4dc877SAlfred Perlstein 	int	retval;
137bf4dc877SAlfred Perlstein 
138bf4dc877SAlfred Perlstein 	_SEM_CHECK_VALIDITY(sem);
139bf4dc877SAlfred Perlstein 
140bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&(*sem)->lock);
141bf4dc877SAlfred Perlstein 	/*
142bf4dc877SAlfred Perlstein 	 * If this is a system semaphore let the kernel track it otherwise
143bf4dc877SAlfred Perlstein 	 * make sure there are no waiters.
144bf4dc877SAlfred Perlstein 	 */
145bf4dc877SAlfred Perlstein 	if ((*sem)->syssem != 0) {
146bf4dc877SAlfred Perlstein 		retval = ksem_destroy((*sem)->semid);
147bf4dc877SAlfred Perlstein 		if (retval == -1) {
148bf4dc877SAlfred Perlstein 			_pthread_mutex_unlock(&(*sem)->lock);
149bf4dc877SAlfred Perlstein 			goto RETURN;
150bf4dc877SAlfred Perlstein 		}
151bf4dc877SAlfred Perlstein 	} else if ((*sem)->nwaiters > 0) {
152bf4dc877SAlfred Perlstein 		_pthread_mutex_unlock(&(*sem)->lock);
153bf4dc877SAlfred Perlstein 		errno = EBUSY;
154bf4dc877SAlfred Perlstein 		retval = -1;
155bf4dc877SAlfred Perlstein 		goto RETURN;
156bf4dc877SAlfred Perlstein 	}
157bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&(*sem)->lock);
158bf4dc877SAlfred Perlstein 
159bf4dc877SAlfred Perlstein 	sem_free(*sem);
160bf4dc877SAlfred Perlstein 
161bf4dc877SAlfred Perlstein 	retval = 0;
162bf4dc877SAlfred Perlstein   RETURN:
163bf4dc877SAlfred Perlstein 	return retval;
164bf4dc877SAlfred Perlstein }
165bf4dc877SAlfred Perlstein 
166bf4dc877SAlfred Perlstein sem_t *
167bf4dc877SAlfred Perlstein sem_open(const char *name, int oflag, ...)
168bf4dc877SAlfred Perlstein {
169bf4dc877SAlfred Perlstein 	sem_t *sem;
170bf4dc877SAlfred Perlstein 	sem_t s;
171bf4dc877SAlfred Perlstein 	semid_t semid;
172bf4dc877SAlfred Perlstein 	mode_t mode;
173bf4dc877SAlfred Perlstein 	unsigned int value;
174bf4dc877SAlfred Perlstein 
175bf4dc877SAlfred Perlstein 	mode = 0;
176bf4dc877SAlfred Perlstein 	value = 0;
177bf4dc877SAlfred Perlstein 
178bf4dc877SAlfred Perlstein 	if ((oflag & O_CREAT) != 0) {
179bf4dc877SAlfred Perlstein 		va_list ap;
180bf4dc877SAlfred Perlstein 
181bf4dc877SAlfred Perlstein 		va_start(ap, oflag);
182bf4dc877SAlfred Perlstein 		mode = va_arg(ap, int);
183bf4dc877SAlfred Perlstein 		value = va_arg(ap, unsigned int);
184bf4dc877SAlfred Perlstein 		va_end(ap);
185bf4dc877SAlfred Perlstein 	}
186bf4dc877SAlfred Perlstein 	/*
187bf4dc877SAlfred Perlstein 	 * we can be lazy and let the kernel handle the "oflag",
188bf4dc877SAlfred Perlstein 	 * we'll just merge duplicate IDs into our list.
189bf4dc877SAlfred Perlstein 	 */
190bf4dc877SAlfred Perlstein 	if (ksem_open(&semid, name, oflag, mode, value) == -1)
191bf4dc877SAlfred Perlstein 		return (SEM_FAILED);
192bf4dc877SAlfred Perlstein 	/*
193bf4dc877SAlfred Perlstein 	 * search for a duplicate ID, we must return the same sem_t *
194bf4dc877SAlfred Perlstein 	 * if we locate one.
195bf4dc877SAlfred Perlstein 	 */
196bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&named_sems_mtx);
197bf4dc877SAlfred Perlstein 	LIST_FOREACH(s, &named_sems, entry) {
198bf4dc877SAlfred Perlstein 	    if (s->semid == semid) {
199bf4dc877SAlfred Perlstein 		    _pthread_mutex_unlock(&named_sems_mtx);
200bf4dc877SAlfred Perlstein 		    return (s->backpointer);
201bf4dc877SAlfred Perlstein 	    }
202bf4dc877SAlfred Perlstein 	}
203bf4dc877SAlfred Perlstein 	sem = (sem_t *)malloc(sizeof(*sem));
204bf4dc877SAlfred Perlstein 	if (sem == NULL)
205bf4dc877SAlfred Perlstein 		goto err;
206bf4dc877SAlfred Perlstein 	*sem = sem_alloc(value, semid, 1);
207bf4dc877SAlfred Perlstein 	if ((*sem) == NULL)
208bf4dc877SAlfred Perlstein 		goto err;
209bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&named_sems_mtx);
210bf4dc877SAlfred Perlstein 	(*sem)->backpointer = sem;
211bf4dc877SAlfred Perlstein 	return (sem);
212bf4dc877SAlfred Perlstein err:
213bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&named_sems_mtx);
214bf4dc877SAlfred Perlstein 	ksem_close(semid);
215bf4dc877SAlfred Perlstein 	if (sem != NULL) {
216bf4dc877SAlfred Perlstein 		if (*sem != NULL)
217bf4dc877SAlfred Perlstein 			sem_free(*sem);
218bf4dc877SAlfred Perlstein 		else
219bf4dc877SAlfred Perlstein 			errno = ENOSPC;
220bf4dc877SAlfred Perlstein 		free(sem);
221bf4dc877SAlfred Perlstein 	} else {
222bf4dc877SAlfred Perlstein 		errno = ENOSPC;
223bf4dc877SAlfred Perlstein 	}
224bf4dc877SAlfred Perlstein 	return (SEM_FAILED);
225bf4dc877SAlfred Perlstein }
226bf4dc877SAlfred Perlstein 
227bf4dc877SAlfred Perlstein int
228bf4dc877SAlfred Perlstein sem_close(sem_t *sem)
229bf4dc877SAlfred Perlstein {
230bf4dc877SAlfred Perlstein 
231bf4dc877SAlfred Perlstein 	if ((*sem)->syssem == 0) {
232bf4dc877SAlfred Perlstein 		errno = EINVAL;
233bf4dc877SAlfred Perlstein 		return (-1);
234bf4dc877SAlfred Perlstein 	}
235bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&named_sems_mtx);
236bf4dc877SAlfred Perlstein 	if (ksem_close((*sem)->semid) == -1) {
237bf4dc877SAlfred Perlstein 		_pthread_mutex_unlock(&named_sems_mtx);
238bf4dc877SAlfred Perlstein 		return (-1);
239bf4dc877SAlfred Perlstein 	}
240bf4dc877SAlfred Perlstein 	LIST_REMOVE((*sem), entry);
241bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&named_sems_mtx);
242bf4dc877SAlfred Perlstein 	sem_free(*sem);
243bf4dc877SAlfred Perlstein 	free(sem);
244bf4dc877SAlfred Perlstein 	return (0);
245bf4dc877SAlfred Perlstein }
246bf4dc877SAlfred Perlstein 
247bf4dc877SAlfred Perlstein int
248bf4dc877SAlfred Perlstein sem_unlink(const char *name)
249bf4dc877SAlfred Perlstein {
250bf4dc877SAlfred Perlstein 
251bf4dc877SAlfred Perlstein 	return (ksem_unlink(name));
252bf4dc877SAlfred Perlstein }
253bf4dc877SAlfred Perlstein 
254bf4dc877SAlfred Perlstein int
255bf4dc877SAlfred Perlstein sem_wait(sem_t *sem)
256bf4dc877SAlfred Perlstein {
257bf4dc877SAlfred Perlstein 	int	retval;
258bf4dc877SAlfred Perlstein 
259bf4dc877SAlfred Perlstein 	_SEM_CHECK_VALIDITY(sem);
260bf4dc877SAlfred Perlstein 
261bf4dc877SAlfred Perlstein 	if ((*sem)->syssem != 0) {
262bf4dc877SAlfred Perlstein 		retval = ksem_wait((*sem)->semid);
263bf4dc877SAlfred Perlstein 		goto RETURN;
264bf4dc877SAlfred Perlstein 	}
265bf4dc877SAlfred Perlstein 
266bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&(*sem)->lock);
267bf4dc877SAlfred Perlstein 
268bf4dc877SAlfred Perlstein 	while ((*sem)->count == 0) {
269bf4dc877SAlfred Perlstein 		(*sem)->nwaiters++;
270bf4dc877SAlfred Perlstein 		_pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
271bf4dc877SAlfred Perlstein 		(*sem)->nwaiters--;
272bf4dc877SAlfred Perlstein 	}
273bf4dc877SAlfred Perlstein 	(*sem)->count--;
274bf4dc877SAlfred Perlstein 
275bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&(*sem)->lock);
276bf4dc877SAlfred Perlstein 
277bf4dc877SAlfred Perlstein 	retval = 0;
278bf4dc877SAlfred Perlstein   RETURN:
279bf4dc877SAlfred Perlstein 	return retval;
280bf4dc877SAlfred Perlstein }
281bf4dc877SAlfred Perlstein 
282bf4dc877SAlfred Perlstein int
283bf4dc877SAlfred Perlstein sem_trywait(sem_t *sem)
284bf4dc877SAlfred Perlstein {
285bf4dc877SAlfred Perlstein 	int	retval;
286bf4dc877SAlfred Perlstein 
287bf4dc877SAlfred Perlstein 	_SEM_CHECK_VALIDITY(sem);
288bf4dc877SAlfred Perlstein 
289bf4dc877SAlfred Perlstein 	if ((*sem)->syssem != 0) {
290bf4dc877SAlfred Perlstein 		retval = ksem_trywait((*sem)->semid);
291bf4dc877SAlfred Perlstein 		goto RETURN;
292bf4dc877SAlfred Perlstein 	}
293bf4dc877SAlfred Perlstein 
294bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&(*sem)->lock);
295bf4dc877SAlfred Perlstein 
296bf4dc877SAlfred Perlstein 	if ((*sem)->count > 0) {
297bf4dc877SAlfred Perlstein 		(*sem)->count--;
298bf4dc877SAlfred Perlstein 		retval = 0;
299bf4dc877SAlfred Perlstein 	} else {
300bf4dc877SAlfred Perlstein 		errno = EAGAIN;
301bf4dc877SAlfred Perlstein 		retval = -1;
302bf4dc877SAlfred Perlstein 	}
303bf4dc877SAlfred Perlstein 
304bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&(*sem)->lock);
305bf4dc877SAlfred Perlstein 
306bf4dc877SAlfred Perlstein   RETURN:
307bf4dc877SAlfred Perlstein 	return retval;
308bf4dc877SAlfred Perlstein }
309bf4dc877SAlfred Perlstein 
310bf4dc877SAlfred Perlstein int
311bf4dc877SAlfred Perlstein sem_post(sem_t *sem)
312bf4dc877SAlfred Perlstein {
313bf4dc877SAlfred Perlstein 	int	retval;
314bf4dc877SAlfred Perlstein 
315bf4dc877SAlfred Perlstein 	_SEM_CHECK_VALIDITY(sem);
316bf4dc877SAlfred Perlstein 
317bf4dc877SAlfred Perlstein 	if ((*sem)->syssem != 0) {
318bf4dc877SAlfred Perlstein 		retval = ksem_post((*sem)->semid);
319bf4dc877SAlfred Perlstein 		goto RETURN;
320bf4dc877SAlfred Perlstein 	}
321bf4dc877SAlfred Perlstein 
322bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&(*sem)->lock);
323bf4dc877SAlfred Perlstein 
324bf4dc877SAlfred Perlstein 	(*sem)->count++;
325bf4dc877SAlfred Perlstein 	if ((*sem)->nwaiters > 0)
326bf4dc877SAlfred Perlstein 		_pthread_cond_signal(&(*sem)->gtzero);
327bf4dc877SAlfred Perlstein 
328bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&(*sem)->lock);
329bf4dc877SAlfred Perlstein 
330bf4dc877SAlfred Perlstein 	retval = 0;
331bf4dc877SAlfred Perlstein   RETURN:
332bf4dc877SAlfred Perlstein 	return retval;
333bf4dc877SAlfred Perlstein }
334bf4dc877SAlfred Perlstein 
335bf4dc877SAlfred Perlstein int
336ddb4fb5bSMike Barcroft sem_getvalue(sem_t * __restrict sem, int * __restrict sval)
337bf4dc877SAlfred Perlstein {
338bf4dc877SAlfred Perlstein 	int	retval;
339bf4dc877SAlfred Perlstein 
340bf4dc877SAlfred Perlstein 	_SEM_CHECK_VALIDITY(sem);
341bf4dc877SAlfred Perlstein 
342bf4dc877SAlfred Perlstein 	if ((*sem)->syssem != 0) {
343bf4dc877SAlfred Perlstein 		retval = ksem_getvalue((*sem)->semid, sval);
344bf4dc877SAlfred Perlstein 		goto RETURN;
345bf4dc877SAlfred Perlstein 	}
346bf4dc877SAlfred Perlstein 
347bf4dc877SAlfred Perlstein 	_pthread_mutex_lock(&(*sem)->lock);
348bf4dc877SAlfred Perlstein 	*sval = (int)(*sem)->count;
349bf4dc877SAlfred Perlstein 	_pthread_mutex_unlock(&(*sem)->lock);
350bf4dc877SAlfred Perlstein 
351bf4dc877SAlfred Perlstein 	retval = 0;
352bf4dc877SAlfred Perlstein   RETURN:
353bf4dc877SAlfred Perlstein 	return retval;
354bf4dc877SAlfred Perlstein }
355