Backed out changeset 4beec31b9ea9 for increasing frequency of intermittent orange bug 618052

This commit is contained in:
Chris Jones
2011-03-31 18:57:38 -05:00
parent 5dece3352a
commit ecb9597975
165 changed files with 2718 additions and 1375 deletions

View File

@@ -41,6 +41,7 @@
#include "nsTimerImpl.h"
#include "TimerThread.h"
#include "nsAutoLock.h"
#include "nsThreadUtils.h"
#include "pratom.h"
@@ -51,15 +52,13 @@
#include <math.h>
using namespace mozilla;
NS_IMPL_THREADSAFE_ISUPPORTS2(TimerThread, nsIRunnable, nsIObserver)
TimerThread::TimerThread() :
mInitInProgress(0),
mInitialized(PR_FALSE),
mLock("TimerThread.mLock"),
mCondVar(mLock, "TimerThread.mCondVar"),
mLock(nsnull),
mCondVar(nsnull),
mShutdown(PR_FALSE),
mWaiting(PR_FALSE),
mSleeping(PR_FALSE),
@@ -70,6 +69,11 @@ TimerThread::TimerThread() :
TimerThread::~TimerThread()
{
if (mCondVar)
PR_DestroyCondVar(mCondVar);
if (mLock)
nsAutoLock::DestroyLock(mLock);
mThread = nsnull;
NS_ASSERTION(mTimers.IsEmpty(), "Timers remain in TimerThread::~TimerThread");
@@ -78,6 +82,15 @@ TimerThread::~TimerThread()
nsresult
TimerThread::InitLocks()
{
NS_ASSERTION(!mLock, "InitLocks called twice?");
mLock = nsAutoLock::NewLock("TimerThread::mLock");
if (!mLock)
return NS_ERROR_OUT_OF_MEMORY;
mCondVar = PR_NewCondVar(mLock);
if (!mCondVar)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@@ -117,17 +130,17 @@ nsresult TimerThread::Init()
}
}
{
MutexAutoLock lock(mLock);
mInitialized = PR_TRUE;
mCondVar.NotifyAll();
}
PR_Lock(mLock);
mInitialized = PR_TRUE;
PR_NotifyAllCondVar(mCondVar);
PR_Unlock(mLock);
}
else {
MutexAutoLock lock(mLock);
PR_Lock(mLock);
while (!mInitialized) {
mCondVar.Wait();
PR_WaitCondVar(mCondVar, PR_INTERVAL_NO_TIMEOUT);
}
PR_Unlock(mLock);
}
if (!mThread)
@@ -145,13 +158,13 @@ nsresult TimerThread::Shutdown()
nsTArray<nsTimerImpl*> timers;
{ // lock scope
MutexAutoLock lock(mLock);
nsAutoLock lock(mLock);
mShutdown = PR_TRUE;
// notify the cond var so that Run() can return
if (mWaiting)
mCondVar.Notify();
if (mCondVar && mWaiting)
PR_NotifyCondVar(mCondVar);
// Need to copy content of mTimers array to a local array
// because call to timers' ReleaseCallback() (and release its self)
@@ -233,7 +246,7 @@ void TimerThread::UpdateFilter(PRUint32 aDelay, TimeStamp aTimeout,
/* void Run(); */
NS_IMETHODIMP TimerThread::Run()
{
MutexAutoLock lock(mLock);
nsAutoLock lock(mLock);
// We need to know how many microseconds give a positive PRIntervalTime. This
// is platform-dependent, we calculate it at runtime now.
@@ -283,41 +296,40 @@ NS_IMETHODIMP TimerThread::Run()
NS_ADDREF(timer);
RemoveTimerInternal(timer);
{
// We release mLock around the Fire call to avoid deadlock.
MutexAutoUnlock unlock(mLock);
// We release mLock around the Fire call to avoid deadlock.
lock.unlock();
#ifdef DEBUG_TIMERS
if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
PR_LOG(gTimerLog, PR_LOG_DEBUG,
("Timer thread woke up %fms from when it was supposed to\n",
fabs((now - timer->mTimeout).ToMilliseconds())));
}
if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
PR_LOG(gTimerLog, PR_LOG_DEBUG,
("Timer thread woke up %fms from when it was supposed to\n",
fabs((now - timer->mTimeout).ToMilliseconds())));
}
#endif
// We are going to let the call to PostTimerEvent here handle the
// release of the timer so that we don't end up releasing the timer
// on the TimerThread instead of on the thread it targets.
if (NS_FAILED(timer->PostTimerEvent())) {
nsrefcnt rc;
NS_RELEASE2(timer, rc);
// We are going to let the call to PostTimerEvent here handle the
// release of the timer so that we don't end up releasing the timer
// on the TimerThread instead of on the thread it targets.
if (NS_FAILED(timer->PostTimerEvent())) {
nsrefcnt rc;
NS_RELEASE2(timer, rc);
// The nsITimer interface requires that its users keep a reference
// to the timers they use while those timers are initialized but
// have not yet fired. If this ever happens, it is a bug in the
// code that created and used the timer.
//
// Further, note that this should never happen even with a
// misbehaving user, because nsTimerImpl::Release checks for a
// refcount of 1 with an armed timer (a timer whose only reference
// is from the timer thread) and when it hits this will remove the
// timer from the timer thread and thus destroy the last reference,
// preventing this situation from occurring.
NS_ASSERTION(rc != 0, "destroyed timer off its target thread!");
}
timer = nsnull;
// The nsITimer interface requires that its users keep a reference
// to the timers they use while those timers are initialized but
// have not yet fired. If this ever happens, it is a bug in the
// code that created and used the timer.
//
// Further, note that this should never happen even with a
// misbehaving user, because nsTimerImpl::Release checks for a
// refcount of 1 with an armed timer (a timer whose only reference
// is from the timer thread) and when it hits this will remove the
// timer from the timer thread and thus destroy the last reference,
// preventing this situation from occurring.
NS_ASSERTION(rc != 0, "destroyed timer off its target thread!");
}
timer = nsnull;
lock.lock();
if (mShutdown)
break;
@@ -360,7 +372,7 @@ NS_IMETHODIMP TimerThread::Run()
}
mWaiting = PR_TRUE;
mCondVar.Wait(waitFor);
PR_WaitCondVar(mCondVar, waitFor);
mWaiting = PR_FALSE;
}
@@ -369,7 +381,7 @@ NS_IMETHODIMP TimerThread::Run()
nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
{
MutexAutoLock lock(mLock);
nsAutoLock lock(mLock);
// Add the timer to our list.
PRInt32 i = AddTimerInternal(aTimer);
@@ -377,15 +389,15 @@ nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
return NS_ERROR_OUT_OF_MEMORY;
// Awaken the timer thread.
if (mWaiting && i == 0)
mCondVar.Notify();
if (mCondVar && mWaiting && i == 0)
PR_NotifyCondVar(mCondVar);
return NS_OK;
}
nsresult TimerThread::TimerDelayChanged(nsTimerImpl *aTimer)
{
MutexAutoLock lock(mLock);
nsAutoLock lock(mLock);
// Our caller has a strong ref to aTimer, so it can't go away here under
// ReleaseTimerInternal.
@@ -396,15 +408,15 @@ nsresult TimerThread::TimerDelayChanged(nsTimerImpl *aTimer)
return NS_ERROR_OUT_OF_MEMORY;
// Awaken the timer thread.
if (mWaiting && i == 0)
mCondVar.Notify();
if (mCondVar && mWaiting && i == 0)
PR_NotifyCondVar(mCondVar);
return NS_OK;
}
nsresult TimerThread::RemoveTimer(nsTimerImpl *aTimer)
{
MutexAutoLock lock(mLock);
nsAutoLock lock(mLock);
// Remove the timer from our array. Tell callers that aTimer was not found
// by returning NS_ERROR_NOT_AVAILABLE. Unlike the TimerDelayChanged case
@@ -417,8 +429,8 @@ nsresult TimerThread::RemoveTimer(nsTimerImpl *aTimer)
return NS_ERROR_NOT_AVAILABLE;
// Awaken the timer thread.
if (mWaiting)
mCondVar.Notify();
if (mCondVar && mWaiting)
PR_NotifyCondVar(mCondVar);
return NS_OK;
}