@@ -296,39 +296,77 @@ void Timer::HandleComplete()
296296Error Timer::HandleExpiredTimers (Layer& aLayer)
297297{
298298 // expire each timer in turn until an unexpired timer is reached or the timerlist is emptied.
299- while (aLayer.mTimerList )
299+
300+ // The platform timer API has MSEC resolution so expire any timer with less than 1 msec remaining.
301+ Epoch currentEpoch = Timer::GetCurrentEpoch () + 1 ;
302+
303+ VerifyOrExit (aLayer.mTimerList != NULL , );
304+
305+ // Verify that there are any timers to be processed
306+ if (Timer::IsEarlierEpoch (aLayer.mTimerList ->mAwakenEpoch , currentEpoch))
300307 {
301- const Epoch kCurrentEpoch = Timer::GetCurrentEpoch ();
308+ // Bound the number of timers processed to those that are already on the
309+ // expired queue. We copy the expired timers onto the queue pointed to
310+ // by headTimer, and then reset the timer queue in the system layer to
311+ // point to the first unexpired timer.
312+ Timer * headTimer = aLayer.mTimerList ;
313+ Timer * cursorTimer = aLayer.mTimerList ;
314+
315+ while (cursorTimer->mNextTimer != NULL &&
316+ Timer::IsEarlierEpoch (cursorTimer->mNextTimer ->mAwakenEpoch , currentEpoch))
317+ {
318+ cursorTimer = cursorTimer->mNextTimer ;
319+ }
302320
303- // The platform timer API has MSEC resolution so expire any timer with less than 1 msec remaining.
304- if (Timer::IsEarlierEpoch (aLayer.mTimerList ->mAwakenEpoch , kCurrentEpoch + 1 ))
321+ // unexpired timer list points to the next unexpired timer
322+ aLayer.mTimerList = cursorTimer->mNextTimer ;
323+
324+ // list pointed to by the headTimer terminates
325+ cursorTimer->mNextTimer = NULL ;
326+
327+ aLayer.mTimerComplete = true ;
328+
329+ while (headTimer != NULL )
305330 {
306- Timer& lTimer = *aLayer. mTimerList ;
307- aLayer. mTimerList = lTimer. mNextTimer ;
308- lTimer. mNextTimer = NULL ;
331+ cursorTimer = headTimer ;
332+ headTimer = headTimer-> mNextTimer ;
333+ cursorTimer-> mNextTimer = NULL ;
309334
310- aLayer.mTimerComplete = true ;
311- lTimer.HandleComplete ();
312- aLayer.mTimerComplete = false ;
335+ cursorTimer->HandleComplete ();
336+ }
337+ aLayer.mTimerComplete = false ;
338+ }
339+
340+ if (aLayer.mTimerList )
341+ {
342+ // timers still exist so restart the platform timer.
343+ uint64_t delayMilliseconds;
344+
345+ // re-read the timer to account for the time that has elapsed while we
346+ // were processing the expired timers
347+
348+ currentEpoch = Timer::GetCurrentEpoch ();
349+
350+ if (aLayer.mTimerList ->mAwakenEpoch < currentEpoch)
351+ {
352+ delayMilliseconds = 0 ;
313353 }
314354 else
315355 {
316- // timers still exist so restart the platform timer.
317- const uint64_t kDelayMilliseconds = aLayer.mTimerList ->mAwakenEpoch - kCurrentEpoch ;
318-
319- /*
320- * Original kDelayMilliseconds was a 32 bit value. The only way in which this could overflow is if time went backwards
321- * (e.g. as a result of a time adjustment from time synchronization). Verify that the timer can still be executed
322- * (even if it is very late) and exit if that is the case. Note: if the time sync ever ends up adjusting the clock, we
323- * should implement a method that deals with all the timers in the system.
324- */
325- VerifyOrDie (kDelayMilliseconds <= UINT32_MAX);
326-
327- aLayer.StartPlatformTimer (static_cast <uint32_t >(kDelayMilliseconds ));
328- break ; // all remaining timers are still ticking.
356+ delayMilliseconds = aLayer.mTimerList ->mAwakenEpoch - currentEpoch;
329357 }
358+ /*
359+ * StartPlatformTimer() accepts a 32bit value in milliseconds. Epochs are 64bit numbers. The only way in which this could
360+ * overflow is if time went backwards (e.g. as a result of a time adjustment from time synchronization). Verify that the
361+ * timer can still be executed (even if it is very late) and exit if that is the case. Note: if the time sync ever ends up
362+ * adjusting the clock, we should implement a method that deals with all the timers in the system.
363+ */
364+ VerifyOrDie (delayMilliseconds <= UINT32_MAX);
365+
366+ aLayer.StartPlatformTimer (static_cast <uint32_t >(delayMilliseconds));
330367 }
331368
369+ exit:
332370 return WEAVE_SYSTEM_NO_ERROR;
333371}
334372#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
0 commit comments