Back to index

lightning-sunbird  0.9+nobinonly
Classes | Functions
prrwlock.c File Reference
#include "primpl.h"
#include <string.h>

Go to the source code of this file.

Classes

struct  PRRWLock

Functions

 PR_NewRWLock (PRUint32 lock_rank, const char *lock_name)
 PR_DestroyRWLock (PRRWLock *rwlock)
 PR_RWLock_Rlock (PRRWLock *rwlock)
 PR_RWLock_Wlock (PRRWLock *rwlock)
 PR_RWLock_Unlock (PRRWLock *rwlock)
void _PR_InitRWLocks (void)

Class Documentation

struct PRRWLock

Definition at line 70 of file prrwlock.c.

Collaboration diagram for PRRWLock:
Class Members
PRLock * rw_lock
PRInt32 rw_lock_cnt
char * rw_name
PRUint32 rw_rank
PRUint32 rw_reader_cnt
PRCondVar * rw_reader_waitq
PRUint32 rw_writer_cnt
PRCondVar * rw_writer_waitq

Function Documentation

Definition at line 389 of file prrwlock.c.

{ }

Here is the caller graph for this function:

PR_DestroyRWLock ( PRRWLock rwlock)

Definition at line 198 of file prrwlock.c.

{
#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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_NewRWLock ( PRUint32  lock_rank,
const char *  lock_name 
)

Definition at line 129 of file prrwlock.c.

{
    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
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_RWLock_Rlock ( PRRWLock rwlock)

Definition at line 219 of file prrwlock.c.

{
#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
        */
       _PR_SET_THREAD_RWLOCK_RANK(rwlock);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_RWLock_Unlock ( PRRWLock rwlock)

Definition at line 325 of file prrwlock.c.

{
#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
        */
       _PR_UNSET_THREAD_RWLOCK_RANK(rwlock);
#endif
       return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PR_RWLock_Wlock ( PRRWLock rwlock)

Definition at line 269 of file prrwlock.c.

{
#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
        */
       _PR_SET_THREAD_RWLOCK_RANK(rwlock);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function: