From 50e9a5123e65e77cd4aeca4c8b0eded16579bb14 Mon Sep 17 00:00:00 2001 From: Juri Lelli Date: Tue, 22 Nov 2016 12:29:27 +0000 Subject: rt-app: implement relative/absolute timers Implement "relative" (current behavior) and "absolute" working modes for timer events. Text added in doc/tutorial.txt gives more information about the two modes. Signed-off-by: Juri Lelli Acked-by: Vincent Guittot --- doc/tutorial.txt | 64 +++++++++++++++++++++++++++++++++++++++++++++++ src/rt-app.c | 3 ++- src/rt-app_parse_config.c | 6 +++++ src/rt-app_types.h | 1 + 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/doc/tutorial.txt b/doc/tutorial.txt index dfcc405..a4455b6 100644 --- a/doc/tutorial.txt +++ b/doc/tutorial.txt @@ -321,6 +321,70 @@ below: } } +Timers can work with a "relative" or an "absolute" reference. By default they +work in "relative" mode, but this mode can also be explicity specified as the +following: + + "phases" : { + "phase0" : { + "loop" : 10, + "run0" : 10000, + "timer0" : { "ref" : "unique", "period" : 20000, "mode" : "relative" }, + } + +"relative" mode means that the reference for setting the next timer event is +relative to the end of the current phase. This in turn means that if, for some +reason (i.e., clock frequency was too low), events in a certain phase took too +long to execute and the timer of that phase couldn't actually fire at all, the +next phase won't be affected. For example: + + +---- + +-----+ +-------------------+-----+ +--- + |r0 | |r0 | |r0 |r0 | |r0 + | | | | | | | | + o-----------o-----------o-------------------o-----------o-------> + 0 10 20 30 40 50 60 70 80 100 120 + ^ ^ ^ ^ + | | | MISS! | + + + + + + Timer0 Timer0 Timer0 Timer0 + +In this example character "o" denotes when phases finish/start. Third +activation of Timer0 is missed, since r0 executed for more that 20ms. However +the next phase is not affected as Timer0 was set considering the instant of +time when the misbehaving r0 finished executing. + +"absolute" mode is specified as the following: + + "phases" : { + "phase0" : { + "loop" : 10, + "run0" : 10000, + "timer0" : { "ref" : "unique", "period" : 20000, "mode" : "absolute" }, + } + +"absolute" mode means that the reference for setting the next timer event is +fixed and always consider the starting time of the first phase. This means that +if, for some reason (i.e., clock frequency was too low), events in a certain +phase took too long to execute and the timer of that phase couldn't actually +fire at all, the next phase (and potentially other subsequent phases) _will_ be +affected. For example, considering again the example above: + + +---- + +-----+ +-------------------+-----+-----+ +--- + |r0 | |r0 | |r0 |r0 |r0 | |r0 + | | | | | | | | | + o-----------o-----------o-------------------o-----o---------o----> + 0 10 20 30 40 50 60 70 80 100 120 + ^ ^ ^ ^ ^ + | | | MISS! | MISS! | + + + + + + + Timer0 Timer0 Timer0 Timer0 Timer0 + +Third activation of Timer0 is missed, since r0 executed for more that 20ms. +Even if 4th activation of r0 executes for 10ms (as specified in the +configuration), 4th Timer0 is still missed because the reference didn't change. +In this example 5th activation of r0 then managed to recover, but in general it +depends on how badly a certain phase misbehaves. + * lock : String. Lock the mutex defined by the string value. * unlock : String. Unlock the mutex defined by the string value. diff --git a/src/rt-app.c b/src/rt-app.c index 2627d58..fb4b37d 100644 --- a/src/rt-app.c +++ b/src/rt-app.c @@ -339,7 +339,8 @@ static int run_event(event_data_t *event, int dry_run, t_wu = timespec_sub(&t_now, &rdata->res.timer.t_next); ldata->wu_latency += timespec_to_usec(&t_wu); } else { - clock_gettime(CLOCK_MONOTONIC, &rdata->res.timer.t_next); + if (rdata->res.timer.relative) + clock_gettime(CLOCK_MONOTONIC, &rdata->res.timer.t_next); ldata->wu_latency = 0UL; } } diff --git a/src/rt-app_parse_config.c b/src/rt-app_parse_config.c index b0f302e..fbc4612 100644 --- a/src/rt-app_parse_config.c +++ b/src/rt-app_parse_config.c @@ -181,6 +181,7 @@ static int init_timer_resource(rtapp_resource_t *data, const rtapp_options_t *op { log_info(PIN3 "Init: %s timer", data->name); data->res.timer.init = 0; + data->res.timer.relative = 1; } static int init_cond_resource(rtapp_resource_t *data, const rtapp_options_t *opts) @@ -489,6 +490,11 @@ parse_thread_event_data(char *name, struct json_object *obj, rdata = &(opts->resources[data->res]); ddata = &(opts->resources[data->dep]); + tmp = get_string_value_from(obj, "mode", TRUE, "relative"); + if (!strncmp(tmp, "absolute", strlen("absolute"))) + rdata->res.timer.relative = 0; + free(tmp); + log_info(PIN2 "type %d target %s [%d] period %d", data->type, rdata->name, rdata->index, data->duration); return; } diff --git a/src/rt-app_types.h b/src/rt-app_types.h index 8998320..718ce77 100644 --- a/src/rt-app_types.h +++ b/src/rt-app_types.h @@ -87,6 +87,7 @@ struct _rtapp_signal { struct _rtapp_timer { struct timespec t_next; int init; + int relative; }; struct _rtapp_iomem_buf { -- cgit v1.2.3