====== HOWTO build a basic cyclic application ======
The cyclic RT task will use the basic application task which was built in the previous section ([[realtime:documentation:howto:applications:application_base|HOWTO build a simple RT application]]).
===== Cyclic Task =====
A cyclic task is one which is repeated after a fixed period of time like reading sensor data every 100 ms. The execution time for the cyclic task should always be less than the period of the task.
Following are the mechanisms which we will be looking at for implementing cyclic task:
* nanosleep
* EDF Scheduling
===== Current Time =====
There are multiple ways to get current time – gettimeofday, time, clock_gettime, and some other processor specific implementations. Some of them, like gettimeofday, will get time from the system clock. The system clock can be modified by other processes. Which means that the clock can go back in time. clock_gettime with CLOCK_MONOTONIC clock can be used to avoid this problem. CLOCK_MONOTONIC argument ensures that we get a nonsettable monotonically increasing clock that measures time from some unspecified point in the past that does not change after system startup[1]. It is also important to ensure we do not waste a lot of CPU cycles to get the current time. CPU specific implementations to get the current time will be helpful here.
===== Basic Stub =====
Any mechanism for implementing a cyclic task can be divided into the following parts:
* periodic_task_init(): Initialization code for doing things like requesting timers, initializing variables, setting timer periods.
* do_rt_task(): The real time task is done here.
* wait_rest_of_period(): After the task is done, wait for the rest of the period. The assumption here is the task requires less time to complete compared to the period length.
* struct period_info: This is a struct which will be used to pass around data required by the above mentioned functions.
The stub for the real time task will look like:
void *simple_cyclic_task(void *data)
{
struct period_info pinfo;
periodic_task_init(&pinfo);
while (1) {
do_rt_task();
wait_rest_of_period(&pinfo);
}
return NULL;
}
===== Examples =====
==== clock_nanosleep ====
clock_nanosleep() is used to ask the process to sleep for certain amount of time. nanosleep() can also be used to sleep. But, nanosleep() uses CLOCK_REALTIME which can be changed by another processes and hence can be discontinuous or jump back in time. In clock_nanosleep, CLOCK_MONOTONIC is explicitly specified. This is a immutable clock which does not change after startup.
The periodicity is achieved by using absolute time to specify the end of each period. More information on clock_nanosleep at http://man7.org/linux/man-pages/man2/clock_nanosleep.2.html
struct period_info {
struct timespec next_period;
long period_ns;
};
static void inc_period(struct period_info *pinfo)
{
pinfo->next_period.tv_nsec += pinfo->period_ns;
while (pinfo->next_period.tv_nsec >= 1000000000) {
/* timespec nsec overflow */
pinfo->next_period.tv_sec++;
pinfo->next_period.tv_nsec -= 1000000000;
}
}
static void periodic_task_init(struct period_info *pinfo)
{
/* for simplicity, hardcoding a 1ms period */
pinfo->period_ns = 1000000;
clock_gettime(CLOCK_MONOTONIC, &(pinfo->next_period));
}
static void do_rt_task()
{
/* Do RT stuff here. */
}
static void wait_rest_of_period(struct period_info *pinfo)
{
inc_period(pinfo);
/* for simplicity, ignoring possibilities of signal wakes */
clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pinfo->next_period, NULL);
}
==== EDF Scheduler ====
Recently, earliest deadline first scheduling algorithm has been merged in the mainline kernel. Now, users can specify runtime, period and deadline of a task and they scheduler will run the task every specified period and will make sure the deadline is met. The scheduler will also let user know if the tasks(or a set of tasks) cannot be scheduled because the deadline won't be met.
More information about the EDF scheduler including an example of implementation can be found at: https://www.kernel.org/doc/Documentation/scheduler/sched-deadline.txt