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 + -
显示快捷键?