RTLinux
RTLinux
S_STI :
sti
pushfl
pushl $KERNEL_CS
pushl $1f
S_IRET
1:
Interrupt Emulation (Contd.)
S_IRET:
push %ds
pushl %eax
pushl %edx
movl $KERNEL_DS, %edx
mov %dx, %ds
Interrupt Emulation (Contd.)
cli
movl SFREQ, %edx
andl SFMASK, %edx
bsfl %edx, %eax
jz 1f
S_CLI
sti
jmp SFIDT (,%eax,4)
Interrupt Emulation (Contd.)
1:
movl $1, SFIF
popl %edx
popl %eax
popl %ds
iret
RT Linux – Tasks
Initial Design – Each RT task executed in its
own address space.
High overhead of context switching as TLB
had to be invalidated.
High overhead of system calls.
Now all RT tasks run in the same address
space (in the kernel space) and at the highest
privilege level.
But highly error prone as a bug in a single
application can wipe out entire system.
RT Linux – Tasks (Contd.)
RT tasks run as kernel modules. Can be
dynamically added.
Tasks have integer context for faster context
switching (unless FP context is explicitly
requested).
Hardware context switching provided by x86
is not used.
Task resources should be statically allocated
(kmalloc etc. should not be used within an RT
task).
RT Linux - Scheduling
RT Linux is module based – the
scheduler is itself a loadable kernel
module.
Default – A simple preemptive priority
based scheduler where the tasks are
statically assigned priorities. The
highest priority task ready to run is
scheduled.
RT Linux – Scheduling
(Contd.)
Alternate scheduling policies
Earliest Deadline First (EDF) – A dynamic
priority scheduler in which the task with
the nearest deadline is scheduled.
Rate Monotonic (RM) – A static priority
scheduler for periodic tasks where the task
with the smallest period is assigned the
highest priority. This is provably the
optimal policy.
RT Linux – Timing
Tradeoff between amount of time spent in
handling clock interrupts with task release
jitter (the difference between the exact time
when the task should have been scheduled
and the time at which it is actually
scheduled).
So we program the timer chip to interrupt the
CPU exactly when the next event has to be
scheduled (one-shot mode).
RT Linux – Timing (Contd.)
Global time is kept track of by summing up all
intervals between interrupts.
Time Stamp Counter (TSC) available on
Pentiums can also aid in the process.
Conventional 10ms interrupts are simulated
for Linux.
Normal periodic timer mode is also supported
to avoid the overhead of reprogramming the
clock every time.
Inter-Process Communication
(IPC)
Linux kernel may be preempted by an RT task
even during a system call, so no Linux routine
can be safely called from real-time tasks.
RT fifos used for communication between RT
tasks and Linux user processes.
RT fifo buffers are allocated in kernel address
space.
IPC (Contd.)
RT fifos export lock-free functions for reading
and writing on RT side and a standard device
interface on the user side.
Static limit on the number of fifos.
Fifos should be used unidirectionally. A pair
can be used for bidirectional transfer.
A handler can be associated with a fifo which
is called when Linux task accesses it.
IPC using shared memory also available.
Using Shared Memory
mbuff module and /dev/mbuff device can be
used for shared memory.
Linux tasks can map memory, allocated in the
kernel using vmalloc(), to their address
space.
The allocated memory is logically (but not
physically) contiguous.
Cannot be swapped out, so is suited for
communication between real time tasks and
user space.
RT Fifo vs. Shared Memory
Queue data, no protocol No queuing of data.
needed to prevent Need to follow explicit
overwrites. protocol
Message boundaries not Can write structured
maintained. data into memory.
Support blocking for Need to poll for
synchronization, no synchronization.
polling required.
Fifos are point-to-point Can have any number
channels. of tasks sharing
memory.
Maximum number of Physical memory is the
fifos statically defined. only limit.
Design of applications using
RT Linux
It is envisaged that applications will
consist of two parts.
The Real Time part should be fast,
simple and small.
Other part will run in user space and
should take care of I/O etc.
User task will communicate with real
time task via real time fifos.
Structure of RT Application
RT Fifo
User Process
RT Fifo
int init_module(void) {
return pthread_create(&thread, NULL,
start_routine, 0);
}
int cleanup_module(void) {
pthread_delete(thread);
}
Hello World (contd…)
void * start_routine(void *arg) {
struct sched_param p;
p.sched_priority = 1;
pthread_setschedparam(pthread_self(),
SCHED_FIFO, &p);
pthread_make_periodic_np(pthread_self(),
gethrtime(), 500000000);
while (1) {
pthread_wait_np();
rtl_printf(“Hello World !\n”);
}
return 0;
}
Using Interrupts
There are two types of interrupts : Hard and
Soft.
Hard interrupts are the actual device
interrupts and have less latency.
First RT handler (if any) is called and if it
permits sharing, the interrupt is passed on to
Linux.
Very limited set of kernel functions can be
called from them.
Soft Interrupts
Soft interrupts are at par with normal Linux
interrupts.
They don’t provide real time performance.
Kernel functions may be called from them.
Can be delayed for considerable periods of
time.
Serviced when system switches back to Linux.
Used in implementation of RT fifos.
Writing Interrupts Driven
Threads
A specific IRQ can be requested with
rtl_request_irq(irq, handler, regs).
An IRQ can be released using rtl_free_irq(irq)
The “handler” executes with hardware
interrupts disabled.
If it is necessary to receive further interrupts,
re-enabling is done with
rtl_hard_enable_irq(irq).
Interrupt Driven Threads
(contd…)
An interrupt driven thread is created as
usual by calling pthread_create().
The thread calls pthread_suspend_np()
and blocks.
It is assumed that the interrupt handler
will call pthread_wakeup_np() to wakup
this thread.
Using Floating Point
Operations
By default RTL threads cannot use
floating-point operations.
This is because RTL threads have an
integer context only.
This has been done to facilitate fast
context switches because switching FP
context takes some time.
FP operations (contd…)
To change default status of floating
point operations the following function
needs to be called:
pthread_setfp_np(thread,flag)
To enable use flag set to 1, to disable
set flag to 0.
FP context is switched only if the new
thread requires it.
Providing Mutual Exclusion
RT Linux supports the POSIX style
pthread_mutex_ family of functions.
Internal implementation of lock and
unlock uses spin-locks.
Currently there is no support for
handling problems such as Priority
Inversion, deadlocks etc.
Conclusion
RT Linux has achieved hard real-time
performance by making minimal changes to a
freely available Operating System.
Provides an alternative to proprietary real-
time systems which may be prohibitively
expensive.
As Linux develops, RT Linux will also ride the
wave of its development.
Unlike other RT systems, no separate support
for RT Linux is needed since support for Linux
is already widely available.