Real Time Systems: Notes

RTLinux

 

RTLinux


Existing widely used operating systems, including Unix, MS Windows, and Linux, were not designed with hard real time requirements in mind. There does not appear to be any practical way to modify them to achieve hard real-time predictability. It would be very costly to develop an entire new operating system (including all device drivers) from scratch. RT Linux attempts to solve this problem by providing a very restricted set of capabilities for the hard real-time portion of an application. An application is expected to be partitioned into a small hard-real-time part, which runs in the kernel as one or more RTLinux threads, and the rest of the application, which runs as one or more ordinary Linux processes.

RTLinux attempts to provide a subset of the POSIX API. This is very restricted, though, and should not be confused with the normal Linux API (which it resembles). The big difference is that the RTLinux functions are implemented to be called from *inside* the kernel, and the ordinary Linux functions are implemented to be called from *outside* the kernel.


RTLinux References


Linux Kernel Modules


Linux Kernel Module Internal Structure

module consists of four parts:


Linux Kernel Module Restrictions


Linux Module Shell-level Utilities


Example Output of lsmode

Module                  Size  Used by    Not tainted
loop                   12888   0
soundcore               7108   0 (autoclean)
autofs                 13700   0 (autoclean) (unused)
3c59x                  31312   1
iptable_filter          2412   0 (autoclean) (unused)
ip_tables              15864   1 [iptable_filter]
mousedev                5688   0 (unused)
keybdev                 2976   0 (unused)
hid                    22404   0 (unused)
input                   6240   0 [mousedev keybdev hid]
usb-ohci               22088   0 (unused)
usbcore                80512   1 [hid usb-ohci]
ext3                   72960   3
jbd                    56752   3 [ext3]
raid1                  16300   3

RTLinux Module Installation

scripts/insrtl calls insmod to install them:

insmod modules/rtl.o
insmod modules/rtl_time.o
if [ -f modules/rtl_posixio.o ]; then
	insmod modules/rtl_posixio.o
fi
insmod modules/rtl_fifo.o
insmod modules/rtl_sched.o
if [ -f modules/psc.o ]; then
	insmod modules/psc.o
fi

RTLinux Modules


You should only need to use the modules rtl and rtl_sched for your work in this course.


RTLlinux Examples: A Simple Periodic Task

See hello.c:

#include 
#include 
#include 
#include 

pthread_t thread;
hrtime_t start_nanosec;

void * start_routine(void *arg)
{
	struct sched_param p;
	hrtime_t elapsed_time,now;
	p . sched_priority = 1;
	pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);

	pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000);

	while (1) {
		pthread_wait_np ();
		now = clock_gethrtime(CLOCK_REALTIME);
		elapsed_time = now - start_nanosec;
		rtl_printf("elapsed_time = %Ld\n",(long long)elapsed_time);
	}
	return 0;
}

int init_module(void) {
	start_nanosec = clock_gethrtime(CLOCK_REALTIME);
	return pthread_create (&thread, NULL, start_routine, 0);
}

void cleanup_module(void) {
	pthread_delete_np (thread);
}

Contrast: A Simple Periodic Task in Ordinary Linux

#define _XOPEN_SOURCE 600
#define _XOPEN_SOURCE_EXTENDED
#define _POSIX_C_SOURCE 199506L
#define _REENTRANT
#include 
#include 
#include 
#include 
#include 
#include 

#define CHECK(CALL) if (CALL) { perror (#CALL); exit (-1); } 
#define SECOND_AS_NS 1000000000
#define HALF_SECOND_AS_NS 500000000 

pthread_t thread;
struct timespec start_time;
pthread_mutex_t M;
pthread_cond_t C;
volatile int going = 1;

void * start_routine(void *arg)
{
	struct timespec now, wakeup_time;
        unsigned long elapsed_time; 
       
        wakeup_time = start_time;
	while (going) {
                pthread_mutex_lock(&M);
		pthread_cond_timedwait (&C,&M,&wakeup_time);
                pthread_mutex_unlock(&M);
		if (clock_gettime(CLOCK_REALTIME, &now))
                  { perror ("clock_gettime"); break; };
		elapsed_time = now.tv_sec - start_time.tv_sec;
		elapsed_time = elapsed_time * SECOND_AS_NS +
                       (now.tv_nsec - start_time.tv_nsec);
		fprintf(stderr, "elapsed_time = %ld\n", elapsed_time);
                wakeup_time.tv_nsec += HALF_SECOND_AS_NS;
                if (wakeup_time.tv_nsec >= SECOND_AS_NS) {
                  wakeup_time.tv_nsec -= SECOND_AS_NS;
                  wakeup_time.tv_sec++;
                }
	}
	return 0;
}

int 
main () {
        pthread_attr_t attr;
        struct sched_param param;
        param.sched_priority = sched_get_priority_max(SCHED_FIFO);
        CHECK (pthread_attr_init (&attr));
        CHECK (pthread_attr_setschedpolicy (&attr, SCHED_FIFO));
        CHECK (pthread_attr_setschedparam (&attr, ¶m));
	CHECK (clock_gettime (CLOCK_REALTIME, &start_time));
        CHECK (pthread_mutex_init (&M, NULL));  
        CHECK (pthread_cond_init (&C, NULL));  
	CHECK (pthread_create (&thread, NULL, start_routine, 0));
        fprintf(stderr, "hit the the enter-key to terminate\n");
        getc(stdin);
        going = 0;
        CHECK (pthread_join (thread, NULL));
        return 0;
}

This is not RT Linux. It is just for comparison.


Bisection Benchmark Using Ordinary Linux Threads

See program bisection.c.

Recall that we discussed the breakdown load or breakdown utilization of a system in the notes on measuring execution time.

Observe that this program needs synchronization between the main program, which drives the bisection by increasing and decreasing the load, and the periodic task. The basic idea is to run the periodic task for a while at a given load level, and see whether it misses any deadlines. Then, the load level is adjusted up or down and the periodic task is allowed to run some more. This starting and stopping of the periodic task is done using a POSIX condition variables and a POSIX mutex. They are also used at the beginning, to make the task wait for the main program to tell it to go, and at the end, to synchronize the shutdown of the periodic task.

RT Linux provides its own features that are supposed to behave like POSIX condition variables and mutexes.


RT Linux Example Using a Mutex

See mutex.c.


We will walk through and discuss this in class.


RT Linux Example Using a Mutex & a CV

See condvar.c.


We will walk through and discuss this in class.

© 1998, 2003 T. P. Baker. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means without written permission.
$Id: rtlinux.html,v 1.1 2003/10/17 12:34:01 baker Exp baker $