timer: bugfix and test trigger_periodic (run/timer)

Fix #699
This commit is contained in:
Martin Stein 2013-03-21 16:54:35 +01:00 committed by Norman Feske
parent 5da281c1d8
commit dc814ff0f1
3 changed files with 38 additions and 3 deletions

View File

@ -36,6 +36,9 @@ namespace Timer {
/**
* Program periodic timeout (in microseconds)
*
* The first period will be triggered after 'us' at the latest,
* but it might be triggered earlier as well.
*/
virtual void trigger_periodic(unsigned us) = 0;

View File

@ -110,6 +110,7 @@ namespace Timer {
void sigh(Signal_context_capability sigh) { _sigh = sigh; }
void periodic(bool periodic) { _periodic = periodic; }
bool periodic() { return _periodic; }
/*********************
@ -182,10 +183,13 @@ namespace Timer {
/**
* Called from the '_trigger' function executed by the server activation
*/
void schedule_timeout(Genode::Alarm *alarm, Genode::Alarm::Time timeout)
void schedule_timeout(Wake_up_alarm *alarm, Genode::Alarm::Time timeout)
{
Alarm::Time now = _platform_timer->curr_time();
schedule_absolute(alarm, now + timeout);
if (alarm->periodic()) {
handle(now); /* update '_now' in 'Alarm_scheduler' */
schedule(alarm, timeout);
} else schedule_absolute(alarm, now + timeout);
/* interrupt current 'wait_for_timeout' */
_platform_timer->schedule_timeout(0);
@ -258,7 +262,7 @@ namespace Timer {
unsigned long elapsed_ms() const
{
unsigned long const now = _timeout_scheduler.curr_time();
return now - _initial_time;
return (now - _initial_time) / 1000;
}
void msleep(unsigned) { /* never called at the server side */ }

View File

@ -91,6 +91,34 @@ int main(int argc, char **argv)
main_timer.msleep(2000);
printf("timeout fired\n");
/* check periodic timeouts */
Signal_receiver sig_rcv;
Signal_context sig_cxt;
Signal_context_capability sig = sig_rcv.manage(&sig_cxt);
main_timer.sigh(sig);
enum { PTEST_TIME_US = 2000000 };
unsigned period_us = 500000, periods = PTEST_TIME_US / period_us, i = 0;
printf("start periodic timeouts\n");
for (unsigned j = 0; j < 5; j++) {
unsigned elapsed_ms = main_timer.elapsed_ms();
main_timer.trigger_periodic(period_us);
while (i < periods) {
Signal s = sig_rcv.wait_for_signal();
i += s.num();
}
elapsed_ms = main_timer.elapsed_ms() - elapsed_ms;
unsigned const min_ms = ((i - 1) * period_us) / 1000;
unsigned const max_ms = (i * period_us) / 1000;
if (min_ms > elapsed_ms || max_ms < elapsed_ms) {
PERR("Timing %u ms period %u times failed: %u ms (min %u, max %u)",
period_us / 1000, i, elapsed_ms, min_ms, max_ms);
return -1;
}
printf("Done %u ms period %u times: %u ms (min %u, max %u)\n",
period_us / 1000, i, elapsed_ms, min_ms, max_ms);
i = 0, period_us /= 2, periods = PTEST_TIME_US / period_us;
}
/* create timer clients with different periods */
for (unsigned period_msec = 1; period_msec < 28; period_msec++) {
Timer_client *tc = new (env()->heap()) Timer_client(period_msec);