diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-12-21 23:59:04 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-12-21 23:59:04 +0000 |
commit | d9368ef69de420c7613a640d9d62c5376674eb5a (patch) | |
tree | 39cc4edd2d1d310b20b76d1f69f4df444a74e135 /lib | |
parent | 479071d116be1efbac3dd9be5b49f5f2f3e24c64 (diff) |
Split out the pthread_rwlock* and pthread_once() functions from rthread_sync.c
to new files rthread_rwlock.c, rthread_rwlockattr.c, and rthread_once.c
Diffstat (limited to 'lib')
-rw-r--r-- | lib/librthread/Makefile | 5 | ||||
-rw-r--r-- | lib/librthread/rthread_once.c | 32 | ||||
-rw-r--r-- | lib/librthread/rthread_rwlock.c | 262 | ||||
-rw-r--r-- | lib/librthread/rthread_rwlockattr.c | 51 | ||||
-rw-r--r-- | lib/librthread/rthread_sync.c | 277 |
5 files changed, 350 insertions, 277 deletions
diff --git a/lib/librthread/Makefile b/lib/librthread/Makefile index 3e5bfd8e64a..768cd36dadd 100644 --- a/lib/librthread/Makefile +++ b/lib/librthread/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.20 2011/12/21 00:49:47 guenther Exp $ +# $OpenBSD: Makefile,v 1.21 2011/12/21 23:59:03 guenther Exp $ LIB=rthread WANTLINT= @@ -14,7 +14,8 @@ LDADD = -Wl,-znodelete,-zinitfirst 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_cancel.c rthread_mutexattr.c rthread_once.c \ + rthread_rwlock.c rthread_rwlockattr.c OBJS+= _atomic_lock.o rfork_thread.o cerror.o diff --git a/lib/librthread/rthread_once.c b/lib/librthread/rthread_once.c new file mode 100644 index 00000000000..cb5ea8a948f --- /dev/null +++ b/lib/librthread/rthread_once.c @@ -0,0 +1,32 @@ +/* $OpenBSD: rthread_once.c,v 1.1 2011/12/21 23:59:03 guenther Exp $ */ +/* + * 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 <pthread.h> + +int +pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) +{ + pthread_mutex_lock(&once_control->mutex); + if (once_control->state == PTHREAD_NEEDS_INIT) { + init_routine(); + once_control->state = PTHREAD_DONE_INIT; + } + pthread_mutex_unlock(&once_control->mutex); + + return (0); +} diff --git a/lib/librthread/rthread_rwlock.c b/lib/librthread/rthread_rwlock.c new file mode 100644 index 00000000000..0d391fe9afd --- /dev/null +++ b/lib/librthread/rthread_rwlock.c @@ -0,0 +1,262 @@ +/* $OpenBSD: rthread_rwlock.c,v 1.1 2011/12/21 23:59:03 guenther Exp $ */ +/* + * 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. + */ +/* + * rwlocks + */ + + +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> + +#include "rthread.h" + + +static _spinlock_lock_t rwlock_init_lock = _SPINLOCK_UNLOCKED; + +int +pthread_rwlock_init(pthread_rwlock_t *lockp, const pthread_rwlockattr_t *attrp) +{ + pthread_rwlock_t lock; + + lock = calloc(1, sizeof(*lock)); + if (!lock) + return (errno); + lock->lock = _SPINLOCK_UNLOCKED; + lock->sem.lock = _SPINLOCK_UNLOCKED; + *lockp = lock; + + return (0); +} + +int +pthread_rwlock_destroy(pthread_rwlock_t *lockp) +{ + if ((*lockp) && ((*lockp)->readers || (*lockp)->writer)) { +#define MSG "pthread_rwlock_destroy on rwlock with waiters!\n" + write(2, MSG, sizeof(MSG) - 1); +#undef MSG + return (EBUSY); + } + free(*lockp); + *lockp = NULL; + + return (0); +} + +static int +_rthread_rwlock_ensure_init(pthread_rwlock_t *lockp) +{ + int ret = 0; + + /* + * If the rwlock is statically initialized, perform the dynamic + * initialization. + */ + if (*lockp == NULL) + { + _spinlock(&rwlock_init_lock); + if (*lockp == NULL) + ret = pthread_rwlock_init(lockp, NULL); + _spinunlock(&rwlock_init_lock); + } + return (ret); +} + + +int +pthread_rwlock_rdlock(pthread_rwlock_t *lockp) +{ + pthread_rwlock_t lock; + int error; + + if ((error = _rthread_rwlock_ensure_init(lockp))) + return (error); + + lock = *lockp; +again: + _spinlock(&lock->lock); + if (lock->writer) { + _spinlock(&lock->sem.lock); + _spinunlock(&lock->lock); + _sem_waitl(&lock->sem, 0, 0, NULL); + goto again; + } + lock->readers++; + _spinunlock(&lock->lock); + + return (0); +} + +int +pthread_rwlock_timedrdlock(pthread_rwlock_t *lockp, + const struct timespec *abstime) +{ + pthread_rwlock_t lock; + int do_wait = 1; + int error; + + if ((error = _rthread_rwlock_ensure_init(lockp))) + return (error); + + lock = *lockp; + _spinlock(&lock->lock); + while (lock->writer && do_wait) { + _spinlock(&lock->sem.lock); + _spinunlock(&lock->lock); + do_wait = _sem_waitl(&lock->sem, 0, CLOCK_REALTIME, abstime); + _spinlock(&lock->lock); + } + if (lock->writer) { + /* do_wait must be 0, so timed out */ + _spinunlock(&lock->lock); + return (ETIMEDOUT); + } + lock->readers++; + _spinunlock(&lock->lock); + + return (0); +} + +int +pthread_rwlock_tryrdlock(pthread_rwlock_t *lockp) +{ + pthread_rwlock_t lock; + int error; + + if ((error = _rthread_rwlock_ensure_init(lockp))) + return (error); + + lock = *lockp; + + _spinlock(&lock->lock); + if (lock->writer) { + _spinunlock(&lock->lock); + return (EBUSY); + } + lock->readers++; + _spinunlock(&lock->lock); + + return (0); +} + +int +pthread_rwlock_wrlock(pthread_rwlock_t *lockp) +{ + pthread_rwlock_t lock; + int error; + + if ((error = _rthread_rwlock_ensure_init(lockp))) + return (error); + + lock = *lockp; + + _spinlock(&lock->lock); + lock->writer++; + while (lock->readers) { + _spinlock(&lock->sem.lock); + _spinunlock(&lock->lock); + _sem_waitl(&lock->sem, 0, 0, NULL); + _spinlock(&lock->lock); + } + lock->readers = -pthread_self()->tid; + _spinunlock(&lock->lock); + + return (0); +} + +int +pthread_rwlock_timedwrlock(pthread_rwlock_t *lockp, + const struct timespec *abstime) +{ + pthread_rwlock_t lock; + int do_wait = 1; + int error; + + if ((error = _rthread_rwlock_ensure_init(lockp))) + return (error); + + lock = *lockp; + + _spinlock(&lock->lock); + lock->writer++; + while (lock->readers && do_wait) { + _spinlock(&lock->sem.lock); + _spinunlock(&lock->lock); + do_wait = _sem_waitl(&lock->sem, 0, CLOCK_REALTIME, abstime); + _spinlock(&lock->lock); + } + if (lock->readers) { + /* do_wait must be 0, so timed out */ + lock->writer--; + _spinunlock(&lock->lock); + return (ETIMEDOUT); + } + lock->readers = -pthread_self()->tid; + _spinunlock(&lock->lock); + + return (0); +} + +int +pthread_rwlock_trywrlock(pthread_rwlock_t *lockp) +{ + pthread_rwlock_t lock; + int error; + + if ((error = _rthread_rwlock_ensure_init(lockp))) + return (error); + + lock = *lockp; + + _spinlock(&lock->lock); + if (lock->readers || lock->writer) { + _spinunlock(&lock->lock); + return (EBUSY); + } + lock->writer = 1; + lock->readers = -pthread_self()->tid; + _spinunlock(&lock->lock); + + return (0); +} + +int +pthread_rwlock_unlock(pthread_rwlock_t *lockp) +{ + pthread_rwlock_t lock; + + lock = *lockp; + + _spinlock(&lock->lock); + if (lock->readers == -pthread_self()->tid) { + lock->readers = 0; + lock->writer--; + } else if (lock->readers > 0) { + lock->readers--; + } else { + _spinunlock(&lock->lock); + return (EPERM); + } + _spinunlock(&lock->lock); + _sem_wakeall(&lock->sem); + + return (0); +} diff --git a/lib/librthread/rthread_rwlockattr.c b/lib/librthread/rthread_rwlockattr.c new file mode 100644 index 00000000000..2c611758ce9 --- /dev/null +++ b/lib/librthread/rthread_rwlockattr.c @@ -0,0 +1,51 @@ +/* $OpenBSD: rthread_rwlockattr.c,v 1.1 2011/12/21 23:59:03 guenther Exp $ */ +/* + * 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. + */ +/* + * rwlock attributes + */ + + +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> + +#include <pthread.h> + +#include "rthread.h" + +int +pthread_rwlockattr_init(pthread_rwlockattr_t *attrp) +{ + pthread_rwlockattr_t attr; + + attr = calloc(1, sizeof(*attr)); + if (!attr) + return (errno); + *attrp = attr; + + return (0); +} + +int +pthread_rwlockattr_destroy(pthread_rwlockattr_t *attrp) +{ + free(*attrp); + *attrp = NULL; + + return (0); +} diff --git a/lib/librthread/rthread_sync.c b/lib/librthread/rthread_sync.c index 502ad04fe9e..1cc9aa0aa0b 100644 --- a/lib/librthread/rthread_sync.c +++ b/lib/librthread/rthread_sync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_sync.c,v 1.26 2011/12/21 00:49:47 guenther Exp $ */ +/* $OpenBSD: rthread_sync.c,v 1.27 2011/12/21 23:59:03 guenther 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, rwlocks, and semaphores - synchronization functions. + * Mutexes, conditions, and semaphores - synchronization functions. */ @@ -417,276 +417,3 @@ pthread_condattr_destroy(pthread_condattr_t *attrp) return (0); } -/* - * rwlocks - */ -int -pthread_rwlock_init(pthread_rwlock_t *lockp, const pthread_rwlockattr_t *attrp) -{ - pthread_rwlock_t lock; - - lock = calloc(1, sizeof(*lock)); - if (!lock) - return (errno); - lock->lock = _SPINLOCK_UNLOCKED; - lock->sem.lock = _SPINLOCK_UNLOCKED; - *lockp = lock; - - return (0); -} - -int -pthread_rwlock_destroy(pthread_rwlock_t *lockp) -{ - if ((*lockp) && ((*lockp)->readers || (*lockp)->writer)) { -#define MSG "pthread_rwlock_destroy on rwlock with waiters!\n" - write(2, MSG, sizeof(MSG) - 1); -#undef MSG - return (EBUSY); - } - free(*lockp); - *lockp = NULL; - - return (0); -} - -static int -_rthread_rwlock_ensure_init(pthread_rwlock_t *lockp) -{ - int ret = 0; - - /* - * If the rwlock is statically initialized, perform the dynamic - * initialization. - */ - if (*lockp == NULL) - { - _spinlock(&static_init_lock); - if (*lockp == NULL) - ret = pthread_rwlock_init(lockp, NULL); - _spinunlock(&static_init_lock); - } - return (ret); -} - - -int -pthread_rwlock_rdlock(pthread_rwlock_t *lockp) -{ - pthread_rwlock_t lock; - int error; - - if ((error = _rthread_rwlock_ensure_init(lockp))) - return (error); - - lock = *lockp; -again: - _spinlock(&lock->lock); - if (lock->writer) { - _spinlock(&lock->sem.lock); - _spinunlock(&lock->lock); - _sem_waitl(&lock->sem, 0, 0, NULL); - goto again; - } - lock->readers++; - _spinunlock(&lock->lock); - - return (0); -} - -int -pthread_rwlock_timedrdlock(pthread_rwlock_t *lockp, - const struct timespec *abstime) -{ - pthread_rwlock_t lock; - int do_wait = 1; - int error; - - if ((error = _rthread_rwlock_ensure_init(lockp))) - return (error); - - lock = *lockp; - _spinlock(&lock->lock); - while (lock->writer && do_wait) { - _spinlock(&lock->sem.lock); - _spinunlock(&lock->lock); - do_wait = _sem_waitl(&lock->sem, 0, CLOCK_REALTIME, abstime); - _spinlock(&lock->lock); - } - if (lock->writer) { - /* do_wait must be 0, so timed out */ - _spinunlock(&lock->lock); - return (ETIMEDOUT); - } - lock->readers++; - _spinunlock(&lock->lock); - - return (0); -} - -int -pthread_rwlock_tryrdlock(pthread_rwlock_t *lockp) -{ - pthread_rwlock_t lock; - int error; - - if ((error = _rthread_rwlock_ensure_init(lockp))) - return (error); - - lock = *lockp; - - _spinlock(&lock->lock); - if (lock->writer) { - _spinunlock(&lock->lock); - return (EBUSY); - } - lock->readers++; - _spinunlock(&lock->lock); - - return (0); -} - -int -pthread_rwlock_wrlock(pthread_rwlock_t *lockp) -{ - pthread_rwlock_t lock; - int error; - - if ((error = _rthread_rwlock_ensure_init(lockp))) - return (error); - - lock = *lockp; - - _spinlock(&lock->lock); - lock->writer++; - while (lock->readers) { - _spinlock(&lock->sem.lock); - _spinunlock(&lock->lock); - _sem_waitl(&lock->sem, 0, 0, NULL); - _spinlock(&lock->lock); - } - lock->readers = -pthread_self()->tid; - _spinunlock(&lock->lock); - - return (0); -} - -int -pthread_rwlock_timedwrlock(pthread_rwlock_t *lockp, - const struct timespec *abstime) -{ - pthread_rwlock_t lock; - int do_wait = 1; - int error; - - if ((error = _rthread_rwlock_ensure_init(lockp))) - return (error); - - lock = *lockp; - - _spinlock(&lock->lock); - lock->writer++; - while (lock->readers && do_wait) { - _spinlock(&lock->sem.lock); - _spinunlock(&lock->lock); - do_wait = _sem_waitl(&lock->sem, 0, CLOCK_REALTIME, abstime); - _spinlock(&lock->lock); - } - if (lock->readers) { - /* do_wait must be 0, so timed out */ - lock->writer--; - _spinunlock(&lock->lock); - return (ETIMEDOUT); - } - lock->readers = -pthread_self()->tid; - _spinunlock(&lock->lock); - - return (0); -} - -int -pthread_rwlock_trywrlock(pthread_rwlock_t *lockp) -{ - pthread_rwlock_t lock; - int error; - - if ((error = _rthread_rwlock_ensure_init(lockp))) - return (error); - - lock = *lockp; - - _spinlock(&lock->lock); - if (lock->readers || lock->writer) { - _spinunlock(&lock->lock); - return (EBUSY); - } - lock->writer = 1; - lock->readers = -pthread_self()->tid; - _spinunlock(&lock->lock); - - return (0); -} - -int -pthread_rwlock_unlock(pthread_rwlock_t *lockp) -{ - pthread_rwlock_t lock; - - lock = *lockp; - - _spinlock(&lock->lock); - if (lock->readers == -pthread_self()->tid) { - lock->readers = 0; - lock->writer--; - } else if (lock->readers > 0) { - lock->readers--; - } else { - _spinunlock(&lock->lock); - return (EPERM); - } - _spinunlock(&lock->lock); - _sem_wakeall(&lock->sem); - - return (0); -} - -/* - * rwlock attributes - */ -int -pthread_rwlockattr_init(pthread_rwlockattr_t *attrp) -{ - pthread_rwlockattr_t attr; - - attr = calloc(1, sizeof(*attr)); - if (!attr) - return (errno); - *attrp = attr; - - return (0); -} - -int -pthread_rwlockattr_destroy(pthread_rwlockattr_t *attrp) -{ - free(*attrp); - *attrp = NULL; - - return (0); -} - -/* - * pthread_once - */ -int -pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) -{ - pthread_mutex_lock(&once_control->mutex); - if (once_control->state == PTHREAD_NEEDS_INIT) { - init_routine(); - once_control->state = PTHREAD_DONE_INIT; - } - pthread_mutex_unlock(&once_control->mutex); - - return (0); -} |