Backed out changeset 4beec31b9ea9 for increasing frequency of intermittent orange bug 618052
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user