| Index: nspr/pr/src/threads/prrwlock.c
|
| diff --git a/nspr/pr/src/threads/prrwlock.c b/nspr/pr/src/threads/prrwlock.c
|
| deleted file mode 100644
|
| index 2e0f9ea4e833c50d801bb17fb326716b9149e011..0000000000000000000000000000000000000000
|
| --- a/nspr/pr/src/threads/prrwlock.c
|
| +++ /dev/null
|
| @@ -1,483 +0,0 @@
|
| -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
| -/* This Source Code Form is subject to the terms of the Mozilla Public
|
| - * License, v. 2.0. If a copy of the MPL was not distributed with this
|
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
| -
|
| -#include "primpl.h"
|
| -
|
| -#include <string.h>
|
| -
|
| -#if defined(HPUX) && defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
|
| -
|
| -#include <pthread.h>
|
| -#define HAVE_UNIX98_RWLOCK
|
| -#define RWLOCK_T pthread_rwlock_t
|
| -#define RWLOCK_INIT(lock) pthread_rwlock_init(lock, NULL)
|
| -#define RWLOCK_DESTROY(lock) pthread_rwlock_destroy(lock)
|
| -#define RWLOCK_RDLOCK(lock) pthread_rwlock_rdlock(lock)
|
| -#define RWLOCK_WRLOCK(lock) pthread_rwlock_wrlock(lock)
|
| -#define RWLOCK_UNLOCK(lock) pthread_rwlock_unlock(lock)
|
| -
|
| -#elif defined(SOLARIS) && (defined(_PR_PTHREADS) \
|
| - || defined(_PR_GLOBAL_THREADS_ONLY))
|
| -
|
| -#include <synch.h>
|
| -#define HAVE_UI_RWLOCK
|
| -#define RWLOCK_T rwlock_t
|
| -#define RWLOCK_INIT(lock) rwlock_init(lock, USYNC_THREAD, NULL)
|
| -#define RWLOCK_DESTROY(lock) rwlock_destroy(lock)
|
| -#define RWLOCK_RDLOCK(lock) rw_rdlock(lock)
|
| -#define RWLOCK_WRLOCK(lock) rw_wrlock(lock)
|
| -#define RWLOCK_UNLOCK(lock) rw_unlock(lock)
|
| -
|
| -#endif
|
| -
|
| -/*
|
| - * Reader-writer lock
|
| - */
|
| -struct PRRWLock {
|
| - char *rw_name; /* lock name */
|
| - PRUint32 rw_rank; /* rank of the lock */
|
| -
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - RWLOCK_T rw_lock;
|
| -#else
|
| - PRLock *rw_lock;
|
| - PRInt32 rw_lock_cnt; /* == 0, if unlocked */
|
| - /* == -1, if write-locked */
|
| - /* > 0 , # of read locks */
|
| - PRUint32 rw_reader_cnt; /* number of waiting readers */
|
| - PRUint32 rw_writer_cnt; /* number of waiting writers */
|
| - PRCondVar *rw_reader_waitq; /* cvar for readers */
|
| - PRCondVar *rw_writer_waitq; /* cvar for writers */
|
| -#ifdef DEBUG
|
| - PRThread *rw_owner; /* lock owner for write-lock */
|
| -#endif
|
| -#endif
|
| -};
|
| -
|
| -#ifdef DEBUG
|
| -#define _PR_RWLOCK_RANK_ORDER_DEBUG /* enable deadlock detection using
|
| - rank-order for locks
|
| - */
|
| -#endif
|
| -
|
| -#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| -
|
| -static PRUintn pr_thread_rwlock_key; /* TPD key for lock stack */
|
| -static PRUintn pr_thread_rwlock_alloc_failed;
|
| -
|
| -#define _PR_RWLOCK_RANK_ORDER_LIMIT 10
|
| -
|
| -typedef struct thread_rwlock_stack {
|
| - PRInt32 trs_index; /* top of stack */
|
| - PRRWLock *trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT]; /* stack of lock
|
| - pointers */
|
| -
|
| -} thread_rwlock_stack;
|
| -
|
| -static void _PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock);
|
| -static PRUint32 _PR_GET_THREAD_RWLOCK_RANK(void);
|
| -static void _PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock);
|
| -static void _PR_RELEASE_LOCK_STACK(void *lock_stack);
|
| -
|
| -#endif
|
| -
|
| -/*
|
| - * Reader/Writer Locks
|
| - */
|
| -
|
| -/*
|
| - * PR_NewRWLock
|
| - * Create a reader-writer lock, with the given lock rank and lock name
|
| - *
|
| - */
|
| -
|
| -PR_IMPLEMENT(PRRWLock *)
|
| -PR_NewRWLock(PRUint32 lock_rank, const char *lock_name)
|
| -{
|
| - PRRWLock *rwlock;
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - int err;
|
| -#endif
|
| -
|
| - if (!_pr_initialized) _PR_ImplicitInitialization();
|
| -
|
| - rwlock = PR_NEWZAP(PRRWLock);
|
| - if (rwlock == NULL)
|
| - return NULL;
|
| -
|
| - rwlock->rw_rank = lock_rank;
|
| - if (lock_name != NULL) {
|
| - rwlock->rw_name = (char*) PR_Malloc(strlen(lock_name) + 1);
|
| - if (rwlock->rw_name == NULL) {
|
| - PR_DELETE(rwlock);
|
| - return(NULL);
|
| - }
|
| - strcpy(rwlock->rw_name, lock_name);
|
| - } else {
|
| - rwlock->rw_name = NULL;
|
| - }
|
| -
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - err = RWLOCK_INIT(&rwlock->rw_lock);
|
| - if (err != 0) {
|
| - PR_SetError(PR_UNKNOWN_ERROR, err);
|
| - PR_Free(rwlock->rw_name);
|
| - PR_DELETE(rwlock);
|
| - return NULL;
|
| - }
|
| - return rwlock;
|
| -#else
|
| - rwlock->rw_lock = PR_NewLock();
|
| - if (rwlock->rw_lock == NULL) {
|
| - goto failed;
|
| - }
|
| - rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock);
|
| - if (rwlock->rw_reader_waitq == NULL) {
|
| - goto failed;
|
| - }
|
| - rwlock->rw_writer_waitq = PR_NewCondVar(rwlock->rw_lock);
|
| - if (rwlock->rw_writer_waitq == NULL) {
|
| - goto failed;
|
| - }
|
| - rwlock->rw_reader_cnt = 0;
|
| - rwlock->rw_writer_cnt = 0;
|
| - rwlock->rw_lock_cnt = 0;
|
| - return rwlock;
|
| -
|
| -failed:
|
| - if (rwlock->rw_reader_waitq != NULL) {
|
| - PR_DestroyCondVar(rwlock->rw_reader_waitq);
|
| - }
|
| - if (rwlock->rw_lock != NULL) {
|
| - PR_DestroyLock(rwlock->rw_lock);
|
| - }
|
| - PR_Free(rwlock->rw_name);
|
| - PR_DELETE(rwlock);
|
| - return NULL;
|
| -#endif
|
| -}
|
| -
|
| -/*
|
| -** Destroy the given RWLock "lock".
|
| -*/
|
| -PR_IMPLEMENT(void)
|
| -PR_DestroyRWLock(PRRWLock *rwlock)
|
| -{
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - int err;
|
| - err = RWLOCK_DESTROY(&rwlock->rw_lock);
|
| - PR_ASSERT(err == 0);
|
| -#else
|
| - PR_ASSERT(rwlock->rw_reader_cnt == 0);
|
| - PR_DestroyCondVar(rwlock->rw_reader_waitq);
|
| - PR_DestroyCondVar(rwlock->rw_writer_waitq);
|
| - PR_DestroyLock(rwlock->rw_lock);
|
| -#endif
|
| - if (rwlock->rw_name != NULL)
|
| - PR_Free(rwlock->rw_name);
|
| - PR_DELETE(rwlock);
|
| -}
|
| -
|
| -/*
|
| -** Read-lock the RWLock.
|
| -*/
|
| -PR_IMPLEMENT(void)
|
| -PR_RWLock_Rlock(PRRWLock *rwlock)
|
| -{
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| -int err;
|
| -#endif
|
| -
|
| -#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| - /*
|
| - * assert that rank ordering is not violated; the rank of 'rwlock' should
|
| - * be equal to or greater than the highest rank of all the locks held by
|
| - * the thread.
|
| - */
|
| - PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) ||
|
| - (rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK()));
|
| -#endif
|
| -
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - err = RWLOCK_RDLOCK(&rwlock->rw_lock);
|
| - PR_ASSERT(err == 0);
|
| -#else
|
| - PR_Lock(rwlock->rw_lock);
|
| - /*
|
| - * wait if write-locked or if a writer is waiting; preference for writers
|
| - */
|
| - while ((rwlock->rw_lock_cnt < 0) ||
|
| - (rwlock->rw_writer_cnt > 0)) {
|
| - rwlock->rw_reader_cnt++;
|
| - PR_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);
|
| - rwlock->rw_reader_cnt--;
|
| - }
|
| - /*
|
| - * Increment read-lock count
|
| - */
|
| - rwlock->rw_lock_cnt++;
|
| -
|
| - PR_Unlock(rwlock->rw_lock);
|
| -#endif
|
| -
|
| -#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| - /*
|
| - * update thread's lock rank
|
| - */
|
| - if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
|
| - _PR_SET_THREAD_RWLOCK_RANK(rwlock);
|
| -#endif
|
| -}
|
| -
|
| -/*
|
| -** Write-lock the RWLock.
|
| -*/
|
| -PR_IMPLEMENT(void)
|
| -PR_RWLock_Wlock(PRRWLock *rwlock)
|
| -{
|
| -#if defined(DEBUG)
|
| -PRThread *me = PR_GetCurrentThread();
|
| -#endif
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| -int err;
|
| -#endif
|
| -
|
| -#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| - /*
|
| - * assert that rank ordering is not violated; the rank of 'rwlock' should
|
| - * be equal to or greater than the highest rank of all the locks held by
|
| - * the thread.
|
| - */
|
| - PR_ASSERT((rwlock->rw_rank == PR_RWLOCK_RANK_NONE) ||
|
| - (rwlock->rw_rank >= _PR_GET_THREAD_RWLOCK_RANK()));
|
| -#endif
|
| -
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - err = RWLOCK_WRLOCK(&rwlock->rw_lock);
|
| - PR_ASSERT(err == 0);
|
| -#else
|
| - PR_Lock(rwlock->rw_lock);
|
| - /*
|
| - * wait if read locked
|
| - */
|
| - while (rwlock->rw_lock_cnt != 0) {
|
| - rwlock->rw_writer_cnt++;
|
| - PR_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT);
|
| - rwlock->rw_writer_cnt--;
|
| - }
|
| - /*
|
| - * apply write lock
|
| - */
|
| - rwlock->rw_lock_cnt--;
|
| - PR_ASSERT(rwlock->rw_lock_cnt == -1);
|
| -#ifdef DEBUG
|
| - PR_ASSERT(me != NULL);
|
| - rwlock->rw_owner = me;
|
| -#endif
|
| - PR_Unlock(rwlock->rw_lock);
|
| -#endif
|
| -
|
| -#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| - /*
|
| - * update thread's lock rank
|
| - */
|
| - if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
|
| - _PR_SET_THREAD_RWLOCK_RANK(rwlock);
|
| -#endif
|
| -}
|
| -
|
| -/*
|
| -** Unlock the RW lock.
|
| -*/
|
| -PR_IMPLEMENT(void)
|
| -PR_RWLock_Unlock(PRRWLock *rwlock)
|
| -{
|
| -#if defined(DEBUG)
|
| -PRThread *me = PR_GetCurrentThread();
|
| -#endif
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| -int err;
|
| -#endif
|
| -
|
| -#if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK)
|
| - err = RWLOCK_UNLOCK(&rwlock->rw_lock);
|
| - PR_ASSERT(err == 0);
|
| -#else
|
| - PR_Lock(rwlock->rw_lock);
|
| - /*
|
| - * lock must be read or write-locked
|
| - */
|
| - PR_ASSERT(rwlock->rw_lock_cnt != 0);
|
| - if (rwlock->rw_lock_cnt > 0) {
|
| -
|
| - /*
|
| - * decrement read-lock count
|
| - */
|
| - rwlock->rw_lock_cnt--;
|
| - if (rwlock->rw_lock_cnt == 0) {
|
| - /*
|
| - * lock is not read-locked anymore; wakeup a waiting writer
|
| - */
|
| - if (rwlock->rw_writer_cnt > 0)
|
| - PR_NotifyCondVar(rwlock->rw_writer_waitq);
|
| - }
|
| - } else {
|
| - PR_ASSERT(rwlock->rw_lock_cnt == -1);
|
| -
|
| - rwlock->rw_lock_cnt = 0;
|
| -#ifdef DEBUG
|
| - PR_ASSERT(rwlock->rw_owner == me);
|
| - rwlock->rw_owner = NULL;
|
| -#endif
|
| - /*
|
| - * wakeup a writer, if present; preference for writers
|
| - */
|
| - if (rwlock->rw_writer_cnt > 0)
|
| - PR_NotifyCondVar(rwlock->rw_writer_waitq);
|
| - /*
|
| - * else, wakeup all readers, if any
|
| - */
|
| - else if (rwlock->rw_reader_cnt > 0)
|
| - PR_NotifyAllCondVar(rwlock->rw_reader_waitq);
|
| - }
|
| - PR_Unlock(rwlock->rw_lock);
|
| -#endif
|
| -
|
| -#ifdef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| - /*
|
| - * update thread's lock rank
|
| - */
|
| - if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE)
|
| - _PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
|
| -#endif
|
| - return;
|
| -}
|
| -
|
| -#ifndef _PR_RWLOCK_RANK_ORDER_DEBUG
|
| -
|
| -void _PR_InitRWLocks(void) { }
|
| -
|
| -#else
|
| -
|
| -void _PR_InitRWLocks(void)
|
| -{
|
| - /*
|
| - * allocated thread-private-data index for rwlock list
|
| - */
|
| - if (PR_NewThreadPrivateIndex(&pr_thread_rwlock_key,
|
| - _PR_RELEASE_LOCK_STACK) == PR_FAILURE) {
|
| - pr_thread_rwlock_alloc_failed = 1;
|
| - return;
|
| - }
|
| -}
|
| -
|
| -/*
|
| - * _PR_SET_THREAD_RWLOCK_RANK
|
| - * Set a thread's lock rank, which is the highest of the ranks of all
|
| - * the locks held by the thread. Pointers to the locks are added to a
|
| - * per-thread list, which is anchored off a thread-private data key.
|
| - */
|
| -
|
| -static void
|
| -_PR_SET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
|
| -{
|
| -thread_rwlock_stack *lock_stack;
|
| -PRStatus rv;
|
| -
|
| - /*
|
| - * allocate a lock stack
|
| - */
|
| - if ((lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key)) == NULL) {
|
| - lock_stack = (thread_rwlock_stack *)
|
| - PR_CALLOC(1 * sizeof(thread_rwlock_stack));
|
| - if (lock_stack) {
|
| - rv = PR_SetThreadPrivate(pr_thread_rwlock_key, lock_stack);
|
| - if (rv == PR_FAILURE) {
|
| - PR_DELETE(lock_stack);
|
| - pr_thread_rwlock_alloc_failed = 1;
|
| - return;
|
| - }
|
| - } else {
|
| - pr_thread_rwlock_alloc_failed = 1;
|
| - return;
|
| - }
|
| - }
|
| - /*
|
| - * add rwlock to lock stack, if limit is not exceeded
|
| - */
|
| - if (lock_stack) {
|
| - if (lock_stack->trs_index < _PR_RWLOCK_RANK_ORDER_LIMIT)
|
| - lock_stack->trs_stack[lock_stack->trs_index++] = rwlock;
|
| - }
|
| -}
|
| -
|
| -static void
|
| -_PR_RELEASE_LOCK_STACK(void *lock_stack)
|
| -{
|
| - PR_ASSERT(lock_stack);
|
| - PR_DELETE(lock_stack);
|
| -}
|
| -
|
| -/*
|
| - * _PR_GET_THREAD_RWLOCK_RANK
|
| - *
|
| - * return thread's lock rank. If thread-private-data for the lock
|
| - * stack is not allocated, return PR_RWLOCK_RANK_NONE.
|
| - */
|
| -
|
| -static PRUint32
|
| -_PR_GET_THREAD_RWLOCK_RANK(void)
|
| -{
|
| - thread_rwlock_stack *lock_stack;
|
| -
|
| - lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);
|
| - if (lock_stack == NULL || lock_stack->trs_index == 0)
|
| - return (PR_RWLOCK_RANK_NONE);
|
| - else
|
| - return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank);
|
| -}
|
| -
|
| -/*
|
| - * _PR_UNSET_THREAD_RWLOCK_RANK
|
| - *
|
| - * remove the rwlock from the lock stack. Since locks may not be
|
| - * unlocked in a FIFO order, the entire lock stack is searched.
|
| - */
|
| -
|
| -static void
|
| -_PR_UNSET_THREAD_RWLOCK_RANK(PRRWLock *rwlock)
|
| -{
|
| - thread_rwlock_stack *lock_stack;
|
| - int new_index = 0, index, done = 0;
|
| -
|
| - lock_stack = PR_GetThreadPrivate(pr_thread_rwlock_key);
|
| -
|
| - PR_ASSERT(lock_stack != NULL);
|
| -
|
| - for (index = lock_stack->trs_index - 1; index >= 0; index--) {
|
| - if (!done && (lock_stack->trs_stack[index] == rwlock)) {
|
| - /*
|
| - * reset the slot for rwlock
|
| - */
|
| - lock_stack->trs_stack[index] = NULL;
|
| - done = 1;
|
| - }
|
| - /*
|
| - * search for the lowest-numbered empty slot, above which there are
|
| - * no non-empty slots
|
| - */
|
| - if (!new_index && (lock_stack->trs_stack[index] != NULL))
|
| - new_index = index + 1;
|
| - if (done && new_index)
|
| - break;
|
| - }
|
| - /*
|
| - * set top of stack to highest numbered empty slot
|
| - */
|
| - lock_stack->trs_index = new_index;
|
| -
|
| -}
|
| -
|
| -#endif /* _PR_RWLOCK_RANK_ORDER_DEBUG */
|
|
|