nssrwlk.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 513 行 · 第 1/2 页

C
513
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "nssrwlk.h"#include "nspr.h"PR_BEGIN_EXTERN_C/* * Reader-writer lock */struct nssRWLockStr {    PRLock *        rw_lock;    char   *        rw_name;            /* lock name                    */    PRUint32        rw_rank;            /* rank of the lock             */    PRInt32         rw_writer_locks;    /* ==  0, if unlocked           */    PRInt32         rw_reader_locks;    /* ==  0, if unlocked           */                                        /* > 0  , # of read locks       */    PRUint32        rw_waiting_readers; /* number of waiting readers    */    PRUint32        rw_waiting_writers; /* number of waiting writers    */    PRCondVar *     rw_reader_waitq;    /* cvar for readers             */    PRCondVar *     rw_writer_waitq;    /* cvar for writers             */    PRThread  *     rw_owner;           /* lock owner for write-lock    */                                        /* Non-null if write lock held. */};PR_END_EXTERN_C#include <string.h>#ifdef DEBUG_RANK_ORDER#define NSS_RWLOCK_RANK_ORDER_DEBUG /* enable deadlock detection using                                       rank-order for locks                                    */#endif#ifdef NSS_RWLOCK_RANK_ORDER_DEBUGstatic PRUintn  nss_thread_rwlock_initialized;static PRUintn  nss_thread_rwlock;               /* TPD key for lock stack */static PRUintn  nss_thread_rwlock_alloc_failed;#define _NSS_RWLOCK_RANK_ORDER_LIMIT 10typedef struct thread_rwlock_stack {    PRInt32     trs_index;                                  /* top of stack */    NSSRWLock    *trs_stack[_NSS_RWLOCK_RANK_ORDER_LIMIT];  /* stack of lock                                                               pointers */} thread_rwlock_stack;/* forward static declarations. */static PRUint32 nssRWLock_GetThreadRank(PRThread *me);static void     nssRWLock_SetThreadRank(PRThread *me, NSSRWLock *rwlock);static void     nssRWLock_UnsetThreadRank(PRThread *me, NSSRWLock *rwlock);static void     nssRWLock_ReleaseLockStack(void *lock_stack);#endif#define UNTIL(x) while(!(x))/* * Reader/Writer Locks *//* * NSSRWLock_New *      Create a reader-writer lock, with the given lock rank and lock name * */PR_IMPLEMENT(NSSRWLock *)NSSRWLock_New(PRUint32 lock_rank, const char *lock_name){    NSSRWLock *rwlock;    rwlock = PR_NEWZAP(NSSRWLock);    if (rwlock == NULL)        return NULL;    rwlock->rw_lock = PR_NewLock();    if (rwlock->rw_lock == NULL) {	goto loser;    }    rwlock->rw_reader_waitq = PR_NewCondVar(rwlock->rw_lock);    if (rwlock->rw_reader_waitq == NULL) {	goto loser;    }    rwlock->rw_writer_waitq = PR_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);}/*** Destroy the given RWLock "lock".*/PR_IMPLEMENT(void)NSSRWLock_Destroy(NSSRWLock *rwlock){    PR_ASSERT(rwlock != NULL);    PR_ASSERT(rwlock->rw_waiting_readers == 0);    /* XXX Shouldn't we lock the PRLock before destroying this?? */    if (rwlock->rw_name)    	PR_Free(rwlock->rw_name);    if (rwlock->rw_reader_waitq)    	PR_DestroyCondVar(rwlock->rw_reader_waitq);    if (rwlock->rw_writer_waitq)	PR_DestroyCondVar(rwlock->rw_writer_waitq);    if (rwlock->rw_lock)	PR_DestroyLock(rwlock->rw_lock);    PR_DELETE(rwlock);}/*************************************************************************  Given the address of a NULL pointer to a NSSRWLock, **  atomically initializes that pointer to a newly created NSSRWLock.**  Returns the value placed into that pointer, or NULL.**   If the lock cannot be created because of resource constraints, **   the pointer will be left NULL.**  ***********************************************************************/PR_IMPLEMENT(NSSRWLock *)nssRWLock_AtomicCreate( NSSRWLock  ** prwlock, 			PRUint32      lock_rank, 			const char *  lock_name){    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) {	    *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;}/*** Read-lock the RWLock.*/PR_IMPLEMENT(void)NSSRWLock_LockRead(NSSRWLock *rwlock){    PRThread *me = PR_GetCurrentThread();    PR_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++;	PR_WaitCondVar(rwlock->rw_reader_waitq, PR_INTERVAL_NO_TIMEOUT);	rwlock->rw_waiting_readers--;    }    rwlock->rw_reader_locks++; 		/* Increment read-lock count */    PR_Unlock(rwlock->rw_lock);#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG    nssRWLock_SetThreadRank(me, rwlock);/* update thread's lock rank */#endif}/* Unlock a Read lock held on this RW lock.*/PR_IMPLEMENT(void)NSSRWLock_UnlockRead(NSSRWLock *rwlock){    PRThread *me = PR_GetCurrentThread();    PR_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. */	PR_NotifyCondVar(rwlock->rw_writer_waitq); /* wake him up. */    }    PR_Unlock(rwlock->rw_lock);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?