diff options
Diffstat (limited to 'nsprpub/pr/src/threads/prrwlock.c')
-rw-r--r-- | nsprpub/pr/src/threads/prrwlock.c | 559 |
1 files changed, 287 insertions, 272 deletions
diff --git a/nsprpub/pr/src/threads/prrwlock.c b/nsprpub/pr/src/threads/prrwlock.c index 1dd9e0a90..0cb51e5bd 100644 --- a/nsprpub/pr/src/threads/prrwlock.c +++ b/nsprpub/pr/src/threads/prrwlock.c @@ -36,43 +36,43 @@ * Reader-writer lock */ struct PRRWLock { - char *rw_name; /* lock name */ - PRUint32 rw_rank; /* rank of the lock */ + 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; + 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 */ + 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 */ + 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 - */ +#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; +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 +#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 */ + PRInt32 trs_index; /* top of stack */ + PRRWLock *trs_stack[_PR_RWLOCK_RANK_ORDER_LIMIT]; /* stack of lock + pointers */ } thread_rwlock_stack; @@ -89,8 +89,8 @@ static void _PR_RELEASE_LOCK_STACK(void *lock_stack); /* * PR_NewRWLock - * Create a reader-writer lock, with the given lock rank and lock name - * + * Create a reader-writer lock, with the given lock rank and lock name + * */ PR_IMPLEMENT(PRRWLock *) @@ -98,64 +98,67 @@ PR_NewRWLock(PRUint32 lock_rank, const char *lock_name) { PRRWLock *rwlock; #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) - int err; + int err; #endif - if (!_pr_initialized) _PR_ImplicitInitialization(); + 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 (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; + 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(); + rwlock->rw_lock = PR_NewLock(); if (rwlock->rw_lock == NULL) { - goto failed; - } - rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock); + 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); + 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; + 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; + 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 } @@ -166,17 +169,18 @@ 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); + 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); + 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); + if (rwlock->rw_name != NULL) { + PR_Free(rwlock->rw_name); + } PR_DELETE(rwlock); } @@ -187,47 +191,48 @@ PR_IMPLEMENT(void) PR_RWLock_Rlock(PRRWLock *rwlock) { #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) -int err; + 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())); + /* + * 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); + 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); + 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); + /* + * update thread's lock rank + */ + if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE) { + _PR_SET_THREAD_RWLOCK_RANK(rwlock); + } #endif } @@ -238,53 +243,54 @@ PR_IMPLEMENT(void) PR_RWLock_Wlock(PRRWLock *rwlock) { #if defined(DEBUG) -PRThread *me = PR_GetCurrentThread(); + PRThread *me = PR_GetCurrentThread(); #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) -int err; + 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())); + /* + * 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); + 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); + 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; + PR_ASSERT(me != NULL); + rwlock->rw_owner = me; #endif - PR_Unlock(rwlock->rw_lock); + 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); + /* + * update thread's lock rank + */ + if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE) { + _PR_SET_THREAD_RWLOCK_RANK(rwlock); + } #endif } @@ -295,64 +301,68 @@ PR_IMPLEMENT(void) PR_RWLock_Unlock(PRRWLock *rwlock) { #if defined(DEBUG) -PRThread *me = PR_GetCurrentThread(); + PRThread *me = PR_GetCurrentThread(); #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) -int err; + int err; #endif #if defined(HAVE_UNIX98_RWLOCK) || defined(HAVE_UI_RWLOCK) - err = RWLOCK_UNLOCK(&rwlock->rw_lock); - PR_ASSERT(err == 0); + 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; + 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; + 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); + /* + * 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); + /* + * update thread's lock rank + */ + if (rwlock->rw_rank != PR_RWLOCK_RANK_NONE) { + _PR_UNSET_THREAD_RWLOCK_RANK(rwlock); + } #endif - return; + return; } #ifndef _PR_RWLOCK_RANK_ORDER_DEBUG @@ -363,121 +373,126 @@ void _PR_InitRWLocks(void) { } 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; - } + /* + * 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. + * 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; - } + 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_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. + * 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); + 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. + * 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; + 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 */ +#endif /* _PR_RWLOCK_RANK_ORDER_DEBUG */ |