Backed out changeset 00ed3d264438 (bug 590422) for OSX browser-chrome failures on a CLOSED TREE.

This commit is contained in:
Ryan VanderMeulen 2013-02-26 22:05:51 -05:00
Родитель 4c53d4b6c6
Коммит 2165eca1a3
5 изменённых файлов: 96 добавлений и 13 удалений

Просмотреть файл

@ -10088,11 +10088,11 @@ nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
TimeStamp deadline;
if (aTimeout && aTimeout->mWhen > now) {
// The OS timer fired early (which can happen due to the timers
// having lower precision than TimeStamp does). Set |deadline| to
// be the time when the OS timer *should* have fired so that any
// timers that *should* have fired before aTimeout *will* be fired
// now.
// The OS timer fired early (yikes!), and possibly out of order
// too. Set |deadline| to be the time when the OS timer *should*
// have fired so that any timers that *should* have fired before
// aTimeout *will* be fired now. This happens most of the time on
// Win2k.
deadline = aTimeout->mWhen;
} else {

Просмотреть файл

@ -25,7 +25,9 @@ TimerThread::TimerThread() :
mMonitor("TimerThread.mMonitor"),
mShutdown(false),
mWaiting(false),
mSleeping(false)
mSleeping(false),
mDelayLineCounter(0),
mMinTimerPeriod(0)
{
}
@ -159,6 +161,60 @@ nsresult TimerThread::Shutdown()
return NS_OK;
}
// Keep track of how early (positive slack) or late (negative slack) timers
// are running, and use the filtered slack number to adaptively estimate how
// early timers should fire to be "on time".
void TimerThread::UpdateFilter(uint32_t aDelay, TimeStamp aTimeout,
TimeStamp aNow)
{
TimeDuration slack = aTimeout - aNow;
double smoothSlack = 0;
uint32_t i, filterLength;
static TimeDuration kFilterFeedbackMaxTicks =
TimeDuration::FromMilliseconds(FILTER_FEEDBACK_MAX);
static TimeDuration kFilterFeedbackMinTicks =
TimeDuration::FromMilliseconds(-FILTER_FEEDBACK_MAX);
if (slack > kFilterFeedbackMaxTicks)
slack = kFilterFeedbackMaxTicks;
else if (slack < kFilterFeedbackMinTicks)
slack = kFilterFeedbackMinTicks;
mDelayLine[mDelayLineCounter & DELAY_LINE_LENGTH_MASK] =
slack.ToMilliseconds();
if (++mDelayLineCounter < DELAY_LINE_LENGTH) {
// Startup mode: accumulate a full delay line before filtering.
PR_ASSERT(mTimeoutAdjustment.ToSeconds() == 0);
filterLength = 0;
} else {
// Past startup: compute number of filter taps based on mMinTimerPeriod.
if (mMinTimerPeriod == 0) {
mMinTimerPeriod = (aDelay != 0) ? aDelay : 1;
} else if (aDelay != 0 && aDelay < mMinTimerPeriod) {
mMinTimerPeriod = aDelay;
}
filterLength = (uint32_t) (FILTER_DURATION / mMinTimerPeriod);
if (filterLength > DELAY_LINE_LENGTH)
filterLength = DELAY_LINE_LENGTH;
else if (filterLength < 4)
filterLength = 4;
for (i = 1; i <= filterLength; i++)
smoothSlack += mDelayLine[(mDelayLineCounter-i) & DELAY_LINE_LENGTH_MASK];
smoothSlack /= filterLength;
// XXXbe do we need amplification? hacking a fudge factor, need testing...
mTimeoutAdjustment = TimeDuration::FromMilliseconds(smoothSlack * 1.5);
}
#ifdef DEBUG_TIMERS
PR_LOG(GetTimerLog(), PR_LOG_DEBUG,
("UpdateFilter: smoothSlack = %g, filterLength = %u\n",
smoothSlack, filterLength));
#endif
}
/* void Run(); */
NS_IMETHODIMP TimerThread::Run()
{
@ -203,7 +259,7 @@ NS_IMETHODIMP TimerThread::Run()
if (!mTimers.IsEmpty()) {
timer = mTimers[0];
if (now >= timer->mTimeout) {
if (now >= timer->mTimeout + mTimeoutAdjustment) {
next:
// NB: AddRef before the Release under RemoveTimerInternal to avoid
// mRefCnt passing through zero, in case all other refs than the one
@ -261,7 +317,7 @@ NS_IMETHODIMP TimerThread::Run()
if (!mTimers.IsEmpty()) {
timer = mTimers[0];
TimeStamp timeout = timer->mTimeout;
TimeStamp timeout = timer->mTimeout + mTimeoutAdjustment;
// Don't wait at all (even for PR_INTERVAL_NO_WAIT) if the next timer
// is due now or overdue.
@ -273,7 +329,7 @@ NS_IMETHODIMP TimerThread::Run()
double microseconds = (timeout - now).ToMilliseconds()*1000;
if (microseconds < halfMicrosecondsIntervalResolution)
goto next; // round down; execute event now
waitFor = PR_MicrosecondsToInterval(static_cast<PRUint32>(microseconds)); // Floor is accurate enough.
waitFor = PR_MicrosecondsToInterval(microseconds);
if (waitFor == 0)
waitFor = 1; // round up, wait the minimum time we can wait
}
@ -362,7 +418,7 @@ int32_t TimerThread::AddTimerInternal(nsTimerImpl *aTimer)
TimeStamp now = TimeStamp::Now();
TimerAdditionComparator c(now, aTimer);
TimerAdditionComparator c(now, mTimeoutAdjustment, aTimer);
nsTimerImpl** insertSlot = mTimers.InsertElementSorted(aTimer, c);
if (!insertSlot)
@ -405,6 +461,9 @@ void TimerThread::DoAfterSleep()
timer->SetDelay(delay);
}
// nuke the stored adjustments, so they get recalibrated
mTimeoutAdjustment = TimeDuration(0);
mDelayLineCounter = 0;
mSleeping = false;
}

Просмотреть файл

@ -40,6 +40,12 @@ public:
nsresult TimerDelayChanged(nsTimerImpl *aTimer);
nsresult RemoveTimer(nsTimerImpl *aTimer);
#define FILTER_DURATION 1e3 /* one second */
#define FILTER_FEEDBACK_MAX 100 /* 1/10th of a second */
void UpdateFilter(uint32_t aDelay, TimeStamp aTimeout,
TimeStamp aNow);
void DoBeforeSleep();
void DoAfterSleep();
@ -64,12 +70,23 @@ private:
bool mSleeping;
nsTArray<nsTimerImpl*> mTimers;
#define DELAY_LINE_LENGTH_LOG2 5
#define DELAY_LINE_LENGTH_MASK ((1u << DELAY_LINE_LENGTH_LOG2) - 1)
#define DELAY_LINE_LENGTH (1u << DELAY_LINE_LENGTH_LOG2)
int32_t mDelayLine[DELAY_LINE_LENGTH]; // milliseconds
uint32_t mDelayLineCounter;
uint32_t mMinTimerPeriod; // milliseconds
TimeDuration mTimeoutAdjustment;
};
struct TimerAdditionComparator {
TimerAdditionComparator(const mozilla::TimeStamp &aNow,
const mozilla::TimeDuration &aTimeoutAdjustment,
nsTimerImpl *aTimerToInsert) :
now(aNow)
now(aNow),
timeoutAdjustment(aTimeoutAdjustment)
#ifdef DEBUG
, timerToInsert(aTimerToInsert)
#endif
@ -79,7 +96,11 @@ struct TimerAdditionComparator {
NS_ABORT_IF_FALSE(newTimer == timerToInsert, "Unexpected timer ordering");
// Skip any overdue timers.
return fromArray->mTimeout <= now ||
// XXXbz why? Given our definition of overdue in terms of
// mTimeoutAdjustment, aTimer might be overdue already! Why not
// just fire timers in order?
return now >= fromArray->mTimeout + timeoutAdjustment ||
fromArray->mTimeout <= newTimer->mTimeout;
}
@ -89,6 +110,7 @@ struct TimerAdditionComparator {
private:
const mozilla::TimeStamp &now;
const mozilla::TimeDuration &timeoutAdjustment;
#ifdef DEBUG
const nsTimerImpl * const timerToInsert;
#endif

Просмотреть файл

@ -460,6 +460,8 @@ void nsTimerImpl::Fire()
// calling Fire().
timeout -= TimeDuration::FromMilliseconds(mDelay);
}
if (gThread)
gThread->UpdateFilter(mDelay, timeout, now);
if (mCallbackType == CALLBACK_TYPE_INTERFACE)
mTimerCallbackWhileFiring = mCallback.i;

Просмотреть файл

@ -52,7 +52,7 @@ public:
static NS_HIDDEN_(void) Shutdown();
friend class TimerThread;
friend struct TimerAdditionComparator;
friend class TimerAdditionComparator;
void Fire();
nsresult PostTimerEvent();