Index: mozilla/nsprpub/pr/src/threads/combined/prulock.c |
=================================================================== |
--- mozilla/nsprpub/pr/src/threads/combined/prulock.c (revision 191424) |
+++ mozilla/nsprpub/pr/src/threads/combined/prulock.c (working copy) |
@@ -1,433 +0,0 @@ |
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
- |
-#include "primpl.h" |
- |
-#if defined(WIN95) |
-/* |
-** Some local variables report warnings on Win95 because the code paths |
-** using them are conditioned on HAVE_CUSTOME_USER_THREADS. |
-** The pragma suppresses the warning. |
-** |
-*/ |
-#pragma warning(disable : 4101) |
-#endif |
- |
- |
-void _PR_InitLocks(void) |
-{ |
- _PR_MD_INIT_LOCKS(); |
-} |
- |
-/* |
-** Deal with delayed interrupts/requested reschedule during interrupt |
-** re-enables. |
-*/ |
-void _PR_IntsOn(_PRCPU *cpu) |
-{ |
- PRUintn missed, pri, i; |
- _PRInterruptTable *it; |
- PRThread *me; |
- |
- PR_ASSERT(cpu); /* Global threads don't have CPUs */ |
- PR_ASSERT(_PR_MD_GET_INTSOFF() > 0); |
- me = _PR_MD_CURRENT_THREAD(); |
- PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); |
- |
- /* |
- ** Process delayed interrupts. This logic is kinda scary because we |
- ** need to avoid losing an interrupt (it's ok to delay an interrupt |
- ** until later). |
- ** |
- ** There are two missed state words. _pr_ints.where indicates to the |
- ** interrupt handler which state word is currently safe for |
- ** modification. |
- ** |
- ** This code scans both interrupt state words, using the where flag |
- ** to indicate to the interrupt which state word is safe for writing. |
- ** If an interrupt comes in during a scan the other word will be |
- ** modified. This modification will be noticed during the next |
- ** iteration of the loop or during the next call to this routine. |
- */ |
- for (i = 0; i < 2; i++) { |
- cpu->where = (1 - i); |
- missed = cpu->u.missed[i]; |
- if (missed != 0) { |
- cpu->u.missed[i] = 0; |
- for (it = _pr_interruptTable; it->name; it++) { |
- if (missed & it->missed_bit) { |
- PR_LOG(_pr_sched_lm, PR_LOG_MIN, |
- ("IntsOn[0]: %s intr", it->name)); |
- (*it->handler)(); |
- } |
- } |
- } |
- } |
- |
- if (cpu->u.missed[3] != 0) { |
- _PRCPU *cpu; |
- |
- _PR_THREAD_LOCK(me); |
- me->state = _PR_RUNNABLE; |
- pri = me->priority; |
- |
- cpu = me->cpu; |
- _PR_RUNQ_LOCK(cpu); |
- _PR_ADD_RUNQ(me, cpu, pri); |
- _PR_RUNQ_UNLOCK(cpu); |
- _PR_THREAD_UNLOCK(me); |
- _PR_MD_SWITCH_CONTEXT(me); |
- } |
-} |
- |
-/* |
-** Unblock the first runnable waiting thread. Skip over |
-** threads that are trying to be suspended |
-** Note: Caller must hold _PR_LOCK_LOCK() |
-*/ |
-void _PR_UnblockLockWaiter(PRLock *lock) |
-{ |
- PRThread *t = NULL; |
- PRThread *me; |
- PRCList *q; |
- |
- q = lock->waitQ.next; |
- PR_ASSERT(q != &lock->waitQ); |
- while (q != &lock->waitQ) { |
- /* Unblock first waiter */ |
- t = _PR_THREAD_CONDQ_PTR(q); |
- |
- /* |
- ** We are about to change the thread's state to runnable and for local |
- ** threads, we are going to assign a cpu to it. So, protect thread's |
- ** data structure. |
- */ |
- _PR_THREAD_LOCK(t); |
- |
- if (t->flags & _PR_SUSPENDING) { |
- q = q->next; |
- _PR_THREAD_UNLOCK(t); |
- continue; |
- } |
- |
- /* Found a runnable thread */ |
- PR_ASSERT(t->state == _PR_LOCK_WAIT); |
- PR_ASSERT(t->wait.lock == lock); |
- t->wait.lock = 0; |
- PR_REMOVE_LINK(&t->waitQLinks); /* take it off lock's waitQ */ |
- |
- /* |
- ** If this is a native thread, nothing else to do except to wake it |
- ** up by calling the machine dependent wakeup routine. |
- ** |
- ** If this is a local thread, we need to assign it a cpu and |
- ** put the thread on that cpu's run queue. There are two cases to |
- ** take care of. If the currently running thread is also a local |
- ** thread, we just assign our own cpu to that thread and put it on |
- ** the cpu's run queue. If the the currently running thread is a |
- ** native thread, we assign the primordial cpu to it (on NT, |
- ** MD_WAKEUP handles the cpu assignment). |
- */ |
- |
- if ( !_PR_IS_NATIVE_THREAD(t) ) { |
- |
- t->state = _PR_RUNNABLE; |
- |
- me = _PR_MD_CURRENT_THREAD(); |
- |
- _PR_AddThreadToRunQ(me, t); |
- _PR_THREAD_UNLOCK(t); |
- } else { |
- t->state = _PR_RUNNING; |
- _PR_THREAD_UNLOCK(t); |
- } |
- _PR_MD_WAKEUP_WAITER(t); |
- break; |
- } |
- return; |
-} |
- |
-/************************************************************************/ |
- |
- |
-PR_IMPLEMENT(PRLock*) PR_NewLock(void) |
-{ |
- PRLock *lock; |
- |
- if (!_pr_initialized) _PR_ImplicitInitialization(); |
- |
- lock = PR_NEWZAP(PRLock); |
- if (lock) { |
- if (_PR_MD_NEW_LOCK(&lock->ilock) == PR_FAILURE) { |
- PR_DELETE(lock); |
- return(NULL); |
- } |
- PR_INIT_CLIST(&lock->links); |
- PR_INIT_CLIST(&lock->waitQ); |
- } |
- return lock; |
-} |
- |
-/* |
-** Destroy the given lock "lock". There is no point in making this race |
-** free because if some other thread has the pointer to this lock all |
-** bets are off. |
-*/ |
-PR_IMPLEMENT(void) PR_DestroyLock(PRLock *lock) |
-{ |
- PR_ASSERT(lock->owner == 0); |
- _PR_MD_FREE_LOCK(&lock->ilock); |
- PR_DELETE(lock); |
-} |
- |
-extern PRThread *suspendAllThread; |
-/* |
-** Lock the lock. |
-*/ |
-PR_IMPLEMENT(void) PR_Lock(PRLock *lock) |
-{ |
- PRThread *me = _PR_MD_CURRENT_THREAD(); |
- PRIntn is; |
- PRThread *t; |
- PRCList *q; |
- |
- PR_ASSERT(me != suspendAllThread); |
- PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); |
- PR_ASSERT(lock != NULL); |
-#ifdef _PR_GLOBAL_THREADS_ONLY |
- PR_ASSERT(lock->owner != me); |
- _PR_MD_LOCK(&lock->ilock); |
- lock->owner = me; |
- return; |
-#else /* _PR_GLOBAL_THREADS_ONLY */ |
- |
- if (_native_threads_only) { |
- PR_ASSERT(lock->owner != me); |
- _PR_MD_LOCK(&lock->ilock); |
- lock->owner = me; |
- return; |
- } |
- |
- if (!_PR_IS_NATIVE_THREAD(me)) |
- _PR_INTSOFF(is); |
- |
- PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); |
- |
-retry: |
- _PR_LOCK_LOCK(lock); |
- if (lock->owner == 0) { |
- /* Just got the lock */ |
- lock->owner = me; |
- lock->priority = me->priority; |
- /* Add the granted lock to this owning thread's lock list */ |
- PR_APPEND_LINK(&lock->links, &me->lockList); |
- _PR_LOCK_UNLOCK(lock); |
- if (!_PR_IS_NATIVE_THREAD(me)) |
- _PR_FAST_INTSON(is); |
- return; |
- } |
- |
- /* If this thread already owns this lock, then it is a deadlock */ |
- PR_ASSERT(lock->owner != me); |
- |
- PR_ASSERT(_PR_IS_NATIVE_THREAD(me) || _PR_MD_GET_INTSOFF() != 0); |
- |
-#if 0 |
- if (me->priority > lock->owner->priority) { |
- /* |
- ** Give the lock owner a priority boost until we get the |
- ** lock. Record the priority we boosted it to. |
- */ |
- lock->boostPriority = me->priority; |
- _PR_SetThreadPriority(lock->owner, me->priority); |
- } |
-#endif |
- |
- /* |
- Add this thread to the asked for lock's list of waiting threads. We |
- add this thread thread in the right priority order so when the unlock |
- occurs, the thread with the higher priority will get the lock. |
- */ |
- q = lock->waitQ.next; |
- if (q == &lock->waitQ || _PR_THREAD_CONDQ_PTR(q)->priority == |
- _PR_THREAD_CONDQ_PTR(lock->waitQ.prev)->priority) { |
- /* |
- * If all the threads in the lock waitQ have the same priority, |
- * then avoid scanning the list: insert the element at the end. |
- */ |
- q = &lock->waitQ; |
- } else { |
- /* Sort thread into lock's waitQ at appropriate point */ |
- /* Now scan the list for where to insert this entry */ |
- while (q != &lock->waitQ) { |
- t = _PR_THREAD_CONDQ_PTR(lock->waitQ.next); |
- if (me->priority > t->priority) { |
- /* Found a lower priority thread to insert in front of */ |
- break; |
- } |
- q = q->next; |
- } |
- } |
- PR_INSERT_BEFORE(&me->waitQLinks, q); |
- |
- /* |
- Now grab the threadLock since we are about to change the state. We have |
- to do this since a PR_Suspend or PR_SetThreadPriority type call that takes |
- a PRThread* as an argument could be changing the state of this thread from |
- a thread running on a different cpu. |
- */ |
- |
- _PR_THREAD_LOCK(me); |
- me->state = _PR_LOCK_WAIT; |
- me->wait.lock = lock; |
- _PR_THREAD_UNLOCK(me); |
- |
- _PR_LOCK_UNLOCK(lock); |
- |
- _PR_MD_WAIT(me, PR_INTERVAL_NO_TIMEOUT); |
- goto retry; |
- |
-#endif /* _PR_GLOBAL_THREADS_ONLY */ |
-} |
- |
-/* |
-** Unlock the lock. |
-*/ |
-PR_IMPLEMENT(PRStatus) PR_Unlock(PRLock *lock) |
-{ |
- PRCList *q; |
- PRThreadPriority pri, boost; |
- PRIntn is; |
- PRThread *me = _PR_MD_CURRENT_THREAD(); |
- |
- PR_ASSERT(lock != NULL); |
- PR_ASSERT(lock->owner == me); |
- PR_ASSERT(me != suspendAllThread); |
- PR_ASSERT(!(me->flags & _PR_IDLE_THREAD)); |
- if (lock->owner != me) { |
- return PR_FAILURE; |
- } |
- |
-#ifdef _PR_GLOBAL_THREADS_ONLY |
- lock->owner = 0; |
- _PR_MD_UNLOCK(&lock->ilock); |
- return PR_SUCCESS; |
-#else /* _PR_GLOBAL_THREADS_ONLY */ |
- |
- if (_native_threads_only) { |
- lock->owner = 0; |
- _PR_MD_UNLOCK(&lock->ilock); |
- return PR_SUCCESS; |
- } |
- |
- if (!_PR_IS_NATIVE_THREAD(me)) |
- _PR_INTSOFF(is); |
- _PR_LOCK_LOCK(lock); |
- |
- /* Remove the lock from the owning thread's lock list */ |
- PR_REMOVE_LINK(&lock->links); |
- pri = lock->priority; |
- boost = lock->boostPriority; |
- if (boost > pri) { |
- /* |
- ** We received a priority boost during the time we held the lock. |
- ** We need to figure out what priority to move to by scanning |
- ** down our list of lock's that we are still holding and using |
- ** the highest boosted priority found. |
- */ |
- q = me->lockList.next; |
- while (q != &me->lockList) { |
- PRLock *ll = _PR_LOCK_PTR(q); |
- if (ll->boostPriority > pri) { |
- pri = ll->boostPriority; |
- } |
- q = q->next; |
- } |
- if (pri != me->priority) { |
- _PR_SetThreadPriority(me, pri); |
- } |
- } |
- |
- /* Unblock the first waiting thread */ |
- q = lock->waitQ.next; |
- if (q != &lock->waitQ) |
- _PR_UnblockLockWaiter(lock); |
- lock->boostPriority = PR_PRIORITY_LOW; |
- lock->owner = 0; |
- _PR_LOCK_UNLOCK(lock); |
- if (!_PR_IS_NATIVE_THREAD(me)) |
- _PR_INTSON(is); |
- return PR_SUCCESS; |
-#endif /* _PR_GLOBAL_THREADS_ONLY */ |
-} |
- |
-/* |
-** If the current thread owns |lock|, this assertion is guaranteed to |
-** succeed. Otherwise, the behavior of this function is undefined. |
-*/ |
-PR_IMPLEMENT(void) PR_AssertCurrentThreadOwnsLock(PRLock *lock) |
-{ |
- PRThread *me = _PR_MD_CURRENT_THREAD(); |
- PR_ASSERT(lock->owner == me); |
-} |
- |
-/* |
-** Test and then lock the lock if it's not already locked by some other |
-** thread. Return PR_FALSE if some other thread owned the lock at the |
-** time of the call. |
-*/ |
-PR_IMPLEMENT(PRBool) PR_TestAndLock(PRLock *lock) |
-{ |
- PRThread *me = _PR_MD_CURRENT_THREAD(); |
- PRBool rv = PR_FALSE; |
- PRIntn is; |
- |
-#ifdef _PR_GLOBAL_THREADS_ONLY |
- is = _PR_MD_TEST_AND_LOCK(&lock->ilock); |
- if (is == 0) { |
- lock->owner = me; |
- return PR_TRUE; |
- } |
- return PR_FALSE; |
-#else /* _PR_GLOBAL_THREADS_ONLY */ |
- |
-#ifndef _PR_LOCAL_THREADS_ONLY |
- if (_native_threads_only) { |
- is = _PR_MD_TEST_AND_LOCK(&lock->ilock); |
- if (is == 0) { |
- lock->owner = me; |
- return PR_TRUE; |
- } |
- return PR_FALSE; |
- } |
-#endif |
- |
- if (!_PR_IS_NATIVE_THREAD(me)) |
- _PR_INTSOFF(is); |
- |
- _PR_LOCK_LOCK(lock); |
- if (lock->owner == 0) { |
- /* Just got the lock */ |
- lock->owner = me; |
- lock->priority = me->priority; |
- /* Add the granted lock to this owning thread's lock list */ |
- PR_APPEND_LINK(&lock->links, &me->lockList); |
- rv = PR_TRUE; |
- } |
- _PR_LOCK_UNLOCK(lock); |
- |
- if (!_PR_IS_NATIVE_THREAD(me)) |
- _PR_INTSON(is); |
- return rv; |
-#endif /* _PR_GLOBAL_THREADS_ONLY */ |
-} |
- |
-/************************************************************************/ |
-/************************************************************************/ |
-/***********************ROUTINES FOR DCE EMULATION***********************/ |
-/************************************************************************/ |
-/************************************************************************/ |
-PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock) |
- { return (PR_TestAndLock(lock)) ? PR_SUCCESS : PR_FAILURE; } |