nssrwlk.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 513 行 · 第 1/2 页
C
513 行
#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG /* * update thread's lock rank */ nssRWLock_UnsetThreadRank(me, rwlock);#endif return;}/*** Write-lock the RWLock.*/PR_IMPLEMENT(void)NSSRWLock_LockWrite(NSSRWLock *rwlock){ PRInt32 lock_acquired = 0; 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 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++; PR_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 */ PR_Unlock(rwlock->rw_lock);#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG /* * update thread's lock rank */ nssRWLock_SetThreadRank(me,rwlock);#endif}/* Unlock a Read lock held on this RW lock.*/PR_IMPLEMENT(void)NSSRWLock_UnlockWrite(NSSRWLock *rwlock){ PRThread *me = PR_GetCurrentThread(); PR_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. */ if (rwlock->rw_reader_locks == 0) { /* no readers, wake up somebody. */ /* Give preference to waiting writers. */ if (rwlock->rw_waiting_writers > 0) PR_NotifyCondVar(rwlock->rw_writer_waitq); else if (rwlock->rw_waiting_readers > 0) PR_NotifyAllCondVar(rwlock->rw_reader_waitq); } } PR_Unlock(rwlock->rw_lock);#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG /* * update thread's lock rank */ nssRWLock_UnsetThreadRank(me, rwlock);#endif return;}/* This is primarily for debugging, i.e. for inclusion in ASSERT calls. */PR_IMPLEMENT(PRBool)NSSRWLock_HaveWriteLock(NSSRWLock *rwlock) { 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 PR_Lock(rwlock->rw_lock); #endif ownWriteLock = (PRBool)(me == rwlock->rw_owner);#if UNNECESSARY PR_Unlock(rwlock->rw_lock);#endif return ownWriteLock;}#ifdef NSS_RWLOCK_RANK_ORDER_DEBUG/* * nssRWLock_SetThreadRank * 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 voidnssRWLock_SetThreadRank(PRThread *me, NSSRWLock *rwlock){ thread_rwlock_stack *lock_stack; PRStatus rv; /* * allocated thread-private-data for rwlock list, if not already allocated */ if (!nss_thread_rwlock_initialized) { /* * allocate tpd, only if not failed already */ if (!nss_thread_rwlock_alloc_failed) { if (PR_NewThreadPrivateIndex(&nss_thread_rwlock, nssRWLock_ReleaseLockStack) == PR_FAILURE) { nss_thread_rwlock_alloc_failed = 1; return; } } else return; } /* * allocate a lock stack */ if ((lock_stack = PR_GetThreadPrivate(nss_thread_rwlock)) == NULL) { lock_stack = (thread_rwlock_stack *) PR_CALLOC(1 * sizeof(thread_rwlock_stack)); if (lock_stack) { rv = PR_SetThreadPrivate(nss_thread_rwlock, lock_stack); if (rv == PR_FAILURE) { PR_DELETE(lock_stack); nss_thread_rwlock_alloc_failed = 1; return; } } else { nss_thread_rwlock_alloc_failed = 1; return; } } /* * add rwlock to lock stack, if limit is not exceeded */ if (lock_stack) { if (lock_stack->trs_index < _NSS_RWLOCK_RANK_ORDER_LIMIT) lock_stack->trs_stack[lock_stack->trs_index++] = rwlock; } nss_thread_rwlock_initialized = 1;}static voidnssRWLock_ReleaseLockStack(void *lock_stack){ PR_ASSERT(lock_stack); PR_DELETE(lock_stack);}/* * nssRWLock_GetThreadRank * * return thread's lock rank. If thread-private-data for the lock * stack is not allocated, return NSS_RWLOCK_RANK_NONE. */static PRUint32nssRWLock_GetThreadRank(PRThread *me){ thread_rwlock_stack *lock_stack; if (nss_thread_rwlock_initialized) { if ((lock_stack = PR_GetThreadPrivate(nss_thread_rwlock)) == NULL) return (NSS_RWLOCK_RANK_NONE); else return(lock_stack->trs_stack[lock_stack->trs_index - 1]->rw_rank); } else return (NSS_RWLOCK_RANK_NONE);}/* * nssRWLock_UnsetThreadRank * * remove the rwlock from the lock stack. Since locks may not be * unlocked in a FIFO order, the entire lock stack is searched. */static voidnssRWLock_UnsetThreadRank(PRThread *me, NSSRWLock *rwlock){ thread_rwlock_stack *lock_stack; int new_index = 0, index, done = 0; if (!nss_thread_rwlock_initialized) return; lock_stack = PR_GetThreadPrivate(nss_thread_rwlock); PR_ASSERT(lock_stack != NULL); index = lock_stack->trs_index - 1; while (index-- >= 0) { if ((lock_stack->trs_stack[index] == rwlock) && !done) { /* * 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 ((lock_stack->trs_stack[index] != NULL) && !new_index) 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 /* NSS_RWLOCK_RANK_ORDER_DEBUG */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?