diff options
Diffstat (limited to 'lib/libc_r/uthread/uthread_rwlock.c')
-rw-r--r-- | lib/libc_r/uthread/uthread_rwlock.c | 379 |
1 files changed, 0 insertions, 379 deletions
diff --git a/lib/libc_r/uthread/uthread_rwlock.c b/lib/libc_r/uthread/uthread_rwlock.c deleted file mode 100644 index fdda04c..0000000 --- a/lib/libc_r/uthread/uthread_rwlock.c +++ /dev/null @@ -1,379 +0,0 @@ -/*- - * Copyright (c) 1998 Alex Nash - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include <errno.h> -#include <limits.h> -#include <stdlib.h> - -#include "namespace.h" -#include <pthread.h> -#include "un-namespace.h" - -#include "pthread_private.h" - -/* maximum number of times a read lock may be obtained */ -#define MAX_READ_LOCKS (INT_MAX - 1) - -__weak_reference(_pthread_rwlock_destroy, pthread_rwlock_destroy); -__weak_reference(_pthread_rwlock_init, pthread_rwlock_init); -__weak_reference(_pthread_rwlock_rdlock, pthread_rwlock_rdlock); -__weak_reference(_pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock); -__weak_reference(_pthread_rwlock_trywrlock, pthread_rwlock_trywrlock); -__weak_reference(_pthread_rwlock_unlock, pthread_rwlock_unlock); -__weak_reference(_pthread_rwlock_wrlock, pthread_rwlock_wrlock); - -static int init_static (pthread_rwlock_t *rwlock); - -static spinlock_t static_init_lock = _SPINLOCK_INITIALIZER; - -static int -init_static (pthread_rwlock_t *rwlock) -{ - int ret; - - _SPINLOCK(&static_init_lock); - - if (*rwlock == NULL) - ret = _pthread_rwlock_init(rwlock, NULL); - else - ret = 0; - - _SPINUNLOCK(&static_init_lock); - - return (ret); -} - -int -_pthread_rwlock_destroy (pthread_rwlock_t *rwlock) -{ - int ret; - - if (rwlock == NULL) - ret = EINVAL; - else { - pthread_rwlock_t prwlock; - - prwlock = *rwlock; - - _pthread_mutex_destroy(&prwlock->lock); - _pthread_cond_destroy(&prwlock->read_signal); - _pthread_cond_destroy(&prwlock->write_signal); - free(prwlock); - - *rwlock = NULL; - - ret = 0; - } - return (ret); -} - -int -_pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) -{ - pthread_rwlock_t prwlock; - int ret; - - /* allocate rwlock object */ - prwlock = (pthread_rwlock_t)malloc(sizeof(struct pthread_rwlock)); - - if (prwlock == NULL) - return(ENOMEM); - - /* initialize the lock */ - if ((ret = _pthread_mutex_init(&prwlock->lock, NULL)) != 0) - free(prwlock); - else { - /* initialize the read condition signal */ - ret = _pthread_cond_init(&prwlock->read_signal, NULL); - - if (ret != 0) { - _pthread_mutex_destroy(&prwlock->lock); - free(prwlock); - } else { - /* initialize the write condition signal */ - ret = _pthread_cond_init(&prwlock->write_signal, NULL); - - if (ret != 0) { - _pthread_cond_destroy(&prwlock->read_signal); - _pthread_mutex_destroy(&prwlock->lock); - free(prwlock); - } else { - /* success */ - prwlock->state = 0; - prwlock->blocked_writers = 0; - - *rwlock = prwlock; - } - } - } - - return (ret); -} - -int -_pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) -{ - pthread_rwlock_t prwlock; - struct pthread *curthread; - int ret; - - if (rwlock == NULL) - return(EINVAL); - - prwlock = *rwlock; - - /* check for static initialization */ - if (prwlock == NULL) { - if ((ret = init_static(rwlock)) != 0) - return(ret); - - prwlock = *rwlock; - } - - /* grab the monitor lock */ - if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) - return(ret); - - /* check lock count */ - if (prwlock->state == MAX_READ_LOCKS) { - _pthread_mutex_unlock(&prwlock->lock); - return (EAGAIN); - } - - curthread = _get_curthread(); - if ((curthread->rdlock_count > 0) && (prwlock->state > 0)) { - /* - * To avoid having to track all the rdlocks held by - * a thread or all of the threads that hold a rdlock, - * we keep a simple count of all the rdlocks held by - * a thread. If a thread holds any rdlocks it is - * possible that it is attempting to take a recursive - * rdlock. If there are blocked writers and precedence - * is given to them, then that would result in the thread - * deadlocking. So allowing a thread to take the rdlock - * when it already has one or more rdlocks avoids the - * deadlock. I hope the reader can follow that logic ;-) - */ - ; /* nothing needed */ - } else { - /* give writers priority over readers */ - while (prwlock->blocked_writers || prwlock->state < 0) { - ret = _pthread_cond_wait(&prwlock->read_signal, - &prwlock->lock); - - if (ret != 0) { - /* can't do a whole lot if this fails */ - _pthread_mutex_unlock(&prwlock->lock); - return(ret); - } - } - } - - curthread->rdlock_count++; - prwlock->state++; /* indicate we are locked for reading */ - - /* - * Something is really wrong if this call fails. Returning - * error won't do because we've already obtained the read - * lock. Decrementing 'state' is no good because we probably - * don't have the monitor lock. - */ - _pthread_mutex_unlock(&prwlock->lock); - - return (ret); -} - -int -_pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) -{ - pthread_rwlock_t prwlock; - struct pthread *curthread; - int ret; - - if (rwlock == NULL) - return(EINVAL); - - prwlock = *rwlock; - - /* check for static initialization */ - if (prwlock == NULL) { - if ((ret = init_static(rwlock)) != 0) - return(ret); - - prwlock = *rwlock; - } - - /* grab the monitor lock */ - if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) - return(ret); - - curthread = _get_curthread(); - if (prwlock->state == MAX_READ_LOCKS) - ret = EAGAIN; /* too many read locks acquired */ - else if ((curthread->rdlock_count > 0) && (prwlock->state > 0)) { - /* see comment for pthread_rwlock_rdlock() */ - curthread->rdlock_count++; - prwlock->state++; - } - /* give writers priority over readers */ - else if (prwlock->blocked_writers || prwlock->state < 0) - ret = EBUSY; - else { - prwlock->state++; /* indicate we are locked for reading */ - curthread->rdlock_count++; - } - - /* see the comment on this in pthread_rwlock_rdlock */ - _pthread_mutex_unlock(&prwlock->lock); - - return (ret); -} - -int -_pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) -{ - pthread_rwlock_t prwlock; - int ret; - - if (rwlock == NULL) - return(EINVAL); - - prwlock = *rwlock; - - /* check for static initialization */ - if (prwlock == NULL) { - if ((ret = init_static(rwlock)) != 0) - return(ret); - - prwlock = *rwlock; - } - - /* grab the monitor lock */ - if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) - return(ret); - - if (prwlock->state != 0) - ret = EBUSY; - else - /* indicate we are locked for writing */ - prwlock->state = -1; - - /* see the comment on this in pthread_rwlock_rdlock */ - _pthread_mutex_unlock(&prwlock->lock); - - return (ret); -} - -int -_pthread_rwlock_unlock (pthread_rwlock_t *rwlock) -{ - pthread_rwlock_t prwlock; - struct pthread *curthread; - int ret; - - if (rwlock == NULL) - return(EINVAL); - - prwlock = *rwlock; - - if (prwlock == NULL) - return(EINVAL); - - /* grab the monitor lock */ - if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) - return(ret); - - curthread = _get_curthread(); - if (prwlock->state > 0) { - curthread->rdlock_count--; - prwlock->state--; - if (prwlock->state == 0 && prwlock->blocked_writers) - ret = _pthread_cond_signal(&prwlock->write_signal); - } else if (prwlock->state < 0) { - prwlock->state = 0; - - if (prwlock->blocked_writers) - ret = _pthread_cond_signal(&prwlock->write_signal); - else - ret = _pthread_cond_broadcast(&prwlock->read_signal); - } else - ret = EINVAL; - - /* see the comment on this in pthread_rwlock_rdlock */ - _pthread_mutex_unlock(&prwlock->lock); - - return (ret); -} - -int -_pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) -{ - pthread_rwlock_t prwlock; - int ret; - - if (rwlock == NULL) - return(EINVAL); - - prwlock = *rwlock; - - /* check for static initialization */ - if (prwlock == NULL) { - if ((ret = init_static(rwlock)) != 0) - return(ret); - - prwlock = *rwlock; - } - - /* grab the monitor lock */ - if ((ret = _pthread_mutex_lock(&prwlock->lock)) != 0) - return(ret); - - while (prwlock->state != 0) { - prwlock->blocked_writers++; - - ret = _pthread_cond_wait(&prwlock->write_signal, - &prwlock->lock); - - if (ret != 0) { - prwlock->blocked_writers--; - _pthread_mutex_unlock(&prwlock->lock); - return(ret); - } - - prwlock->blocked_writers--; - } - - /* indicate we are locked for writing */ - prwlock->state = -1; - - /* see the comment on this in pthread_rwlock_rdlock */ - _pthread_mutex_unlock(&prwlock->lock); - - return (ret); -} - |