RTS Programming Language

Download as pdf or txt
Download as pdf or txt
You are on page 1of 24

PROGRAMMING LANGUAGES

FOR REAL - TIME SYSTEMS


Fitness of a Programming Language for Real -
Time Applications
• C1. Economy of Execution: (How fast ?)
• C2. Economy of Compilation: (single or multiple file)
• C3. Economy of Small - Scale Development: How hard to design?
• C4. Economy of Large - Scale Development: How hard for a team of
programmers?
• C5. Economy of Language Features: How hard to learn and
programming language?
Coding Standards for Real - Time Software
• Header format
• Frequency, length, and style of comments
• Naming of classes, data, files, methods, procedures, variables, and so
forth
• Formatting of program source code, including use of white space and
indentation
• Size limitations on code units, including maximum and minimum
number of code lines, and number of methods used
• Rules about the choice of language construct to be used; for example,
when to use case statements instead of nested if-then-else
statements.
ASSEMBLY LANGUAGE
• It does have a particular advantage for use in real - time programming; it provides the most direct control of the
computer hardware over high - level languages.
• This advantage has extended the use of assembly language in real - time systems, despite the fact that assembly
language is unstructured and has very limited abstraction properties.
• Coding in assembly language is, in general, time - consuming to learn, tedious, and error prone.
• Finally, the resulting code is not easily ported across different processors, and hence the use of assembly language in
embedded real - time systems — or in any professional system — is to be discouraged.
• But with significant improvements in optimizing compilers, the compiler should be able to generate very efficient
machine - language code in terms of execution speed and memory usage.
• Furthermore, you will find assembly - language code in many legacy real – time applications, and even today you can
still occasionally encounter situations where small portions of a real - time system need to be written using assembly
language.
• Assembly languages, however, have poor economies of small - and large - scale development and of language
features. Hence, assembly language programming should be limited to use in very tight timing situations or in
controlling hardware features that are not supported by the compiler.
Continuing role of assembly language
• For certain kinds of code, such as interrupt handlers and for device drivers for unique hardware
where the “ intellectual distance ” between the hardware and software needs to be minimized.
• For situations where predictable performance for the code is extremely difficult or impossible to
obtain because of undesirable programming - language – compiler interactions.
• For effectively using all architectural features of a CPU, for instance, parallel adders and multipliers.
• For writing code with minimum execution time achievable for time – critical applications, such as
sophisticated signal - processing algorithms with high sampling rates.
• For writing the entire software for custom - designed CPUs with a small instruction set (see Section
2.5.3 ) — if no high - level language support is available.
• For debugging hard problems below the level of high - level language code and tracing the stream
of fetched instructions by a logic analyser.
• For teaching and learning computer architectures and internal operation of processors.
PROCEDURAL LANGUAGES FEATURES
• Modularity
• Strong typing
• Abstract data typing
• Versatile parameter passing mechanisms
• Dynamic memory allocation facilities
• Exception handling

Ex- Ada, C, Fortran, and Visual Basic


PROCEDURAL LANGUAGES FEATURES
• Procedural languages that are amenable to the principle of information hiding tend to promote the construction of high - integrity real -
time systems.
• While C and Fortran both have mechanisms that can support information hiding (procedures and subroutines), other languages, such as
Ada, tend to foster more modular design because of the requirement to have clearly defi ned inputs and outputs in the module
parameter lists.
• In Ada, the notion of a package embodies the concept of Parnas information hiding (Parnas, 1972 ) exquisitely. The Ada package consists
of a specification and declarations that include its public or visible interface and its private or invisible elements. In addition, the package
body, which has more externally invisible components, contains the working code of the package. Individual packages are separately
compilable entities, which further enhances their application as black boxes. Furthermore, the C language provides for separately
compiled modules and other features that promote a rigorous top – down design approach, which should lead to a solid modular design.
• While modular software is desirable for many reasons, there is a price to pay in the overhead associated with procedure calls and
essential parameter passing. This adverse effect should be considered carefully when sizing modules.
• Typed languages require that each variable and constant be of a specific type and that each be declared as such before use.
• Strongly typed languages prohibit the mixing of different types in operations and assignments, and thus force the programmer to be
exact about the way data are to be handled.
• Precise typing can prevent corruption of data through unwanted or unnecessary type conversion. Moreover, compiler type - checking is
an important step to find errors at compile time, rather than at runtime, when they are more costly to repair. Hence, strongly typed
languages are truly desirable for real - time systems.
• Generally, high - level languages provide integer and real types, along with Boolean, character, and string types. In some cases, abstract
data types are supported, too. These allow programmers to defi ne their own types along with the associated operations. Use of abstract
data types, however, may incur an execution - time penalty, as complicated internal representations are often needed to support the
abstraction.
• Some languages are typed, but do not prohibit mixing of types in arithmetic operations. Since these languages generally perform mixed
calculations using the type that has the highest storage complexity, they must promote all variables to that highest type.
Parameter Passing and Dynamic Memory
Allocation
• call - by - value
• call - by - reference
Cardelli ’ s Metrics and Procedural Languages
• Use variable in procedural language makes the compiler more efficient.
• Further, because modules can be compiled independently, compilation of
large systems is efficient, at least when interfaces are stable
• In small - scale development makes testing ease and less debugging efforts.
• Finally, experienced programmers usually adopt a coding style that causes
some logical errors to show up as type checking errors; hence, they can use
the type checker as a development tool. For instance, changing the name of a
type when its invariants change even though the type structure remains the
same yields error reports on all its previous uses.
• Dependencies between such pieces of code are minimized, and code can be
locally rearranged without any fear of global effects.
• Finally, procedural languages are economical because certain well – designed
constructions can be naturally composed in orthogonal ways.
Metrics and Object - Oriented Languages
• In terms of economy of execution, object -oriented style is intrinsically less efficient than procedural style. In pure object -oriented style,
every routine is supposed to be a method. This introduces additional indirections through method tables and prevents straightforward
code optimizations, such as inlining. The traditional solution to this problem (analyzing and compiling whole programs) violates
modularity and is not applicable to libraries.
• With respect to economy of compilation, often there is no distinction between the code and the interface of a class. Some object -
oriented languages are not sufficiently modular and require recompilation of super classes when compiling subclasses. Hence, the time
spent in compilation may grow disproportionately with the size of the system.
• On the other hand, object - oriented languages are superior with respect to economy of small - scale development. For example,
individual programmers can take advantage of class libraries and frameworks, drastically reducing their workload. When the project
scope grows, however, programmers must be able to understand the details of those class libraries, and this task turns out to be more
difficult than understanding typical module libraries. The type systems of most object - oriented languages are not expressive enough;
programmers must often resort to dynamic checking or to unsafe features, damaging the robustness of their programs.
• In terms of economy of large - scale development, many developers are frequently involved in developing new class libraries and
tailoring existing ones. Although reuse is a benefit of object - oriented languages, it is also the case that these languages have extremely
poor modularity properties with respect to class extension and modification via inheritance. For instance, it is easy to override a method
that should not be overridden, or to reimplement a class in a way that causes problems in subclasses. Other large - scale development
problems include the confusion between classes and object types, which limits the construction of abstractions, and the fact that subtype
polymorphism is not good enough for expressing container classes.
• Object - oriented languages have low economy of language features. For instance, C ++ is based on a fairly simple model, but is
overwhelming in the complexity of its many features. Unfortunately, what started as economical and uniform language ( “ everything is
an object ” ) ended up as a vast collection of class varieties. Java, on the other hand, represents a step toward reducing complexity, but is
actually more complex than most people realize.
OBJECT - ORIENTED LANGUAGES
• The benefits of object - oriented languages, such as improved programmer productivity, increased software
reliability, and higher potential for code reuse, are well known and appreciated.
• Object - oriented languages include Ada, C ++ , C#, and Java. Formally, object - oriented programming languages are
those that support data abstraction , inheritance , polymorphism , and messaging .
• Objects are an effective way to manage the increasing complexity of real - time systems, as they provide a natural
environment for information hiding, or protected variation and encapsulation. In encapsulation, a class of objects
and methods associated with them are enclosed or encapsulated in class definitions.
• An object can utilize another object ’ s encapsulated data only by sending a message to that object with the name of
the method to apply. For example, consider the problem of sorting objects.
• Object - oriented languages provide a fruitful environment for information hiding; for instance, in image - processing
systems, it might be useful to define a class of type pixel, with attributes describing its position, color, and
brightness, and operations that can be applied to a pixel, such as add, activate, and deactivate.
Synchronizing Objects and Garbage
Collection
• Synchronized Objects . A synchronization object, such as a mutex, is associated with an object that can be
concurrently accessed by multiple threads. If internal locking is used, then on method entry, each public method
acquires a lock on the associated synchronization object and releases the lock on method exit. If external locking is
used, then clients are responsible for acquiring a lock on the associated synchronization object before accessing the
object and subsequently releasing the lock when finished.
• Encapsulated Objects . When an object is encapsulated within another object (i.e., the encapsulated object is not
accessible outside of the enclosing object), it is redundant to acquire a lock on the encapsulated object, since the
lock of the enclosing object also protects the encapsulated object. Operations on encapsulated objects therefore
require no synchronization.
• Thread - Local Objects . Objects that are only accessed by a single thread require no synchronization.
• Objects Migrating between Threads . In this policy, ownership of a migrating object is transferred between threads.
When a thread transfers ownership of a migrating object, it can no longer access it. When a thread receives
ownership of a migrating object, it is guaranteed to have exclusive access to it (i.e., the migrating object is local to
the thread). Hence, migrating objects require no synchronization. However, the transfer of ownership does require
synchronization.
• Immutable Objects . An immutable object ’ s state can never be modified after it is instantiated. Thus, immutable
objects require no synchronization when accessed by multiple threads since all accesses are read - only.
Object - Oriented versus Procedural Languages
• There is no such rules/differences that whether Oops Language or procedural language boundary to be used in Real-Time Systems.
• This is partially due to the fact that there is a huge variety of real - time applications — from nonembedded airline booking and
reservation systems to embedded wireless sensors in running shoes, for example.
• The benefits of an object - oriented approach to problem solving and the use of object - oriented languages are clear.
• Moreover, it is possible to imagine certain aspects of a real - time operating system that would benefit from objectification, such as
process, thread, file, or device. Furthermore, certain application domains can clearly benefit from an object - oriented approach. The
main arguments against object - oriented programming languages for real - time systems, however, are that they can lead to
unpredictable and ineffi cient systems, and that they are hard to optimize.
• Nonetheless, we can confidently recommend object - oriented languages for soft and fi rm real - time systems.
• The unpredictability argument is hard to defend, however, at least with respect to object - oriented languages, such as C ++ , that do not
use garbage collection. It is likely the case that a predictable system — also a hard real – time one — can be just as easily built in C ++ as
C. Similarly, it is probably just as easy to build an unpredictable system in C as in C ++ . The case for more unpredictable systems using
object - oriented languages is easier to sustain when arguing about garbage - collecting languages like Java.
• In any case, the inefficiency argument against object - oriented languages is a powerful one. Generally, there is an execution - time
penalty in object -oriented languages in comparison with procedural languages. This penalty is due in part to late binding (resolution of
memory locations at runtime rather than at compile time) necessitated by function polymorphism, inheritance, and composition. These
effects present considerable and often uncertain delay factors. Another problem results from the overhead of the garbage collection
routines. One way to reduce these penalties is not to defi ne too many classes and only defi ne classes that contain coarse detail and high
– level functionality.
ASSEMBLY LANGUAGE
• assembly language does have a particular advantage for use in real - time programming; it provides the most direct
control of the computer hardware over high - level languages.
• This advantage has extended the use of assembly language in real - time systems, despite the fact that assembly
language is unstructured and has very limited abstraction properties.
• Coding in assembly language is, in general, time - consuming to learn, tedious, and error prone.
• Finally, the resulting code is not easily ported across different processors, and hence the use of assembly language in
embedded real - time systems — or in any professional system — is to be discouraged.
• But with significant improvements in optimizing compilers, the compiler should be able to generate very efficient
machine - language code in terms of execution speed and memory usage.
• Furthermore, you will find assembly - language code in many legacy real – time applications, and even today you can
still occasionally encounter situations where small portions of a real - time system need to be written using assembly
language.
• Assembly languages, however, have poor economies of small - and large - scale development and of language
features. Hence, assembly language programming should be limited to use in very tight timing situations or in
controlling hardware features that are not supported by the compiler
Ada
• Ada was first introduced DoD, USA and in 1983 it was standardized. Ada was intended to be used specifically for programming real - time systems, but, it is found the
resulting executable code to be bulky and inefficient.
• Major problems exists when implemented for multitasking which fails. Ada 83 is renovated to newer version Ada 95 is considered the first internationally standardized object
- oriented programming language. Three particularly useful constructs were introduced in Ada 95 to resolve shortcomings of Ada 83 in scheduling, resource contention, and
synchronization:
• A pragma that controls how tasks are dispatched.
• A pragma that controls the interaction between task scheduling.
• A pragma that controls the queuing policy of task - and resource – entry queues.

• Moreover, other additions to the language strived to make Ada 95 fully object -oriented. These included:
• Tagged types
• Packages
• Protected units

• Proper use of these constructs allows for the construction of objects that exhibit the four characteristics of object - oriented languages.
• In October 2001, a Technical Corrigendum to the Ada 95 Standard was announced by ISO/IEC, and a major Amendment to the international standard was published in March
2007. This latest version of Ada is called “ Ada 2005. ” The differences between Ada 95 and Ada 2005 are not extensive — in any case, includes a few changes that are of
particular interest to the real - time systems community, such as:
• The real - time systems Annex contains additional dispatching policies, support for timing events, and support for control of CPU - time utilization.
• The object - oriented model was improved to provide multiple inheritance.
• The overall reliability of the language was enhanced by numerous improvements.
C
• The C programming language, invented around 1972 at Bell Laboratories, is a good language for “ low - level ”
programming.
• The C language provides special variable types, such as register , volatile, static , and constant , which allow for
effective control of code generation at the procedural language level.
• When variable used as a register type, the compiler to place such a declared variable in a work register, which often
results in faster and smaller programs.
• Furthermore, C supports call - by – value only, but call - by - reference can be implemented easily by passing a
pointer to anything as a value.
• Variables declared as type volatile are not optimized by the compiler at all. This feature is necessary in handling
memory – mapped I/O and other special instances where the code should not be optimized.
• Automatic coercion refers to the implicit casting of data types that sometimes occurs in C.
• The C language provides for exception handling through the use of signals, and two other mechanisms, setjmp and
longjmp , are provided to allow a procedure to return quickly from a deep level of nesting — a particularly useful
feature in procedures requiring an abort.
• Overall, the C language is particularly good for embedded programming, because it provides for structure and
flexibility without complex language restrictions.
C ++
• C ++ is a hybrid object - oriented programming language that was originally implemented as a macro extension of C in the 1980s.
• Today, C ++ stands as an individual compiled language & exhibits all characteristics of an object - oriented language and promotes better
software - engineering practice through encapsulation and more advanced abstraction mechanisms than C.
• C ++ compilers implement a preprocessing stage that basically performs an intelligent search - and - replace on identifiers that have been
declared using the #define or #typedef directives.
• The problem with the preprocessor approach is that it provides a way for programmers to inadvertently add unnecessary complexity to a
program also it has weak type checking and validation.
• Previously C ++ programmers used complex pointer arithmetic to create and maintain dynamic data structures, cconsequently lots of
bugs appear. Today, however, standard libraries of dynamic data structures are available.
• There are three complex data types in C ++ : classes, structures, and unions. However, C ++ has no built - in support for text strings.
• Multiple inheritance is a helpful feature of C ++ that allows a class to be derived from multiple parent classes also complicated to
implement from the compiler perspective.
• C ++ still allows for low - level control; for instance, it can use inline methods rather than a runtime call.
• Furthermore, C ++ does not provide automatic garbage collection, which means dynamic memory must be managed manually or garbage
collection must be homegrown.
• Therefore, when converting a C program to C ++ , a complete redesign is required to fully capture all of the advantages of an object -
oriented design while minimizing the runtime disadvantages.
C#
• C# (pronounced “ C sharp ” ) is a C ++ - like language that, along with its operating environment, has similarities to Java and the Java
virtual machine, respectively.
• C# is first compiled into an intermediate language, which is then used to generate a native image at runtime.
• C# is associated with Microsoft’s .NET framework for scaled - down operating systems is highly configurable, capable of scaling from
small, and upwards (e.g., for real - time systems requiring user - interface support).
• The minimum kernel configuration provides basic networking support, thread management, dynamic link library support, and virtual
memory management.
• C# supports “ unsafe code, ” allowing pointers to refer to specific memory locations. Objects referenced by pointers must be explicitly “
pinned, ” disallowing the garbage collector from altering their location in memory. This capability could increase schedulability, and it
also allows for direct memory access ( DMA ) to write to specific memory locations;
• Moreover, C# provides many thread synchronization mechanisms, but none with this level of precision.
• C# supports an array of thread - synchronization constructs: lock, monitor, mutex, and interlock. A Lock is semantically identical to a
critical section — a code segment guaranteeing entry into itself by only one thread at a time like mutex .
• Finally, interlock, a set of overloaded static methods, is used to increment and decrement numeric in a thread - safe manner in order to
implement the priority - inheritance protocol. Timers that are similar in functionality to the widely used in C#. The accuracy of these
timers is machine dependent, and thus not guaranteed, reducing their usefulness in real - time systems to be used in multiple hardware
platforms.
• C# and the .NET platform are not appropriate for the majority of hard real -time systems for several reasons, including the unbounded
execution of its garbage - collection environment and its lack of threading constructs to adequately support schedulability and
determinism.
• C# ’ s ability to interact effectively with operating - system APIs, shield developers from complex memory management logic, together
with C# ’ s good floating – point performance, make it a programming language that is highly potential for soft and even firm real - time
Java
• Java, in the same way as C#, is an interpreted language, that is, the code compiles into machine - independent intermediate code that runs in a managed execution
environment.
• The obvious advantage is that Java code can run on any device that implements the virtual machine.
• However, there are also native - code Java compilers, which allow Java to run directly “ on the bare metal, ” that is, the compilers convert Java to assembly code or object
code.
• Furthermore, there are even special Java microprocessors, which directly execute Java byte code in hardware .
• Java is an object - oriented language and the code appears very similar to C++. Java supports call - by - value. But Java is a pure object - oriented language, that is, all
functionality in Java has to be implemented by creating object classes, instantiating objects of those classes and manipulating objects ’ attributes through methods.
• Of course, a good object - oriented design is not guaranteed, but the design obtained in the conversion will be a true object - oriented one based on the rules of the language.
This situation is quite different from the kind of false object - oriented conversion that can be obtained from C to C ++ in the blunt manner previously highlighted.
• Java does provide a preprocessor but constant data members are used in place of the #define directive, and class definitions are used in lieu of the #typedef directive.
• The Java language does not support pointers, but it provides similar functionality via references. Java passes all arrays and objects by reference, which prevents common
errors due to pointer mismanagement.
• Java only implements one complex data type: classes. Java programmers use classes when the functionality of structures and unions is desired. This consistency comes at the
cost of increased execution time over simple data structures.
• The Java language does not support standalone functions. Instead, Java requires programmers to bundle all routines into class methods again with significant cost. Moreover,
Java has no direct support for multiple inheritance however, allow for implementation of multiple inheritance.
• In Java, strings are implemented as first - class objects meaning that they are at the core of the Java language. Java ’ s implementation of strings as objects provides several
advantages. First, string creation and access is consistent across all systems. Next, because the Java string classes are defi ned as part of the Java language strings function
predictably every time. Finally, the Java string classes perform extensive runtime checking, which helps eliminate errors. But all these operations increase execution time.
• Operator overloading is not supported in Java. However, in Java’s string class, “ + ” represents concatenation of strings, as well as numeric addition.
• The Java language does not support automatic coercions. In Java, if a coercion will result in a loss of data, then it is necessary to explicitly cast the data element to the new
type.
Real - Time Java
• The specification must include a framework for the lookup and discoveryof available profiles.
• Any garbage collection that is provided shall have a bounded preemption latency.
• The specification must defi ne the relationships among real - time Java threads at the same level of detail as is currently available in existingstandards
documents.
• The specification must include APIs to allow communication and synchronization between Java and non - Java tasks.
• The specification must include handling of both internal and external asynchronous events.
• The specification must include some form of asynchronous thread termination.
• The core must provide mechanisms for enforcing mutual exclusion without blocking.
• The specification must provide a mechanism to allow code to query whether it is running under a real - time Java thread or a nonreal - time Java thread.
• The specification must defi ne the relationships that exist between real -time Java and nonreal - time Java threads.
• The RTSJ defines the real - time thread class to create threads which can access objects on the heap and d therefore can incur delays because of garbage
collection.
• For garbage collection, the RTSJ extends the memory model to support memory management which ensures no interfere with the real - time code’
stability to provide deterministic behaviour.
• RTSJ uses “ priority ” somewhat more loosely than is traditionally accepted. “ Highest priority thread ” merely indicates the most eligible thread — the
thread that the scheduler would choose from among all threads ready to run.
COMPILER OPTIMIZATIONS OF CODE
• There exist infinitely many object codes that implement the same computations produce the same
outputs when presented with the same inputs.
• Some of these object codes may be faster while others may require less memory. Hence, it is more
important use an optimized code.
• When beginning to use a new compiler, it is important to expose the details of the compiler for
effective optimized code design as well as one should know both the language and your compiler
thoroughly.
• Moreover, many of the techniques used in code optimization underscore, but the fact that
mathematical technique is that reformulate any algorithm or expression to eliminate time -
consuming function calls to improve real - time performance.
• Most of the code optimization techniques used by compilers can be exploited to reduce response
times. Often these strategies are employed invisibly by the compiler, or can be turned on or off
with compiler directives or switches.
COMPILER OPTIMIZATIONS OF CODE (contd.)
• Use of arithmetic identities and intrinsic functions
• Reduction in strength
• Common subexpression elimination
• Constant folding
• Loop invariant removal & induction elimination
• Use of registers and caches
• Dead - code removal
• Flow - of - control optimization
• Constant propagation
• Dead store elimination & variable elimination
• Short - circuit Boolean code
• Loop unrolling & jamming
• Cross - branch elimination

You might also like