Real-time Linux (Xenomai)

 Radboud University Nijmegen

Exercise #7: Round-Robin Task Scheduling


Introduction

For task with equal priority, the Xenomai scheduler supports both FIFO scheduling and round-robin policies. The round-robin policy is similar to a time-sharing operating system runs each active process in turn for its share of time (its "timeslice").


Objectives

The following are the primary objectives of this exercise:

  • To demonstrate the use of  round-robin task scheduling facilities.

Description 

FIFO Scheduling

With FIFO scheduling, a task will only preempt a task with a lower priority; it never preempts a task with the same or lower priority. When multiple tasks of the same priority are ready to run, the one which was queued first in the waiting queue of the scheduler, is run first (following FIFO ordering). Only when the first task is ready, the scheduler may execute the second waiting task from the waiting queue.

Round-Robin Scheduling

A round-robin scheduling algorithm tries to achieve fair scheduling among all ready tasks with the same priority. Without round-robin scheduling, a single task can usurp the processor by never blocking and, hence, never giving other equal priority tasks a chance to run.

Round-robin scheduling achieves fair allocation of the CPU to tasks of the same priority by an approach known as time slicing. Each task executes for a defined interval or time slice; then another task executes for an equal interval, in rotation. The allocation is fair in that no task of a priority group gets a second slice of time before the other tasks of a group are given a slice.

Round-robin scheduling can be enabled with a call to the following function

rt_task_set_mode(0,T_RRB ,NULL);

and a call to 

rt_task_slice(task_descr,quantum)

to set the round robin time slice interval value to quantum clock ticks (because of legacy reasons, this quantum has to be specified in terms of jiffies - see exercise 2). This interval is the amount of time each task is allowed to run before relinquishing the processor to another equal priority task. Argument task_desc is the task descriptor at which the round robin interval is set.

Note: with the function rt_task_set_mode  one can also disable  round robin scheduling again.

Example: Round-robin Scheduling

In the example below, three tasks with the same priority print their task ids on the console, similar to the example program of exercise 6.  Because round-robin requires jiffies, the task timing part has been changed.

------------------------------------------------------------------------------------
/* ex07a.c */

 

#include <stdio.h>

#include <signal.h>

#include <unistd.h>

#include <sys/mman.h>

 

#include <native/task.h>

#include <native/timer.h>

#include <native/sem.h>

 

#include  <rtdk.h>

#include <sys/io.h>

 

#define NTASKS 3

 

RT_TASK demo_task[NTASKS];

RT_SEM mysync;

 

// set new baseperiod for the clock :

// - clock only increments counter when a base period is passed

// - the unit of the clock counter is called a jiffie, which in fact

//   represents that a baseperiod is passed

//   e.g. If 10 baseperiods are passed, the clock gives an increase

//   in 10 jiffies

#define BASEPERIOD 1e6   // baseperiod in ns.

 

// when base period is set, all times in the api are expressed in jiffies

#define EXECTIME   200   // execution time in jiffies

#define SPINTIME    10   // spin time in jiffies

 

void demo(void *arg)

{

    RTIME starttime, runtime;

    int num=*(int *)arg;

    RT_TASK *curtask;

    RT_TASK_INFO curtaskinfo;

 

    rt_printf("Task  : %d\n",num);

 

    rt_sem_p(&mysync,TM_INFINITE);

 

    // let the task run RUNTIME(=200) jiffies in steps of SPINTIME(=20) jiffies

    runtime = 0;

    while(runtime < EXECTIME) {

      rt_timer_spin(SPINTIME*BASEPERIOD);  // spin cpu doing nothing

      // note: rt_timer_spin function does not accept jiffies only nanoseconds

      //       deviates from timing conventions throughout the Xenomai API

 

      runtime = runtime + SPINTIME;

 

      rt_printf("Running Task  : %d  at time : %d\n",num,runtime);

    }

    rt_printf("End Task  : %d\n",num);

}

 

//startup code

void startup()

{

  int i;

  char  str[10] ;

 

  // semaphore to sync task startup on

  rt_sem_create(&mysync,"MySemaphore",0,S_FIFO);

 

  // change to period mode because round robin does not work

  // in one shot mode

  rt_timer_set_mode(BASEPERIOD);// set tick period

  for(i=0; i < NTASKS; i++) {

    rt_printf("start task  : %d\n",i);

    sprintf(str,"task%d",i);

    rt_task_create(&demo_task[i], str, 0, 50, 0);

    rt_task_start(&demo_task[i], &demo, &i);

  }

  rt_printf("wake up all tasks\n");

  rt_sem_broadcast(&mysync);

}

 

void init_xenomai() {

  /* Avoids memory swapping for this program */

  mlockall(MCL_CURRENT|MCL_FUTURE);

 

  /* Perform auto-init of rt_print buffers if the task doesn't do so */

  rt_print_auto_init(1);

}

 

int main(int argc, char* argv[])

{

  printf("\nType CTRL-C to end this program\n\n" );

 

  // code to set things to run xenomai

  init_xenomai();

 

  //startup code

  startup();

 

  // wait for CTRL-c is typed to end the program

  pause();

}


------------------------------------------------------------------------------------

Exercises

Exercise 7a.

Run the program above and observe its behaviour.

Exercise 7b.

Schedule all three tasks according to the round robin policy and explain the output.

Exercise 7c. 

Add a fourth task which is the same as the other three tasks, but has a priority of 80. Describe and explain the output from running the program. Does it make a difference whether task four uses the round-robin policy or not? Explain why.


Last Updated: 29 August 2009 (Jozef Hooman)
Created by: Harco Kuppens
h.kuppens@cs.ru.nl