Backing out rev b567a93a5086 (bug 558306) to fix test orange
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 15 Jul 2010 13:49:28 -0400
changeset 47703 5d3c3d5c71bc03965fd60fb8cf6d94548883972f
parent 47702 018ef41768f61c1dee3883364967fb62a8700635
child 47704 2ee91665cb53b1b3544da078f83f01b717f95bf9
push idunknown
push userunknown
push dateunknown
bugs558306
milestone2.0b2pre
Backing out rev b567a93a5086 (bug 558306) to fix test orange
xpcom/threads/TimerThread.cpp
xpcom/threads/TimerThread.h
xpcom/threads/nsTimerImpl.cpp
xpcom/threads/nsTimerImpl.h
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -45,30 +45,29 @@
 #include "nsThreadUtils.h"
 #include "pratom.h"
 
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsIProxyObjectManager.h"
 #include "mozilla/Services.h"
 
-#include <math.h>
-
 NS_IMPL_THREADSAFE_ISUPPORTS2(TimerThread, nsIRunnable, nsIObserver)
 
 TimerThread::TimerThread() :
   mInitInProgress(0),
   mInitialized(PR_FALSE),
   mLock(nsnull),
   mCondVar(nsnull),
   mShutdown(PR_FALSE),
   mWaiting(PR_FALSE),
   mSleeping(PR_FALSE),
   mDelayLineCounter(0),
-  mMinTimerPeriod(0)
+  mMinTimerPeriod(0),
+  mTimeoutAdjustment(0)
 {
 }
 
 TimerThread::~TimerThread()
 {
   if (mCondVar)
     PR_DestroyCondVar(mCondVar);
   if (mLock)
@@ -187,37 +186,36 @@ nsresult TimerThread::Shutdown()
 
   PR_LOG(gTimerLog, PR_LOG_DEBUG, ("TimerThread::Shutdown end\n"));
   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(PRUint32 aDelay, TimeStamp aTimeout,
-                               TimeStamp aNow)
+void TimerThread::UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout,
+                               PRIntervalTime aNow)
 {
-  TimeDuration slack = aTimeout - aNow;
+  PRInt32 slack = (PRInt32) (aTimeout - aNow);
   double smoothSlack = 0;
   PRUint32 i, filterLength;
-  static TimeDuration kFilterFeedbackMaxTicks =
-    TimeDuration::FromMilliseconds(FILTER_FEEDBACK_MAX);
-  static TimeDuration kFilterFeedbackMinTicks =
-    TimeDuration::FromMilliseconds(-FILTER_FEEDBACK_MAX);
+  static PRIntervalTime kFilterFeedbackMaxTicks =
+    PR_MillisecondsToInterval(FILTER_FEEDBACK_MAX);
 
-  if (slack > kFilterFeedbackMaxTicks)
-    slack = kFilterFeedbackMaxTicks;
-  else if (slack < kFilterFeedbackMinTicks)
-    slack = kFilterFeedbackMinTicks;
-
-  mDelayLine[mDelayLineCounter & DELAY_LINE_LENGTH_MASK] =
-    slack.ToMilliseconds();
+  if (slack > 0) {
+    if (slack > (PRInt32)kFilterFeedbackMaxTicks)
+      slack = kFilterFeedbackMaxTicks;
+  } else {
+    if (slack < -(PRInt32)kFilterFeedbackMaxTicks)
+      slack = -(PRInt32)kFilterFeedbackMaxTicks;
+  }
+  mDelayLine[mDelayLineCounter & DELAY_LINE_LENGTH_MASK] = slack;
   if (++mDelayLineCounter < DELAY_LINE_LENGTH) {
     // Startup mode: accumulate a full delay line before filtering.
-    PR_ASSERT(mTimeoutAdjustment.ToSeconds() == 0);
+    PR_ASSERT(mTimeoutAdjustment == 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;
     }
@@ -228,47 +226,46 @@ void TimerThread::UpdateFilter(PRUint32 
     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);
+    mTimeoutAdjustment = (PRInt32) (smoothSlack * 1.5);
   }
 
 #ifdef DEBUG_TIMERS
   PR_LOG(gTimerLog, PR_LOG_DEBUG,
          ("UpdateFilter: smoothSlack = %g, filterLength = %u\n",
           smoothSlack, filterLength));
 #endif
 }
 
 /* void Run(); */
 NS_IMETHODIMP TimerThread::Run()
 {
   nsAutoLock lock(mLock);
 
   while (!mShutdown) {
-    // Have to use PRIntervalTime here, since PR_WaitCondVar takes it
     PRIntervalTime waitFor;
 
     if (mSleeping) {
       // Sleep for 0.1 seconds while not firing timers.
       waitFor = PR_MillisecondsToInterval(100);
     } else {
       waitFor = PR_INTERVAL_NO_TIMEOUT;
-      TimeStamp now = TimeStamp::Now();
+      PRIntervalTime now = PR_IntervalNow();
       nsTimerImpl *timer = nsnull;
 
       if (!mTimers.IsEmpty()) {
         timer = mTimers[0];
 
-        if (now >= timer->mTimeout + mTimeoutAdjustment) {
+        if (!TIMER_LESS_THAN(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
           // from mTimers have gone away (the last non-mTimers[i]-ref's Release
           // must be racing with us, blocked in gThread->RemoveTimer waiting
           // for TimerThread::mLock, under nsTimerImpl::Release.
 
           NS_ADDREF(timer);
@@ -276,17 +273,20 @@ NS_IMETHODIMP TimerThread::Run()
 
           // 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 %dms from when it was supposed to\n",
-                    PRInt32(fabs((now - timer->mTimeout).ToMilliseconds()))));
+                    (now >= timer->mTimeout)
+                    ? PR_IntervalToMilliseconds(now - timer->mTimeout)
+                    : -(PRInt32)PR_IntervalToMilliseconds(timer->mTimeout-now))
+                  );
           }
 #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;
@@ -308,30 +308,30 @@ NS_IMETHODIMP TimerThread::Run()
           timer = nsnull;
 
           lock.lock();
           if (mShutdown)
             break;
 
           // Update now, as PostTimerEvent plus the locking may have taken a
           // tick or two, and we may goto next below.
-          now = TimeStamp::Now();
+          now = PR_IntervalNow();
         }
       }
 
       if (!mTimers.IsEmpty()) {
         timer = mTimers[0];
 
-        TimeStamp timeout = timer->mTimeout + mTimeoutAdjustment;
+        PRIntervalTime timeout = timer->mTimeout + mTimeoutAdjustment;
 
         // Don't wait at all (even for PR_INTERVAL_NO_WAIT) if the next timer
         // is due now or overdue.
-        if (now >= timeout)
+        if (!TIMER_LESS_THAN(now, timeout))
           goto next;
-        waitFor = PR_MillisecondsToInterval((timeout - now).ToMilliseconds());
+        waitFor = timeout - now;
       }
 
 #ifdef DEBUG_TIMERS
       if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
         if (waitFor == PR_INTERVAL_NO_TIMEOUT)
           PR_LOG(gTimerLog, PR_LOG_DEBUG,
                  ("waiting for PR_INTERVAL_NO_TIMEOUT\n"));
         else
@@ -406,32 +406,33 @@ nsresult TimerThread::RemoveTimer(nsTime
 }
 
 // This function must be called from within a lock
 PRInt32 TimerThread::AddTimerInternal(nsTimerImpl *aTimer)
 {
   if (mShutdown)
     return -1;
 
-  TimeStamp now = TimeStamp::Now();
+  PRIntervalTime now = PR_IntervalNow();
   PRUint32 count = mTimers.Length();
   PRUint32 i = 0;
   for (; i < count; i++) {
     nsTimerImpl *timer = mTimers[i];
 
-    // Don't break till we have skipped any overdue timers.
-
-    // XXXbz why?  Given our definition of overdue in terms of
-    // mTimeoutAdjustment, aTimer might be overdue already!  Why not
-    // just fire timers in order?
+    // Don't break till we have skipped any overdue timers.  Do not include
+    // mTimeoutAdjustment here, because we are really trying to avoid calling
+    // TIMER_LESS_THAN(t, u), where the t is now + DELAY_INTERVAL_MAX, u is
+    // now - overdue, and DELAY_INTERVAL_MAX + overdue > DELAY_INTERVAL_LIMIT.
+    // In other words, we want to use now-based time, now adjusted time, even
+    // though "overdue" ultimately depends on adjusted time.
 
     // XXX does this hold for TYPE_REPEATING_PRECISE?  /be
 
-    if (now < timer->mTimeout + mTimeoutAdjustment &&
-        aTimer->mTimeout < timer->mTimeout) {
+    if (TIMER_LESS_THAN(now, timer->mTimeout) &&
+        TIMER_LESS_THAN(aTimer->mTimeout, timer->mTimeout)) {
       break;
     }
   }
 
   if (!mTimers.InsertElementAt(i, aTimer))
     return -1;
 
   aTimer->mArmed = PR_TRUE;
@@ -467,17 +468,17 @@ void TimerThread::DoAfterSleep()
     nsTimerImpl *timer = mTimers[i];
     // get and set the delay to cause its timeout to be recomputed
     PRUint32 delay;
     timer->GetDelay(&delay);
     timer->SetDelay(delay);
   }
 
   // nuke the stored adjustments, so they get recalibrated
-  mTimeoutAdjustment = TimeDuration(0);
+  mTimeoutAdjustment = 0;
   mDelayLineCounter = 0;
   mSleeping = PR_FALSE;
 }
 
 
 /* void observe (in nsISupports aSubject, in string aTopic, in wstring aData); */
 NS_IMETHODIMP
 TimerThread::Observe(nsISupports* /* aSubject */, const char *aTopic, const PRUnichar* /* aData */)
--- a/xpcom/threads/TimerThread.h
+++ b/xpcom/threads/TimerThread.h
@@ -45,26 +45,23 @@
 #include "nsIRunnable.h"
 #include "nsIThread.h"
 
 #include "nsTimerImpl.h"
 
 #include "nsTArray.h"
 
 #include "prcvar.h"
-#include "mozilla/TimeStamp.h"
+#include "prinrval.h"
 #include "prlock.h"
 
 class TimerThread : public nsIRunnable,
                     public nsIObserver
 {
 public:
-  typedef mozilla::TimeStamp TimeStamp;
-  typedef mozilla::TimeDuration TimeDuration;
-
   TimerThread();
   NS_HIDDEN_(nsresult) InitLocks();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIOBSERVER
   
   NS_HIDDEN_(nsresult) Init();
@@ -72,18 +69,18 @@ public:
 
   nsresult AddTimer(nsTimerImpl *aTimer);
   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(PRUint32 aDelay, TimeStamp aTimeout,
-                    TimeStamp aNow);
+  void UpdateFilter(PRUint32 aDelay, PRIntervalTime aTimeout,
+                    PRIntervalTime aNow);
 
   void DoBeforeSleep();
   void DoAfterSleep();
 
 private:
   ~TimerThread();
 
   PRInt32 mInitInProgress;
@@ -105,15 +102,15 @@ private:
   PRPackedBool mSleeping;
   
   nsTArray<nsTimerImpl*> mTimers;
 
 #define DELAY_LINE_LENGTH_LOG2  5
 #define DELAY_LINE_LENGTH_MASK  PR_BITMASK(DELAY_LINE_LENGTH_LOG2)
 #define DELAY_LINE_LENGTH       PR_BIT(DELAY_LINE_LENGTH_LOG2)
 
-  PRInt32  mDelayLine[DELAY_LINE_LENGTH]; // milliseconds
+  PRInt32  mDelayLine[DELAY_LINE_LENGTH];
   PRUint32 mDelayLineCounter;
   PRUint32 mMinTimerPeriod;     // milliseconds
-  TimeDuration mTimeoutAdjustment;
+  PRInt32  mTimeoutAdjustment;
 };
 
 #endif /* TimerThread_h___ */
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -41,19 +41,16 @@
 #include "nsTimerImpl.h"
 #include "TimerThread.h"
 #include "nsAutoLock.h"
 #include "nsAutoPtr.h"
 #include "nsThreadManager.h"
 #include "nsThreadUtils.h"
 #include "prmem.h"
 
-using mozilla::TimeDuration;
-using mozilla::TimeStamp;
-
 static PRInt32          gGenerator = 0;
 static TimerThread*     gThread = nsnull;
 
 #ifdef DEBUG_TIMERS
 #include <math.h>
 
 double nsTimerImpl::sDeltaSumSquared = 0;
 double nsTimerImpl::sDeltaSum = 0;
@@ -140,22 +137,28 @@ NS_IMETHODIMP_(nsrefcnt) nsTimerImpl::Re
 
 nsTimerImpl::nsTimerImpl() :
   mClosure(nsnull),
   mCallbackType(CALLBACK_TYPE_UNKNOWN),
   mFiring(PR_FALSE),
   mArmed(PR_FALSE),
   mCanceled(PR_FALSE),
   mGeneration(0),
-  mDelay(0)
+  mDelay(0),
+  mTimeout(0)
 {
   // XXXbsmedberg: shouldn't this be in Init()?
   mEventTarget = static_cast<nsIEventTarget*>(NS_GetCurrentThread());
 
   mCallback.c = nsnull;
+
+#ifdef DEBUG_TIMERS
+  mStart = 0;
+  mStart2 = 0;
+#endif
 }
 
 nsTimerImpl::~nsTimerImpl()
 {
   ReleaseCallback();
 }
 
 //static
@@ -293,18 +296,18 @@ NS_IMETHODIMP nsTimerImpl::SetDelay(PRUi
     // by re-setting delay instead of reinitializing the timer.
     NS_ERROR("nsITimer->SetDelay() called when the "
              "one-shot timer is not set up.");
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // If we're already repeating precisely, update mTimeout now so that the
   // new delay takes effect in the future.
-  if (!mTimeout.IsNull() && mType == TYPE_REPEATING_PRECISE)
-    mTimeout = TimeStamp::Now();
+  if (mTimeout != 0 && mType == TYPE_REPEATING_PRECISE)
+    mTimeout = PR_IntervalNow();
 
   SetDelayInternal(aDelay);
 
   if (!mFiring && gThread)
     gThread->TimerDelayChanged(this);
 
   return NS_OK;
 }
@@ -371,42 +374,41 @@ NS_IMETHODIMP nsTimerImpl::SetTarget(nsI
 }
 
 
 void nsTimerImpl::Fire()
 {
   if (mCanceled)
     return;
 
-  TimeStamp now = TimeStamp::Now();
+  PRIntervalTime now = PR_IntervalNow();
 #ifdef DEBUG_TIMERS
   if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
-    TimeDuration   a = now - mStart; // actual delay in intervals
-    TimeDuration   b = TimeDuration::FromMilliseconds(mDelay); // expected delay in intervals
-    TimeDuration   delta = (a > b) ? a - b : b - a;
-    PRUint32       d = delta.ToMilliseconds(); // delta in ms
+    PRIntervalTime a = now - mStart; // actual delay in intervals
+    PRUint32       b = PR_MillisecondsToInterval(mDelay); // expected delay in intervals
+    PRUint32       d = PR_IntervalToMilliseconds((a > b) ? a - b : b - a); // delta in ms
     sDeltaSum += d;
     sDeltaSumSquared += double(d) * double(d);
     sDeltaNum++;
 
     PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] expected delay time %4dms\n", this, mDelay));
-    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] actual delay time   %4dms\n", this, PRInt32(a.ToMilliseconds())));
+    PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] actual delay time   %4dms\n", this, PR_IntervalToMilliseconds(a)));
     PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p] (mType is %d)       -------\n", this, mType));
     PR_LOG(gTimerLog, PR_LOG_DEBUG, ("[this=%p]     delta           %4dms\n", this, (a > b) ? (PRInt32)d : -(PRInt32)d));
 
     mStart = mStart2;
-    mStart2 = TimeStamp::TimeStamp();
+    mStart2 = 0;
   }
 #endif
 
-  TimeStamp timeout = mTimeout;
+  PRIntervalTime timeout = mTimeout;
   if (mType == TYPE_REPEATING_PRECISE) {
     // Precise repeating timers advance mTimeout by mDelay without fail before
     // calling Fire().
-    timeout -= TimeDuration::FromMilliseconds(mDelay);
+    timeout -= PR_MillisecondsToInterval(mDelay);
   }
   if (gThread)
     gThread->UpdateFilter(mDelay, timeout, now);
 
   if (mCallbackType == CALLBACK_TYPE_INTERFACE)
     mTimerCallbackWhileFiring = mCallback.i;
   mFiring = PR_TRUE;
   
@@ -451,17 +453,17 @@ void nsTimerImpl::Fire()
 
   mFiring = PR_FALSE;
   mTimerCallbackWhileFiring = nsnull;
 
 #ifdef DEBUG_TIMERS
   if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
     PR_LOG(gTimerLog, PR_LOG_DEBUG,
            ("[this=%p] Took %dms to fire timer callback\n",
-            this, (TimeStamp::Now() - now).ToMilliseconds()));
+            this, PR_IntervalToMilliseconds(PR_IntervalNow() - now)));
   }
 #endif
 
   // Reschedule REPEATING_SLACK timers, but make sure that we aren't armed
   // already (which can happen if the callback reinitialized the timer).
   if (mType == TYPE_REPEATING_SLACK && !mArmed) {
     SetDelayInternal(mDelay); // force mTimeout to be recomputed.
     if (gThread)
@@ -476,17 +478,17 @@ public:
 
   nsTimerEvent(nsTimerImpl *timer, PRInt32 generation)
     : mTimer(timer), mGeneration(generation) {
     // timer is already addref'd for us
     MOZ_COUNT_CTOR(nsTimerEvent);
   }
 
 #ifdef DEBUG_TIMERS
-  TimeStamp mInitTime;
+  PRIntervalTime mInitTime;
 #endif
 
 private:
   ~nsTimerEvent() { 
 #ifdef DEBUG
     if (mTimer)
       NS_WARNING("leaking reference to nsTimerImpl");
 #endif
@@ -502,20 +504,20 @@ NS_IMETHODIMP nsTimerEvent::Run()
   nsRefPtr<nsTimerImpl> timer;
   timer.swap(mTimer);
 
   if (mGeneration != timer->GetGeneration())
     return NS_OK;
 
 #ifdef DEBUG_TIMERS
   if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
-    TimeStamp now = TimeStamp::Now();
+    PRIntervalTime now = PR_IntervalNow();
     PR_LOG(gTimerLog, PR_LOG_DEBUG,
            ("[this=%p] time between PostTimerEvent() and Fire(): %dms\n",
-            this, (now - mInitTime).ToMilliseconds()));
+            this, PR_IntervalToMilliseconds(now - mInitTime)));
   }
 #endif
 
   timer->Fire();
 
   return NS_OK;
 }
 
@@ -529,17 +531,17 @@ nsresult nsTimerImpl::PostTimerEvent()
   // re-initialized after being canceled.
 
   nsRefPtr<nsTimerEvent> event = new nsTimerEvent(this, mGeneration);
   if (!event)
     return NS_ERROR_OUT_OF_MEMORY;
 
 #ifdef DEBUG_TIMERS
   if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
-    event->mInitTime = TimeStamp::Now();
+    event->mInitTime = PR_IntervalNow();
   }
 #endif
 
   // If this is a repeating precise timer, we need to calculate the time for
   // the next timer to fire before we make the callback.
   if (mType == TYPE_REPEATING_PRECISE) {
     SetDelayInternal(mDelay);
     if (gThread) {
@@ -552,29 +554,33 @@ nsresult nsTimerImpl::PostTimerEvent()
   nsresult rv = mEventTarget->Dispatch(event, NS_DISPATCH_NORMAL);
   if (NS_FAILED(rv) && gThread)
     gThread->RemoveTimer(this);
   return rv;
 }
 
 void nsTimerImpl::SetDelayInternal(PRUint32 aDelay)
 {
-  TimeDuration delayInterval = TimeDuration::FromMilliseconds(aDelay);
+  PRIntervalTime delayInterval = PR_MillisecondsToInterval(aDelay);
+  if (delayInterval > DELAY_INTERVAL_MAX) {
+    delayInterval = DELAY_INTERVAL_MAX;
+    aDelay = PR_IntervalToMilliseconds(delayInterval);
+  }
 
   mDelay = aDelay;
 
-  TimeStamp now = TimeStamp::Now();
-  if (mTimeout.IsNull() || mType != TYPE_REPEATING_PRECISE)
+  PRIntervalTime now = PR_IntervalNow();
+  if (mTimeout == 0 || mType != TYPE_REPEATING_PRECISE)
     mTimeout = now;
 
   mTimeout += delayInterval;
 
 #ifdef DEBUG_TIMERS
   if (PR_LOG_TEST(gTimerLog, PR_LOG_DEBUG)) {
-    if (mStart.IsNull())
+    if (mStart == 0)
       mStart = now;
     else
       mStart2 = now;
   }
 #endif
 }
 
 // NOT FOR PUBLIC CONSUMPTION!
--- a/xpcom/threads/nsTimerImpl.h
+++ b/xpcom/threads/nsTimerImpl.h
@@ -45,17 +45,16 @@
 
 #include "nsITimer.h"
 #include "nsIEventTarget.h"
 #include "nsIObserver.h"
 
 #include "nsCOMPtr.h"
 
 #include "prlog.h"
-#include "mozilla/TimeStamp.h"
 
 #if defined(PR_LOGGING)
 static PRLogModuleInfo *gTimerLog = PR_NewLogModule("nsTimerImpl");
 #define DEBUG_TIMERS 1
 #else
 #undef DEBUG_TIMERS
 #endif
 
@@ -70,20 +69,28 @@ static PRLogModuleInfo *gTimerLog = PR_N
 
 enum {
   CALLBACK_TYPE_UNKNOWN   = 0,
   CALLBACK_TYPE_INTERFACE = 1,
   CALLBACK_TYPE_FUNC      = 2,
   CALLBACK_TYPE_OBSERVER  = 3
 };
 
+// Two timer deadlines must differ by less than half the PRIntervalTime domain.
+#define DELAY_INTERVAL_LIMIT    PR_BIT(8 * sizeof(PRIntervalTime) - 1)
+
+// Maximum possible delay (XXX rework to use ms rather than interval ticks).
+#define DELAY_INTERVAL_MAX      (DELAY_INTERVAL_LIMIT - 1)
+
+// Is interval-time t less than u, even if t has wrapped PRIntervalTime?
+#define TIMER_LESS_THAN(t, u)   ((t) - (u) > DELAY_INTERVAL_LIMIT)
+
 class nsTimerImpl : public nsITimer
 {
 public:
-  typedef mozilla::TimeStamp TimeStamp;
 
   nsTimerImpl();
 
   static NS_HIDDEN_(nsresult) Startup();
   static NS_HIDDEN_(void) Shutdown();
 
   friend class TimerThread;
 
@@ -145,20 +152,20 @@ private:
   PRBool                mCanceled;
 
   // The generation number of this timer, re-generated each time the timer is
   // initialized so one-shot timers can be canceled and re-initialized by the
   // arming thread without any bad race conditions.
   PRInt32               mGeneration;
 
   PRUint32              mDelay;
-  TimeStamp             mTimeout;
+  PRIntervalTime        mTimeout;
 
 #ifdef DEBUG_TIMERS
-  TimeStamp             mStart, mStart2;
+  PRIntervalTime        mStart, mStart2;
   static double         sDeltaSum;
   static double         sDeltaSumSquared;
   static double         sDeltaNum;
 #endif
 
 };
 
 #endif /* nsTimerImpl_h___ */