From e410ecc9957ddf27201fa67a9fe7705270d54c1a Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 12 Aug 2015 09:58:58 +0200 Subject: [PATCH] timer test: trigger timeout-masking bug Issue #1646 --- repos/os/src/test/timer/main.cc | 47 ++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/repos/os/src/test/timer/main.cc b/repos/os/src/test/timer/main.cc index 38ff43c92..899c78a56 100644 --- a/repos/os/src/test/timer/main.cc +++ b/repos/os/src/test/timer/main.cc @@ -75,6 +75,37 @@ class Timer_client : public Genode::List::Element, }; +/** + * Timer client that continuously reprograms timeouts + */ +struct Timer_stressful_client : Timer::Connection, Genode::Thread +{ + unsigned long us; + + /* + * In principle, we could constantly execute 'trigger_once' in a busy loop. + * This however would significantly skew the precision of the timer on + * platforms w/o priority support. The behaviour would highly depend on the + * kernel's scheduling and its parameters such as the time-slice length. To + * even out those kernel-specific peculiarities, we let the stressful + * client delay its execution after each iteration instead of keeping it + * busy all the time. The delay must be smaller than scheduled 'us' to + * trigger the edge case of constantly reprogramming timeouts that never + * trigger. + */ + Timer::Connection delayer; + + void entry() { for (;;) { trigger_once(us); delayer.usleep(us/2); } } + + Timer_stressful_client(unsigned long us) + : + Thread("timer_stressful_client"), us(us) + { + Genode::Thread::start(); + } +}; + + using namespace Genode; extern "C" int usleep(unsigned long usec); @@ -87,10 +118,18 @@ int main(int argc, char **argv) static Genode::List timer_clients; static Timer::Connection main_timer; - /* check long single timeout */ - printf("register two-seconds timeout...\n"); - main_timer.msleep(2000); - printf("timeout fired\n"); + /* + * Check long single timeout in the presence of another client that + * reprograms timeouts all the time. + */ + { + /* will get destructed at the end of the current scope */ + Timer_stressful_client stressful_client(250*1000); + + printf("register two-seconds timeout...\n"); + main_timer.msleep(2000); + printf("timeout fired\n"); + } /* check periodic timeouts */ Signal_receiver sig_rcv;