]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
simplify logic
authoridgay <idgay>
Fri, 11 Aug 2006 21:03:52 +0000 (21:03 +0000)
committeridgay <idgay>
Fri, 11 Aug 2006 21:03:52 +0000 (21:03 +0000)
tos/lib/timer/TransformAlarmCounterC.nc
tos/lib/timer/VirtualizeTimerC.nc

index 69da71506c6f83a5f07a2a73fcb8ea361b47f87c..d6341b8a7302c27c634301b25426f42f783a505d 100644 (file)
@@ -146,7 +146,6 @@ implementation
   {
     atomic
     {
-
       m_upper++;
       if ((m_upper & OVERFLOW_MASK) == 0)
        signal Counter.overflow();
@@ -178,31 +177,23 @@ implementation
 
   void set_alarm()
   {
-    to_size_type now = call Counter.get(), expires, remaining;
-
-    /* m_t0 is assumed to be in the past. If it's > now, we assume
-       that time has wrapped around */
-
-    expires = m_t0 + m_dt;
-
-    /* The cast is necessary to get correct wrap-around arithmetic */
-    remaining = (to_size_type)(expires - now);
+    to_size_type now = call Counter.get(), elapsed = now - m_t0, remaining;
 
-    /* if (expires <= now) remaining = 0; in wrap-around arithmetic */
-    if (m_t0 <= now)
-      {
-       if (expires >= m_t0 && // if it wraps, it's > now
-           expires <= now)
-         remaining = 0;
-      }
+    m_skip_overflows = 0;
+    if (elapsed >= m_dt)
+    {
+      remaining = 0;
+      m_t0 += m_dt;
+      m_dt = 0;
+    }
     else
-      {
-       if (expires >= m_t0 || // didn't wrap so < now
-           expires <= now)
-         remaining = 0;
-      }
+    {
+      remaining = m_dt - elapsed;
 
-    if (remaining > MAX_DELAY * 2)
+      /* MAX_DELAY is 1/2 an underlying counter overflow time. Just count
+        overflows if the timer is far in the future, and we'll set an
+        alarm once we're close to the deadline. */
+      if (remaining > MAX_DELAY * 2)
       {
        if (remaining >= MAX_DELAY * 2 * (to_size_type)256)
          m_skip_overflows = 255;
@@ -210,20 +201,19 @@ implementation
          m_skip_overflows = remaining / (MAX_DELAY * 2);
        return;
       }
-    else
-      m_skip_overflows = 0;
 
-    if (remaining > MAX_DELAY)
+      if (remaining > MAX_DELAY)
       {
        m_t0 = now + MAX_DELAY;
        m_dt = remaining - MAX_DELAY;
        remaining = MAX_DELAY;
       }
-    else
+      else
       {
        m_t0 += m_dt;
        m_dt = 0;
       }
+    }
     call AlarmFrom.startAt((from_size_type)now << bit_shift_right,
                           (from_size_type)remaining << bit_shift_right);
   }
index 8b6bea257a87c623608bbd936b46d9d640a0b359..b36e75a8162974e0e550fa5d1db3459426d382f1 100644 (file)
@@ -55,41 +55,33 @@ implementation
   } Timer_t;
 
   Timer_t m_timers[NUM_TIMERS];
-
-  enum {
-    /* bitmask */
-    S_TIMER_RUNNING = 1,
-    S_TIMER_CHANGED = 2
-  };
-  bool state;
+  bool m_timers_changed;
 
   task void executeTimersNow();
 
-  void executeTimers(uint32_t then)
+  void executeTimers()
   {
-    int32_t min_remaining = (1UL<<31)-1; //max signed int32_t
+    /* This code supports a maximum dt of MAXINT. If min_remaining and
+       remaining were switched to uint32_t, and the logic changed a
+       little, dt's up to 2^32-1 should work (but at a slightly higher
+       runtime cost). */
+    uint32_t now = call TimerFrom.getNow();
+    int32_t min_remaining = (1UL << 31) - 1; /* max int32_t */
     bool min_remaining_isset = FALSE;
-    int num;
+    uint8_t num;
 
-    /* We always come here with the timer stopped */
-    state = 0;
+    call TimerFrom.stop();
+    m_timers_changed = FALSE;
 
-    for(num=0; num<NUM_TIMERS; num++)
+    for (num=0; num<NUM_TIMERS; num++)
     {
       Timer_t* timer = &m_timers[num];
 
       if (timer->isrunning)
       {
-       // Calculate "remaining" before the timer is fired.  If a timer
-       // restarts itself in a fired event, then we 1) need a consistent
-       // "remaining" value to work with, and no worries because 2) all
-       // start commands post executeTimersNow, so the timer will be
-       // recomputed later, anyway.
+       uint32_t elapsed = now - timer->t0;
 
-       uint32_t elapsed = then - timer->t0;
-       int32_t remaining = timer->dt - elapsed;
-
-       if (remaining <= 0)
+       if (elapsed >= timer->dt)
        {
          if (timer->isoneshot)
          {
@@ -97,70 +89,52 @@ implementation
          }
          else
          {
-           // The remaining time is non-positive (the timer had fired).
-           // So add dt to convert it to remaining for the next event.
+           // Update timer for next event
            timer->t0 += timer->dt;
-           remaining += timer->dt; 
+           // Update elapsed so we compute the time of the next event
+           elapsed -= timer->dt;
          }
 
          signal Timer.fired[num]();
        }
 
-       // check isrunning in case the timer was stopped in the fired
+       // Check isrunning in case the timer was stopped in the fired
        // event or this was a one shot timer; note that a one shot
        // timer that was restarted in its fired event will push us
-       // through here with remaining <= 0, but we're already scheduled
-       // an executeTimersTask in that case (and suppressed setting
-       // TimerFrom)
+       // through here with a value of remaining <= 0. But we're
+       // already scheduled an executeTimersNow in that case (and
+       // suppressed setting TimerFrom)
        if (timer->isrunning)
        {
+         int32_t remaining = timer->dt - elapsed;
+
          if (remaining < min_remaining)
-           min_remaining = remaining;
-         min_remaining_isset = TRUE;
+           {
+             min_remaining = remaining;
+             min_remaining_isset = TRUE;
+           }
        }
       }
     }
 
-    if (!(state & S_TIMER_CHANGED) && min_remaining_isset)
+    if (!m_timers_changed && min_remaining_isset)
     {
       if (min_remaining <= 0)
        post executeTimersNow();
       else
-       {
-         call TimerFrom.startOneShotAt(then, min_remaining);
-         state |= S_TIMER_RUNNING;
-       }
+       call TimerFrom.startOneShotAt(now, min_remaining);
     }
   }
   
 
   event void TimerFrom.fired()
   {
-    executeTimers(call TimerFrom.gett0() + call TimerFrom.getdt());
+    executeTimers();
   }
 
   task void executeTimersNow()
   {
-    /* If we set a timer, try and stop it. But if it believes it's
-       not running, that means that the execution of its fired event
-       is pending, so we:
-       - don't need to call executeTimers (it will happen soon)
-       - we must not call executeTimers, because that would change the
-         timer's setting, confusing the pending call to TimerFrom.fired
-        (it would call executeTimers with an incorrect "then"
-        parameter)
-       We need to use an atomic section even though it's a "timer",
-       because it's based on an underlying alarm, whose transitions
-       are asynchronous (yuck?)
-    */
-    if (state & S_TIMER_RUNNING)
-      atomic
-       {
-         if (!call TimerFrom.isRunning())
-           return;
-         call TimerFrom.stop();
-       }
-    executeTimers(call TimerFrom.getNow());
+    executeTimers();
   }
 
   void startTimer(uint8_t num, uint32_t t0, uint32_t dt, bool isoneshot)
@@ -170,7 +144,7 @@ implementation
     timer->dt = dt;
     timer->isoneshot = isoneshot;
     timer->isrunning = TRUE;
-    state |= S_TIMER_CHANGED;
+    m_timers_changed = TRUE;
     post executeTimersNow();
   }