Skip to content

Commit

Permalink
SystemLayerImplSelect: libev: avoid timers firing slightly too early (p…
Browse files Browse the repository at this point in the history
…roject-chip#28434)

This fixes a ReportEngine problem that was caused by libev based timers
firing slightly (in the range of 20mS) too early, because libev by
default uses the time when events started processing as the "now"
reference for relative timers for efficiency reasons.

To ensure timers cannot fire early, timer setup must compensate for
any difference between ev_now() which is the time events started
processing and ev_time(), which is the actual current time (but is
a bit less efficient to obtain).

# Conflicts:
#	src/system/SystemLayerImplSelect.cpp
  • Loading branch information
plan44 committed Aug 22, 2023
1 parent cbc3865 commit a085fd8
Showing 1 changed file with 6 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/system/SystemLayerImplSelect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,12 @@ CHIP_ERROR LayerImplSelect::StartTimer(Clock::Timeout delay, TimerCompleteCallba
ev_timer_init(&timer->mLibEvTimer, &LayerImplSelect::HandleLibEvTimer, 1, 0);
timer->mLibEvTimer.data = timer;
auto t = Clock::Milliseconds64(delay).count();
ev_timer_set(&timer->mLibEvTimer, static_cast<double>(t) / 1E3, 0.);
// Note: libev uses the time when events started processing as the "now" reference for relative timers,
// for efficiency reasons. This point in time is represented by ev_now().
// The real time is represented by ev_time().
// As some chip code relies on timers to fire NEVER even only a bit early, we must increase the
// relative value passed to ev_timer_set().
ev_timer_set(&timer->mLibEvTimer, (static_cast<double>(t) / 1E3) + ev_time() - ev_now(mLibEvLoopP), 0.);
(void) mTimerList.Add(timer);
ev_timer_start(mLibEvLoopP, &timer->mLibEvTimer);
return CHIP_NO_ERROR;
Expand Down

0 comments on commit a085fd8

Please sign in to comment.