Real-time Linux (Xenomai)

 Radboud University Nijmegen

Exercise #2: Multi-Tasking


Introduction

Modern real-time systems are based on the complementary concepts of multitasking and intertask communication. A multitasking environment allows real-time applications to be constructed as a set of independent tasks, each with a separate thread of execution and its own set of system resources. The intertask communication facilities allow these tasks to synchronize and coordinate their activities. The Xenomai multitasking scheduler uses interrupt-driven, priority-based preemptive task scheduling. It features fast context switch time and low interrupt latency.


Objectives

The following are the primary objectives of this exercise:


Description

Multitasking creates the appearance of many concurrently executing tasks whereas, in fact, the kernel interleaves their execution on the basis of a scheduling algorithm. Each task has its own context, which is the CPU environment and system resources that the task sees each time it is scheduled to run by the kernel. On a context switch, the context of a task is saved in the Task Control Block (TCB). The context of a task includes:

Time in Xenomai Linux

RTIME now; now = rt_timer_read();

Scheduling the Task

A task can be scheduled in two ways.

one-shot mode

periodic mode

As an example, consider a task function which executes an infinite loop which typically reads some inputs, computes some outputs and waits for the next period. Typical code looks like this:

void task_function(void *arg)
{
  rt_task_set_periodic(NULL, TM_NOW, period_ns);
  while (1) {
    /*
      Do your thing here
     */
    rt_task_wait_period(NULL);
  }
  return;
}

Exercises 

Exercise 2a.  

Write a program which runs five tasks, e.g. use

#define NTASKS 5
RT_TASK task[NTASKS];
Give all tasks a different name and run them with the same priority in one-shot mode. Each task executes the following function  :

void demo(void *arg) {
    RT_TASK_INFO curtaskinfo;
    rt_task_inquire(NULL,&curtaskinfo);
    rt_printf("Task name: %s ", curtaskinfo.name);
}

Execute the program and describe the resulting output.

Exercise 2b. 

Note that the demo task has an argument arg which is a pointer to type void. An integer argument can be passed as a reference to a task during the call to rt_task_start(). For instance, for a variable int index, use

rt_task_start(&taskd.., &demo, &index)

Modify the program of exercise 2a such that an unique argument is provided to each of the five tasks. Let the tasks print this number by casting and derefencing the number using, for instance

int num = * (int *)arg;

Again, each task has the same priority. Execute the program and describe its output.

Exercise 2c. 

Note that the correctness of solutions to 2b might depend on the fast evaluation of the reference by the task. If needed, modify your solution to 2b such that all tasks get a reference to the same variable (which changes the value between the start of the tasks). Define
RTIME sec = 1e9;
and insert in each task before int num = * (int *)arg; a real-time sleep statement
rt_task_sleep(sec);

To avoid termination when the main loop stops, end the main loop with the statements:

Makefile, 319B
printf("End program by CTRL-C\n");
pause();

Execute the program and describe the resulting output.

Exercise 2d. 

Modify the program of exercise 2b by assigning each task a unique priority such that the task which is started first gets the lowest priority and the tasks started later get a higher priority. Is there any difference in output? Has the order in which the five tasks print their message changed? If not, explain why.

Exercise 2e. 

Rewrite the program of exercise 2b into one where three tasks are running periodically with periods of 1, 2 and 3 seconds, respectively. All tasks have the same priority; they should start with an rt_task_sleep of 1 second. Then execute a loop in which they print a message and wait for the next period.

Similar to exercise 2c, add a pause() to avoid termination when main ends.

Explain the resulting output.


Last Updated: 18 May 2022 (by Mathijs Schuts)
Created by: Harco Kuppens
h.kuppens@cs.ru.nl