diff options
Diffstat (limited to 'lib/librthread')
-rw-r--r-- | lib/librthread/Makefile | 5 | ||||
-rw-r--r-- | lib/librthread/rthread_sem.c | 202 | ||||
-rw-r--r-- | lib/librthread/rthread_sync.c | 180 |
3 files changed, 207 insertions, 180 deletions
diff --git a/lib/librthread/Makefile b/lib/librthread/Makefile index 3586e8179a7..83f692d9290 100644 --- a/lib/librthread/Makefile +++ b/lib/librthread/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.22 2011/12/22 00:42:07 guenther Exp $ +# $OpenBSD: Makefile,v 1.23 2012/01/04 17:43:34 mpi Exp $ LIB=rthread WANTLINT= @@ -15,7 +15,8 @@ SRCS= rthread.c rthread_attr.c rthread_sched.c rthread_sync.c rthread_tls.c \ rthread_sig.c rthread_np.c rthread_debug.c rthread_stack.c \ rthread_libc.c rthread_fork.c rthread_file.c sched_prio.c \ rthread_cancel.c rthread_mutexattr.c rthread_once.c \ - rthread_rwlock.c rthread_rwlockattr.c rthread_mutex_prio.c + rthread_rwlock.c rthread_rwlockattr.c rthread_mutex_prio.c \ + rthread_sem.c OBJS+= _atomic_lock.o rfork_thread.o cerror.o diff --git a/lib/librthread/rthread_sem.c b/lib/librthread/rthread_sem.c new file mode 100644 index 00000000000..ea855d5d1d3 --- /dev/null +++ b/lib/librthread/rthread_sem.c @@ -0,0 +1,202 @@ +/* $OpenBSD */ +/* + * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> + * All Rights Reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> + +#include "rthread.h" + +/* + * Internal implementation of semaphores + */ +int +_sem_wait(sem_t sem, int tryonly) +{ + + _spinlock(&sem->lock); + return (_sem_waitl(sem, tryonly, 0, NULL)); +} + +int +_sem_waitl(sem_t sem, int tryonly, clockid_t clock_id, + const struct timespec *abstime) +{ + int do_sleep; + +again: + if (sem->value == 0) { + if (tryonly) { + _spinunlock(&sem->lock); + return (0); + } + sem->waitcount++; + do_sleep = 1; + } else { + sem->value--; + do_sleep = 0; + } + + if (do_sleep) { + if (thrsleep(sem, clock_id, abstime, &sem->lock) == -1 && + errno == EWOULDBLOCK) + return (0); + _spinlock(&sem->lock); + sem->waitcount--; + goto again; + } + _spinunlock(&sem->lock); + return (1); +} + +/* always increment count */ +int +_sem_post(sem_t sem) +{ + int rv = 0; + + _spinlock(&sem->lock); + sem->value++; + if (sem->waitcount) { + thrwakeup(sem, 1); + rv = 1; + } + _spinunlock(&sem->lock); + return (rv); +} + +/* only increment count if a waiter */ +int +_sem_wakeup(sem_t sem) +{ + int rv = 0; + + _spinlock(&sem->lock); + if (sem->waitcount) { + sem->value++; + thrwakeup(sem, 1); + rv = 1; + } + _spinunlock(&sem->lock); + return (rv); +} + + +int +_sem_wakeall(sem_t sem) +{ + int rv; + + _spinlock(&sem->lock); + rv = sem->waitcount; + sem->value += rv; + thrwakeup(sem, 0); + _spinunlock(&sem->lock); + + return (rv); +} + +/* + * exported semaphores + */ +int +sem_init(sem_t *semp, int pshared, unsigned int value) +{ + sem_t sem; + + if (pshared) { + errno = EPERM; + return (-1); + } + + sem = calloc(1, sizeof(*sem)); + if (!sem) + return (-1); + sem->value = value; + *semp = sem; + + return (0); +} + +int +sem_destroy(sem_t *semp) +{ + if (!*semp) + return (EINVAL); + if ((*semp)->waitcount) { +#define MSG "sem_destroy on semaphore with waiters!\n" + write(2, MSG, sizeof(MSG) - 1); +#undef MSG + return (EBUSY); + } + free(*semp); + *semp = NULL; + + return (0); +} + +int +sem_getvalue(sem_t *semp, int *sval) +{ + sem_t sem = *semp; + + _spinlock(&sem->lock); + *sval = sem->value; + _spinunlock(&sem->lock); + + return (0); +} + +int +sem_post(sem_t *semp) +{ + sem_t sem = *semp; + + _sem_post(sem); + + return (0); +} + +int +sem_wait(sem_t *semp) +{ + sem_t sem = *semp; + + _sem_wait(sem, 0); + + return (0); +} + +int +sem_trywait(sem_t *semp) +{ + sem_t sem = *semp; + int rv; + + rv = _sem_wait(sem, 1); + + if (!rv) { + errno = EAGAIN; + return (-1); + } + + return (0); +} + diff --git a/lib/librthread/rthread_sync.c b/lib/librthread/rthread_sync.c index 1cc9aa0aa0b..cbe529a83aa 100644 --- a/lib/librthread/rthread_sync.c +++ b/lib/librthread/rthread_sync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_sync.c,v 1.27 2011/12/21 23:59:03 guenther Exp $ */ +/* $OpenBSD: rthread_sync.c,v 1.28 2012/01/04 17:43:34 mpi Exp $ */ /* * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org> * All Rights Reserved. @@ -16,7 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* - * Mutexes, conditions, and semaphores - synchronization functions. + * Mutexes and conditions - synchronization functions. */ @@ -31,182 +31,6 @@ static _spinlock_lock_t static_init_lock = _SPINLOCK_UNLOCKED; /* - * Internal implementation of semaphores - */ -int -_sem_wait(sem_t sem, int tryonly) -{ - - _spinlock(&sem->lock); - return (_sem_waitl(sem, tryonly, 0, NULL)); -} - -int -_sem_waitl(sem_t sem, int tryonly, clockid_t clock_id, - const struct timespec *abstime) -{ - int do_sleep; - -again: - if (sem->value == 0) { - if (tryonly) { - _spinunlock(&sem->lock); - return (0); - } - sem->waitcount++; - do_sleep = 1; - } else { - sem->value--; - do_sleep = 0; - } - - if (do_sleep) { - if (thrsleep(sem, clock_id, abstime, &sem->lock) == -1 && - errno == EWOULDBLOCK) - return (0); - _spinlock(&sem->lock); - sem->waitcount--; - goto again; - } - _spinunlock(&sem->lock); - return (1); -} - -/* always increment count */ -int -_sem_post(sem_t sem) -{ - int rv = 0; - - _spinlock(&sem->lock); - sem->value++; - if (sem->waitcount) { - thrwakeup(sem, 1); - rv = 1; - } - _spinunlock(&sem->lock); - return (rv); -} - -/* only increment count if a waiter */ -int -_sem_wakeup(sem_t sem) -{ - int rv = 0; - - _spinlock(&sem->lock); - if (sem->waitcount) { - sem->value++; - thrwakeup(sem, 1); - rv = 1; - } - _spinunlock(&sem->lock); - return (rv); -} - - -int -_sem_wakeall(sem_t sem) -{ - int rv; - - _spinlock(&sem->lock); - rv = sem->waitcount; - sem->value += rv; - thrwakeup(sem, 0); - _spinunlock(&sem->lock); - - return (rv); -} - -/* - * exported semaphores - */ -int -sem_init(sem_t *semp, int pshared, unsigned int value) -{ - sem_t sem; - - if (pshared) { - errno = EPERM; - return (-1); - } - - sem = calloc(1, sizeof(*sem)); - if (!sem) - return (-1); - sem->value = value; - *semp = sem; - - return (0); -} - -int -sem_destroy(sem_t *semp) -{ - if (!*semp) - return (EINVAL); - if ((*semp)->waitcount) { -#define MSG "sem_destroy on semaphore with waiters!\n" - write(2, MSG, sizeof(MSG) - 1); -#undef MSG - return (EBUSY); - } - free(*semp); - *semp = NULL; - - return (0); -} - -int -sem_getvalue(sem_t *semp, int *sval) -{ - sem_t sem = *semp; - - _spinlock(&sem->lock); - *sval = sem->value; - _spinunlock(&sem->lock); - - return (0); -} - -int -sem_post(sem_t *semp) -{ - sem_t sem = *semp; - - _sem_post(sem); - - return (0); -} - -int -sem_wait(sem_t *semp) -{ - sem_t sem = *semp; - - _sem_wait(sem, 0); - - return (0); -} - -int -sem_trywait(sem_t *semp) -{ - sem_t sem = *semp; - int rv; - - rv = _sem_wait(sem, 1); - - if (!rv) { - errno = EAGAIN; - return (-1); - } - - return (0); -} - -/* * mutexen */ int |