Back to index

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

Go to the source code of this file.

Classes

struct  nssRWLockStr

Defines

#define UNTIL(x)   while(!(x))

Functions

 NSSRWLock_New (PRUint32 lock_rank, const char *lock_name)
 NSSRWLock_Destroy (NSSRWLock *rwlock)
 nssRWLock_AtomicCreate (NSSRWLock **prwlock, PRUint32 lock_rank, const char *lock_name)
 NSSRWLock_LockRead (NSSRWLock *rwlock)
 NSSRWLock_UnlockRead (NSSRWLock *rwlock)
 NSSRWLock_LockWrite (NSSRWLock *rwlock)
 NSSRWLock_UnlockWrite (NSSRWLock *rwlock)
 NSSRWLock_HaveWriteLock (NSSRWLock *rwlock)

Class Documentation

struct nssRWLockStr

Definition at line 45 of file nssrwlk.c.

Collaboration diagram for nssRWLockStr:
Class Members
PZLock * rw_lock
char * rw_name
PRThread * rw_owner
PRUint32 rw_rank
PRInt32 rw_reader_locks
PZCondVar * rw_reader_waitq
PRUint32 rw_waiting_readers
PRUint32 rw_waiting_writers
PRInt32 rw_writer_locks
PZCondVar * rw_writer_waitq

Define Documentation

#define UNTIL (   x)    while(!(x))

Definition at line 92 of file nssrwlk.c.


Function Documentation

nssRWLock_AtomicCreate ( NSSRWLock **  prwlock,
PRUint32  lock_rank,
const char *  lock_name 
)

Definition at line 178 of file nssrwlk.c.

{
    NSSRWLock  *    rwlock;
    static PRInt32  initializers;

    PR_ASSERT(prwlock != NULL);

    /* atomically initialize the lock */
    while (NULL == (rwlock = *prwlock)) {
        PRInt32 myAttempt = PR_AtomicIncrement(&initializers);
        if (myAttempt == 1) {
            if (NULL == (rwlock = *prwlock)) {
                *prwlock = rwlock = NSSRWLock_New(lock_rank, lock_name);
            }
            (void) PR_AtomicDecrement(&initializers);
            break;
        }
        PR_Sleep(PR_INTERVAL_NO_WAIT);          /* PR_Yield() */
        (void) PR_AtomicDecrement(&initializers);
    }

    return rwlock;
}

Here is the call graph for this function:

NSSRWLock_Destroy ( NSSRWLock *  rwlock)

Definition at line 151 of file nssrwlk.c.

{
    PR_ASSERT(rwlock != NULL);
    PR_ASSERT(rwlock->rw_waiting_readers == 0);

    /* XXX Shouldn't we lock the PZLock before destroying this?? */

    if (rwlock->rw_name)
       PR_Free(rwlock->rw_name);
    if (rwlock->rw_reader_waitq)
       PZ_DestroyCondVar(rwlock->rw_reader_waitq);
    if (rwlock->rw_writer_waitq)
       PZ_DestroyCondVar(rwlock->rw_writer_waitq);
    if (rwlock->rw_lock)
       PZ_DestroyLock(rwlock->rw_lock);
    PR_DELETE(rwlock);
}
NSSRWLock_HaveWriteLock ( NSSRWLock *  rwlock)

Definition at line 360 of file nssrwlk.c.

                                           {
    PRBool ownWriteLock;
    PRThread *me = PR_GetCurrentThread();

    /* This lock call isn't really necessary.
    ** If this thread is the owner, that fact cannot change during this call,
    ** because this thread is in this call.
    ** If this thread is NOT the owner, the owner could change, but it 
    ** could not become this thread.  
    */
#if UNNECESSARY
    PZ_Lock(rwlock->rw_lock);      
#endif
    ownWriteLock = (PRBool)(me == rwlock->rw_owner);
#if UNNECESSARY
    PZ_Unlock(rwlock->rw_lock);
#endif
    return ownWriteLock;
}

Here is the call graph for this function:

NSSRWLock_LockRead ( NSSRWLock *  rwlock)

Definition at line 208 of file nssrwlk.c.

{
    PRThread *me = PR_GetCurrentThread();

    PZ_Lock(rwlock->rw_lock);
#ifdef NSS_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 == NSS_RWLOCK_RANK_NONE) ||
              (rwlock->rw_rank >= nssRWLock_GetThreadRank(me)));
#endif
    /*
     * wait if write-locked or if a writer is waiting; preference for writers
     */
    UNTIL ( (rwlock->rw_owner == me) ||            /* I own it, or        */
          ((rwlock->rw_owner == NULL) &&    /* no-one owns it, and */
           (rwlock->rw_waiting_writers == 0))) { /* no-one is waiting to own */

       rwlock->rw_waiting_readers++;
       PZ_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);
       rwlock->rw_waiting_readers--;
    }
    rwlock->rw_reader_locks++;            /* Increment read-lock count */

    PZ_Unlock(rwlock->rw_lock);

#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
    nssRWLock_SetThreadRank(me, rwlock);/* update thread's lock rank */
#endif
}

Here is the call graph for this function:

NSSRWLock_LockWrite ( NSSRWLock *  rwlock)

Definition at line 275 of file nssrwlk.c.

{
    PRThread *me = PR_GetCurrentThread();

    PZ_Lock(rwlock->rw_lock);
#ifdef NSS_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 == NSS_RWLOCK_RANK_NONE) ||
                    (rwlock->rw_rank >= nssRWLock_GetThreadRank(me)));
#endif
    /*
     * wait if read locked or write locked.
     */
    PR_ASSERT(rwlock->rw_reader_locks >= 0);
    PR_ASSERT(me != NULL);

    UNTIL ( (rwlock->rw_owner == me) ||           /* I own write lock, or */
          ((rwlock->rw_owner == NULL) &&    /* no writer   and */
           (rwlock->rw_reader_locks == 0))) {    /* no readers, either. */

        rwlock->rw_waiting_writers++;
        PZ_WaitCondVar(rwlock->rw_writer_waitq, PR_INTERVAL_NO_TIMEOUT);
        rwlock->rw_waiting_writers--;
       PR_ASSERT(rwlock->rw_reader_locks >= 0);
    }

    PR_ASSERT(rwlock->rw_reader_locks == 0);
    /*
     * apply write lock
     */
    rwlock->rw_owner = me;
    rwlock->rw_writer_locks++;            /* Increment write-lock count */

    PZ_Unlock(rwlock->rw_lock);

#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
    /*
     * update thread's lock rank
     */
    nssRWLock_SetThreadRank(me,rwlock);
#endif
}

Here is the call graph for this function:

NSSRWLock_New ( PRUint32  lock_rank,
const char *  lock_name 
)

Definition at line 105 of file nssrwlk.c.

{
    NSSRWLock *rwlock;

    rwlock = PR_NEWZAP(NSSRWLock);
    if (rwlock == NULL)
        return NULL;

    rwlock->rw_lock = PZ_NewLock(nssILockRWLock);
    if (rwlock->rw_lock == NULL) {
       goto loser;
    }
    rwlock->rw_reader_waitq = PZ_NewCondVar(rwlock->rw_lock);
    if (rwlock->rw_reader_waitq == NULL) {
       goto loser;
    }
    rwlock->rw_writer_waitq = PZ_NewCondVar(rwlock->rw_lock);
    if (rwlock->rw_writer_waitq == NULL) {
       goto loser;
    }
    if (lock_name != NULL) {
        rwlock->rw_name = (char*) PR_Malloc(strlen(lock_name) + 1);
        if (rwlock->rw_name == NULL) {
           goto loser;
        }
        strcpy(rwlock->rw_name, lock_name);
    } else {
        rwlock->rw_name = NULL;
    }
    rwlock->rw_rank            = lock_rank;
    rwlock->rw_waiting_readers = 0;
    rwlock->rw_waiting_writers = 0;
    rwlock->rw_reader_locks    = 0;
    rwlock->rw_writer_locks    = 0;

    return rwlock;

loser:
    NSSRWLock_Destroy(rwlock);
    return(NULL);
}

Here is the call graph for this function:

NSSRWLock_UnlockRead ( NSSRWLock *  rwlock)

Definition at line 246 of file nssrwlk.c.

{
    PZ_Lock(rwlock->rw_lock);

    PR_ASSERT(rwlock->rw_reader_locks > 0); /* lock must be read locked */

    if ((  rwlock->rw_reader_locks  > 0)  &&     /* caller isn't screwey */
        (--rwlock->rw_reader_locks == 0)  &&     /* not read locked any more */
       (  rwlock->rw_owner        == NULL) &&    /* not write locked */
       (  rwlock->rw_waiting_writers > 0)) {     /* someone's waiting. */

       PZ_NotifyCondVar(rwlock->rw_writer_waitq); /* wake him up. */
    }

    PZ_Unlock(rwlock->rw_lock);

#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
    /*
     * update thread's lock rank
     */
    nssRWLock_UnsetThreadRank(me, rwlock);
#endif
    return;
}
NSSRWLock_UnlockWrite ( NSSRWLock *  rwlock)

Definition at line 325 of file nssrwlk.c.

{
    PRThread *me = PR_GetCurrentThread();

    PZ_Lock(rwlock->rw_lock);
    PR_ASSERT(rwlock->rw_owner == me); /* lock must be write-locked by me.  */
    PR_ASSERT(rwlock->rw_writer_locks > 0); /* lock must be write locked */

    if (  rwlock->rw_owner        == me  &&      /* I own it, and            */
          rwlock->rw_writer_locks  > 0   &&      /* I own it, and            */
        --rwlock->rw_writer_locks == 0) { /* I'm all done with it     */

       rwlock->rw_owner = NULL;           /* I don't own it any more. */

       /* Give preference to waiting writers. */
       if (rwlock->rw_waiting_writers > 0) {
           if (rwlock->rw_reader_locks == 0)
              PZ_NotifyCondVar(rwlock->rw_writer_waitq);
       } else if (rwlock->rw_waiting_readers > 0) {
           PZ_NotifyAllCondVar(rwlock->rw_reader_waitq);
       }
    }
    PZ_Unlock(rwlock->rw_lock);

#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG
    /*
     * update thread's lock rank
     */
    nssRWLock_UnsetThreadRank(me, rwlock);
#endif
    return;
}

Here is the call graph for this function: