File: index.html

package info (click to toggle)
rtlinux 3.1pre3-2
  • links: PTS
  • area: non-free
  • in suites: sarge, woody
  • size: 4,892 kB
  • ctags: 4,228
  • sloc: ansic: 26,204; sh: 2,069; makefile: 1,414; perl: 855; tcl: 489; asm: 380; cpp: 42
file content (501 lines) | stat: -rw-r--r-- 22,883 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

<!--Converted with LaTeX2HTML 2K.1beta (1.48)
original version by:  Nikos Drakos, CBLU, University of Leeds
* revised and updated by:  Marcus Hennecke, Ross Moore, Herb Swan
* with significant contributions from:
  Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
<HTML>
<HEAD>
<TITLE>FSMLabs Lean POSIX for RTLinux</TITLE>
<META NAME="description" CONTENT="FSMLabs Lean POSIX for RTLinux">
<META NAME="keywords" CONTENT="posix">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="LaTeX2HTML v2K.1beta">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">

<LINK REL="STYLESHEET" HREF="posix.css">

</HEAD>

<BODY bgcolor="white">
<!--Navigation Panel-->
<IMG WIDTH="81" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next_inactive"
 SRC="/usr/share/latex2html/icons/nx_grp_g.png"> 
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
 SRC="/usr/share/latex2html/icons/up_g.png"> 
<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
 SRC="/usr/share/latex2html/icons/prev_g.png">   
<BR>
<BR>
<BR>
<!--End of Navigation Panel-->

<H1 ALIGN="CENTER">FSMLabs Lean POSIX for RTLinux<IMG
 WIDTH="19" HEIGHT="20" ALIGN="BOTTOM" BORDER="0"
 SRC="img1.png"
 ALT="$^{\tt TM}$"></H1>
<P ALIGN="CENTER"><STRONG>Victor Yodaiken<A NAME="tex2html1"
  HREF="#foot44"><SUP>1</SUP></A>
<BR>
Finite State Machine Labs Inc.
<BR>	<FONT SIZE="-1">&#169;Finite State Machine Labs 1999,2000. 
	All rights reserved</FONT>
<BR></STRONG></P>

<P>

<H3>Abstract:</H3>
<DIV>
RTLinux is a small, fast operating system, following the POSIX 1003.13
"minimal realtime operating system" standard. The key design objective
of RTLinux is to produce a peaceful resolution to an apparently
insoluable contradiction: the need for simplicity and ``bare metal"
performance in a hard realtime operating system, and requirements for
all sorts of complex software, such as networking and graphical user
interfaces in modern realtime application code.  RTLinux was
originally released as a research project in 1995 and provided a
simple API that was quite succesful, but since 1999 RTLinux has been
tranforming into an an industrial strength version based on a POSIX
threads API.  In this article, I'll discuss what's important about
``hard realtime", how RTLinux works, ``why POSIX" and how we
reconciled RTLinux with a standard while keeping it small and
efficient.
</DIV>
<P>

<P>

<H1><A NAME="SECTION00010000000000000000">
Introduction: RTLinux, realtime and POSIX</A>
</H1>

<P>
RTLinux is a <EM>hard realtime</EM> operating system. That is, RTLinux is
designed to support applications that have real, serious,
non-negotiable deadlines. A rocket engine emergency shutdown sequence
must complete before the rocket explodes; a servo motor controller
must send commands exactly when the motor is in position; a video
editing system must capture the next frame and not permit it to be
overwritten; a data acquisition system can't miss any samples.  All
these systems are hard realtime systems and for these systems <EM>worst case timing</EM> is critical.  In non-realtime applications <EM>average</EM> or <EM>typical</EM> times are more important.  If a file system
averages 100Mbytes/second in data transfer, we don't care if it stops
now and then to shuffle buffers. Similarly, if a word processor is
delayed a few milliseconds, nobody will notice, if X-windows runs fast
almost all the time, a hitch now and then is no problem.  It's even
reasonable to allow a consumer video player to drop frames now and
then or to live with an occasional pop or drop-out in a soft CD
player.  Systems that are realtime, but where missing a deadline now
and then is acceptable are called <EM>soft</EM> realtime systems.  But
<EM>usually</EM> shutting down the rocket before it explodes or <EM>often</EM> putting a chip on an automated assembly line into the right
socket is not good enough.  A delay of a few microseconds can cause a
servo-motor to get a degree out of position and you can't compensate
for being too late once or twice by being early a few times.

<P>
Twenty years ago, applications needing hard realtime were simple and
were usually placed on dedicated, custom, isolated hardware. Modern
realtime applications must control systems such as factory floors
connected to supply databases, telescopes connected to the Internet,
cell phones generating graphical displays, routers, and telephone
switches.  These applications run platforms that have non-realtime
responsibilities as well as realtime ones, must work on commodity
hardware, and need to be networked. In other words, these applications
are not simple and do not run on dedicated, custom, or isolated
hardware.  Furthermore, as speed and quality requirements increase,
applications that were not realtime, change into hard realtime
applications.  For example, serious use of networked video and audio
requires software that can maintain streams of data with hard realtime
guarantees. As another example, variations in network transmit times
for loosely coupled stand-alone servers on relatively slow networks
has not been a problem, but a server cluster on 10G ethernet in which
there are tightly connected distributed applications is a very
different situation and one where real-time networking capabilities
become an issue.

<P>
The problem here is that to deliver the tight worst case timing
performance needed for hard realtime, operating systems need to be
simple, small, predictable - and optimized to minimize worst case
performace. But sophisticated services and powerful applications run
best on complex operating systems that are optimized to deliver strong
average case performance. TCP network stacks, for example, use
algorithms that trade latency for throughput. Software that tries to
optimize for two contradictory goals will deliver neither.  In fact,
the Mars Lander, running VxWorks had precisely this problem as a
standard non-realtime inter-process communication mechanism caused a
critical realtime process to hang up and time out. RTLinux offers an
alternative to the traditional choices of ``make a general purpose
operating system kind-of-realtime" (IRIX) and ``keep adding
nonrealtime features to a realtime operating system" (VxWorks).

<P>
Instead of trying to attempting to balance worst case time against
average case time, RTLinux decouples the realtime and non-realtime
systems. We put realtime components in a single, multithreaded,
realtime process running on a bare machine.  Applications are threads
and signal handlers.  This realtime process is simple, fast,
predictable and optimized to minimize worst case performance. A
general purpose operating system is run as the lowest priority
thread. In RTLinux this thread is Linux.  A patented "virtual
interrupt controller" prevents the low priority thread from blocking
interrupts aimed at realtime signal handlers.  Communication between
realtime components and the general purpose OS thread is designed to
mimimize interference -- the realtime components are never forced to
wait for operations of the non-realtime thread. But communication
mechanisms are designed to help programmers move all the non-realtime
functionality into the non-realtime environment.

<P>
A realtime application may consist of a periodic thread running in the
base realtime process and collaborating with control software running
under Linux and making use of, for example, an Oracle database, the
KDE desktop environment, and a Perl networking script. Linux and its
processes can never block the realtime process scheduling or event
handling and the realtime process does not need to offer virtual
memory or a journaling file system or a TCP stack as these are all
available within Linux.  The classic RTLinux application consists of a
periodic thread collecting data from an A/D device and driving an D/A
output, with data flowing to a Linux process that logs results and
commands comming from a Linux process that presents the operator with
buttons and a display.  Of course, the challenge with this model is to
make sure that hardware efficiency does not come at the expense of
programmer efficiency and this brings us to the API.

<P>

<H1><A NAME="SECTION00020000000000000000">
API development</A>
</H1>

<P>
The first widely used version of RTLinux was released in 1995. This
"V1" system was intended to run on low end x86 based computers and
provided a spartan API and programming environment.  Faster machines
(and more complex applications), multiprocessing, multiple
architectures, and a much larger programmer community exposed
limitations of the original API. We realized that repairing and
extending our simple API would transform it into a mess.  We also
realized that with over 100 commercial RTOS's in the market, the world
was not exactly crying out for another new RTOS API. POSIX offered
several advantages: POSIX is a real standard, not an effort to lock
customers into a proprietary API; and POSIX is widely known and well
documented. But POSIX seemed inherently slow because it incorporated
too many operations that were impossible to provide in our lean
programming environment. For example, consider how very far from fast,
simple, predictable, and efficient it is to parse a POSIX file name
though links, hardlinks, mounted file systems, and layers of
directories. Fortunately, we discovered that the POSIX 1003.13
standard was the solution we needed.

<P>
POSIX 1003.13 provides a beautiful<A NAME="tex2html2"
  HREF="#foot57"><SUP>2</SUP></A> model for fitting RTLinux tasks and interrupt
handlers into the POSIX world.  The POSIX standard identifies, in
section 6, a "Minimal Realtime System Profile" (PSE51) intended for
hard realtime systems like RTLinux.  The 1003.13 ``minimal realtime
system" application environment consists of a single, multithreaded
POSIX process running on a bare machine.  In this model, RTLinux tasks
became POSIX threads and RTLinux interrupt handlers became signal
handlers. Linux runs as the lowest priority thread.  In an SMP or
other multi-processor system we decided to provide a single realtime
process on each processor.

<P>
The "rationale" given in the standards document is that "the POSIX.1c
Threads model (with all options enabled, but without a file system)
best reflected current industry practice in certain embedded realtime
areas. Instead of full file system support, basic device I/O (read,
write, open, close, control) is considered sufficient for kernels of
this size.  Systems of this size frequently do not include process
isolation hardware or software; therefore, multiple processes (as
opposed to threads) may not be supported."

<P>
POSIX 1003.13 escapes from the POSIX file system by providing a
bare-bones interpretation of file path names.  The standard RTLinux
<TT>open</TT> will open <TT>/dev/x</TT> for a fixed set of devices and will
not support any other path names.

<P>
That's not to say that the Pthreads API is perfect. For example, the
Pthreads API has quite clumsy handling of periodic threads, the entire
cancel system is terrible, and signals are sometimes confusing. But
the API is usable and can be made better by the addition of some POSIX
compatible extensions.

<P>
In the next section, I will explain how a RTLinux program can be
constructed using the POSIX API.  But it's worth noting that there is
an alternative high level interface to RTLinux from Linux user code
via an added Linux system call. The call, <TT>rtlinux_sigaction</TT>
designates some function in the user program as a signal hander to be
run in realtime mode either periodically or in response to some
interrupt (as a user interrrupt handler).  The signal handler code
runs in the address space of the process so, with appropriate use of
data structures, data can be shared between the non-realtime main
process and the realtime handlers. The <TT>rtlinux_sigaction</TT>
interface provides a method for writing realtime code within Linux
processes. This method is exceptionally simple to use, but is less
flexible than the RTLinux pthreads API and suffers a (couple of
microsecond) performance penalty.  For more details, see the section
on the Programmable Signal Control (PSC) modules in the RTLinux
documentation.

<P>

<H1><A NAME="SECTION00030000000000000000">
An example</A>
</H1>

<P>
RTLinux makes use of the Linux kernel module facility to load realtime
components.  Linux boots up in non-realtime mode. To switch over to
realtime operation, we insert a collection of kernel modules providing
RTLinux functionality.  The modules have been designed so that users
can select a minimal subset that supports their applications. RTLinux
is provided with a command <TT>insrtl</TT> to load the full set of
modules, but the modules are designed so that users can pick a minimal
set that provides only the services they need. The RTLinux modules
include <TT>rtl</TT> (basic services), <TT>rtl_timer</TT> (to control
hardware clocks), <TT>rtl_sched</TT> (the scheduler) and <TT>rtl_posixio</TT> (a read/write/open layer for drivers. Once the RTLinux
modules are loaded, RTLinux applications can be loaded. The standard
Linux GDB debugger can be used to debug RTLinux threads. It's also
possible to use the RTLinux system purely from user mode via a
realtime signal handler facility.

<P>

<H2><A NAME="SECTION00031000000000000000">
RTL Threads</A>
</H2>
In order for the realtime system to be able to use Linux, we provide
three three standard interfaces between realtime tasks and Linux. The
first is a device interface called <TT>RTfifos</TT> (illustrated below),r
the second is shared memory, and the third uses the pthread signal
mechanism to allow realtime threads to generate soft interrupts for
Linux.  A simple A/D application might consist of a single periodic
thread that collects data from a A/D device every 500 microseconds and
dumps the data down a fifo for Linux to log or otherwise process.

<P>
A thread function returns an untyped pointer (in "C" a <TT>void</TT>
pointer can point to any type of data structure), and takes a single
argument that is also an untyped pointer. In our case, we don't need
either. The code below declares a POSIX <TT>timespec</TT> to specify its
period, and a structure <TT>D</TT> which will hold data from the A/D
device. The thread calls the POSIX <TT>clock_gettime</TT> to read the
current time from the RTL scheduling clock into the timespec
structure. Each cycle, the thread collects data from the A/D device,
writes the data down a fifo to a Linux process, adds its period in
nano-seconds to the timespec structure and calls the POSIX <TT>clock_nanosleep</TT> to sleep until that time.

<P>
<PRE>
void *my_code(void *arg){ // argument is not used in this example.
     struct timespec t;
     struct mydata D;
     clock_gettime(CLOCK_RTL_SCHED,&amp;t);
     while(!stop){
          copy_device_data(&amp;D.d);
          /* ignore write fails, we just drop the data */
          write(fd,&amp;D,sizeof(D));
          timespec_add_ns(&amp;t,DELAY_NS);
          clock_nanosleep(CLOCK_RTL_SCHED, 
                          TIMER_ABSTIME, 
                          &amp;t, 
                          NULL);
     }
     return (void *)&amp;stop;
}
</PRE>

<P>
This code is placed inside an ordinary Linux kernel module which has
the format:

<P>
<PRE>
INCLUDES 
GLOBAL VARIABLES AND DEFINITIONS
INITIALIZE CODE
CLEANUP CODE
REALTIME THREAD CODE
</PRE>

<P>
The <TT>init_module</TT> code for our example will create "fifo" to send
data to the user process and then create the thread. The <TT>cleanup_module</TT> asks the thread to shut down, waits for it, and then
closes the fifo.

<P>
<PRE>
pthread_t T;
int fd;
int stop = 0;
#define DELAY_NS 500000 // 500 microseconds

int init_module(void){
     if ((fd=open("/dev/rtf0", 
                   O_WRONLY | 
                   O_NONBLOCK | 
                   O_CREAT )) 
         &lt; 0)
     {
          rtl_printf("Example cannot open fifo\n");
          rtl_printf("Error number is %d\n",errno);
          return -1;
     }
     if( pthread_create(&amp;T,NULL,my_code,NULL))
     {
          close(fd);
          rtl_printf("Cannot create thread\n");
          return -1;
     }
     return 0;
}

void cleanup_module(void){ 
     stop = 1;
     pthread_join(T,NULL);
     close(fd);
}
</PRE>

<P>
If you just wanted to log the data produced by this code, the Linux
shell command <TT>cat &lt; /dev/rtf0 &gt; logfile</TT> would do the trick. A two
line <TT>awk</TT> script could convert the data into a format where it could
be displayed by <TT>gplot</TT>. Alternatively, a simply <TT>C</TT> program could
take the data and do some analysis, or a <TT>Perl</TT> script could send the
data over a network.  By adding a second fifo, we could have the user
interface control the period or other properties of the sampling program.
The RTLinux front end <TT>RTiC Lab</TT> automates much of this.

<P>
Full working code can be found at

		<A NAME="tex2html3"
  HREF="http://www.rtlinux.com/RTLinuxExamples"><TT>http://www.rtlinux.com/RTLinuxExamples</TT></A>

.

<P>

<H1><A NAME="SECTION00040000000000000000">
Discussion</A>
</H1>

<P>
On a standard x86 PC RTLinux interrupt latencies are 
20 microseconds, worst case. On hardware with better timers and interrupt
handlers we do much better. For example, the AMD Elan520 a 133MHz processor
shows worst case interrupt latencies of under 7microseconds and on the 
Motorola M8260 worst case seems to be no more than 4 microseconds. Of course,
PC architecture is not created with realtime in mind and badly behaved hardware
will cause long delays. For example, some low-end video cards will hold the
PCI bus for millisecond intervals if their internal fifos are filled! 
But, with sensible hardware choices, RTLinux pushes the 
boundaries of interrupt response down to a level where commodity
microprocessors can replace special purpose devices. 

<P>
One design principle that 6 years of development has validated
is our principle that anything that can go into the general purpose
operating system <EM>should</EM> go into the general purpose operating 
system. Realtime applications should be ruthlessly separated into the
part that must be realtime and the part that does not have hard time 
constraints. This is a design constraint that conflicts with the
programming model in IRIX, VxWorks, and other traditional ``realtime"
operating systems and it requires an adjustment on the part of the 
programmer.  But our decoupled design is at the heart of why RTLinux
is reliable and fast. We require programmers to identify what sections
of their code is realtime and our operating system takes advantage of 
that information. In practice, with tens of thousands of applications, this
seems to be a natural way to design modular applications. There are
some difficulties porting legacy code, but the user mode RTLinux signal
capability reduces this difficulty. In fact, ordinary Linux, provides
better realtime performance than many ``realtime" operating systems and
we have found that turning a non-Linux realtime application into a
multithreaded Linux application with RTLinux signal handlers is reasonably
simple. 

<P>
Since RTLinux was introduced, a number of ``real time"
Linuxes have been 
developed and marketed and advocates for those approaches often claim to 
be escaping from the rigors our our decoupled model. 
Lineo provides a system called RTAI which started
as a variant of RTLinux and has since grown considerably. MontaVista
is attempting to introduce some techniques from the IRIX Operating System
into Linux with a ``fully preemptable kernel". There is, however,
no reason to suppose that re-creating
VxWorks in Linux (Lineo) or re-creating IRIX in Linux (MontaVista) will
produce improvements on the originals. The open-source development model,
however, means that good work will enter the mainstreams of code development.
There are several companies and researchers working on making Linux itself
lower latency and this will extend the range of RTLinux applications where
a soft realtime Linux component can be connected to hard realtime RTLinux
threads. And RTAI, whose main developer is an independent University 
researcher, is free to experiment with APIs. The RTLinux user mode
realtime signals were developed after a far more ambitious mechanism in RTAI
proved to be useful. It's more important for us to retain a POSIX compatible
and small API, so RTLinux is much more conservative about adding new features
and much more likely to push new functionality into the existing framework.

<P>
As an example of how new functionality can be accomodated within the POSIX
framework consider RTLinux/SMP. POSIX does not substantially
address the issue of multiple processors. In RTLinux, each processor
of a SMP system runs its own copy of the RTLinux realtime process (sharing
minimal data). Allocation of threads and signal handlers to processors is 
completeley determined by the application. RTLinux adds a processor
identifier to the POSIX <TT>thread attribute</TT> and when a thread is created
the application can assign it to a processor. 
Efficient cross-processor control is a
difficult problem and we were reluctant to introduce hidden synchronzation
points or operations that would cause significant cache disruption -- e.g
by migrating  tasks between processors. By sending a <TT>suspend</TT>
signal to the general purpose OS thread on a particular processor, it is
possible to dedicate that processor to RTLinux. When the Linux thread on 
the target processor receives the signal, it will run an idle loop. As a 
result, the realtime applications on that processor can generally run within
the processor cache: greatly reducing latency. All this is done with no
additions to the POSIX threads API.

<P>

<H1><A NAME="SECTION00050000000000000000">
About this document ...</A>
</H1>
 Copyright: 2001 FSM Labs, Inc.
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot44">... Yodaiken</A><A NAME="foot44"
 HREF="posix.html#tex2html1"><SUP>1</SUP></A>
<DD>yodaiken@fsmlabs.com

<DT><A NAME="foot57">... beautiful</A><A NAME="foot57"
 HREF="posix.html#tex2html2"><SUP>2</SUP></A>
<DD>A word not usually
associated with POSIX

</DL><HR>
<!--Navigation Panel-->
<IMG WIDTH="81" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next_inactive"
 SRC="/usr/share/latex2html/icons/nx_grp_g.png"> 
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
 SRC="/usr/share/latex2html/icons/up_g.png"> 
<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
 SRC="/usr/share/latex2html/icons/prev_g.png">   
<BR>
<!--End of Navigation Panel-->
<ADDRESS>
Michael Barabanov
2001-06-19
</ADDRESS>
</BODY>
</HTML>