timer: restore semantics of periodic timeout 0

The 'Timer::Session::trigger_periodic' RPC function used to accept 0 as
a way to de-schedule the periodic processing. Several components such as
nitpicker relied on this special case. In "timeout: rework timeout
framework", the value of zero was silently clamped to 1, which has the
opposite effect: triggering signals at the maximum rate. This results in
a visible effect in Sculpt where the leitzentrale-nitpicker instance
produces a constant load of 2% CPU time.

This patch restores the original timer semantics by

- Documenting it in timer_session.h,

- Handling the case explicitly in the timer implementation, and

- Replacing the silent clamping of the unexpected value 0 passed
  to the timeout framework by a diagnostic error message.

Issue #3884
This commit is contained in:
Norman Feske 2021-04-01 13:21:18 +02:00
parent dc8dd3396d
commit 49481dd3fb
3 changed files with 13 additions and 6 deletions

View File

@ -49,7 +49,8 @@ struct Timer::Session : Genode::Session
* Program periodic timeout (in microseconds)
*
* The first period will be triggered after 'us' at the latest,
* but it might be triggered earlier as well.
* but it might be triggered earlier as well. The 'us' value 0
* disables periodic timeouts.
*/
virtual void trigger_periodic(uint64_t us) = 0;

View File

@ -276,7 +276,8 @@ void Timeout_scheduler::_schedule_periodic_timeout(Timeout &timeout,
/* prevent using a period of 0 */
if (period.value == 0) {
period.value = 1;
error("attempt to schedule a periodic timeout of 0");
return;
}
_schedule_timeout(timeout, Microseconds { 0 }, period, handler);
}

View File

@ -65,8 +65,8 @@ class Timer::Session_component : public Genode::Rpc_object<Session>,
** Timer::Session **
********************/
void trigger_once(uint64_t us) override {
void trigger_once(uint64_t us) override
{
/*
* FIXME Workaround for the problem that Alarm scheduler may
* categorize big timeouts into the wrong time counter
@ -80,8 +80,13 @@ class Timer::Session_component : public Genode::Rpc_object<Session>,
_timeout.schedule_one_shot(typed_us, *this);
}
void trigger_periodic(uint64_t us) override {
_timeout.schedule_periodic(Microseconds(us), *this); }
void trigger_periodic(uint64_t us) override
{
if (us)
_timeout.schedule_periodic(Microseconds(us), *this);
else
_timeout.discard();
}
void sigh(Signal_context_capability sigh) override
{