SYSTEM DEVELOPMENT

Ada “Reloaded” a Winner for High-Integrity Real-Time Apps

Despite some challenges from C++ and Java, Ada is still the technology to beat in high-integrity real-time military applications. New features in Ada 2005 help sweeten the deal.

ROBERT DEWAR, PRESIDENT AND CEO, BEN BROSGOL, SENIOR TECHNICAL STAFF, ADACORE

Keywords in this Article:

No Keywords

  • Page 1 of 1
    Bookmark and Share

Programming languages, like living organisms in a Darwinian jungle, need to adapt if they are to survive in a changing technological landscape that can bring challenges, surprises and occasional major climatic disruptions. Ada has been around for more than 25 years and has undergone one major revision, in the mid-1990s. Its most recent update, known as Ada 2005, was published as an ISO standard earlier this year. This version of the language brings improvements in several areas, including new facilities for Object-Oriented Programming and some additional libraries. But what may have even greater impact are a number of relatively small enhancements that increase Ada’s support for high-integrity real-time systems.

High Integrity Means What?

A high-integrity application is one where safety, security, or both are essential requirements. In the safety-critical arena each application domain tends to have its own specific requirements standard that a system must satisfy in order to be certified, for example, RTCA DO-178B for commercial avionics. In the security area the situation is somewhat less fragmented, with the Common Criteria and Common Evaluation Methodology generally accepted as certification requirements standards in a domain-independent fashion. Tables 1 and 2 summarize the various criticality levels of the two standards. Generally systems at DO-178B Level A or B would be considered safety-critical, and systems at EALs 5 through 7 would be considered high security.

Although safety and security standards evolved independently, their common goal is to offer assurance that the delivered system is free from vulnerabilities that could lead to safety hazards or security breaches. Not surprisingly, they make basically the same demands on the programming language—or languages—used for development: the language must support reliable, predictable and analyzable code, yet be expressive enough to capture the processing and data structures characteristic of the application domain.

Ironically, some of the features that in general help developers produce robust and maintainable software—such as Object-Oriented Programming, generic templates and exceptions—complicate analyzability, especially for systems that need to comply with the highest levels of DO-178B or the Common Criteria. The key for the developer is to choose an appropriate language and then to restrict feature usage to a subset based on the kinds of analyses that are to be performed.

Ada Does the Job

Ada is an experienced player in the field of high-integrity software, and Ada 95—indeed Ada 83—already provides a sound language foundation. For example, Ada’s lexical and syntactic rules avoid the confusion found in C-based languages and also in Java for things like octal literals (the leading 0 might better be called the misleading 0) and “if” statements (dangling else). Ada’s parameter passing modes, which reflect the data flow direction (in, out, or in out) make it easier for tools to analyze information flow: dependencies between the inputs to and the outputs from a subprogram.

One of the most notable milestones during Ada’s history was the production of an ISO Technical Report (Table 3) on feature usage for high-integrity systems. That report is basically a matrix that identifies, for each type of analysis that might be desired—such as control flow, data flow, formal proofs of correctness—whether or not a given language feature is permitted.

In short, that report showed that there is no such thing as “the high-integrity” subset of Ada, or for any other language, and indeed what is needed is a language mechanism that allows the programmer to identify which features are to be excluded. Among other things, this means that there will be no run-time libraries for the excluded features, thus simplifying the job of certification against standards such as DO-178B. Ada is unique in supplying a feature called Pragma Restrictions that allows the programmer to specify those features that the program is not using.

High Integrity Systems Annex

The High Integrity Systems Annex of the Ada standard specifically addresses the needs of safety-critical and high-security systems. Among other things, this section of the reference manual, originally called the Safety and Security Annex, identifies a number of features that can be specified with Pragma Restrictions. These include restrictions prohibiting dynamic allocation, exceptions and nested tasks.

The subject of tasking in high-integrity systems is interesting. Concurrency features significantly complicate the job of certifying high-integrity systems, since they make possible new kinds of hard-to-detect errors: race conditions, where the effect of the program may depend on the relative speed with which the concurrent tasks execute, and deadlock, where several tasks are mutually holding resources that are needed by some other tasks, and thus all are waiting.

These sorts of errors are not always deterministically reproducible. Ada addresses this issue in several ways. First, it has a high-level tasking model that makes it easier to express concurrent algorithms. This is in contrast with Java, whose low-level mechanisms (synchronized code, wait/notify) are rather error prone. Second, a subset of the Ada tasking model—the so-called Ravenscar Profile—is simple enough that it can be used in systems where high certification levels are required, but powerful enough to be usable in real systems.

All of these features have been in Ada for some time. Ada 2005 has added a number of improvements that make Ada even better for high-integrity applications. Here are some of the enhancements:

• Pragma Profile is a new mechanism that allows bundling a set of restrictions and giving it a name. This has been done with the Ravenscar restrictions: by specifying pragma Profile (Ravenscar) the programmer is identifying the full set of tasking restrictions that will be enforced. Another potential candidate for pragma Profile is the SPARK subset. SPARK is an Ada subset augmented with annotations in the form of comments. SPARK programs are amenable to various forms of static analysis that make it possible and practical to prove that a program complies with its formal specification.

• Ada’s access type “pointer” facility has been enhanced so that the programmer can more precisely specify various properties. For example, a formal parameter to a subprogram can be marked as “access constant,” meaning that the parameter has “read only” access to the object that it points to. This is an important feature, making information flow analysis easier. Another enhancement is that an access type can be marked as “not null,” such as values of the access type must always point to some existing object, they can never be null. This helps efficiency—since there is no need for a run-time check that a pointer is null—and also facilitates analysis and avoids certain kinds of pointer errors.

• Pragma Assert has been added, with an argument identifying a Boolean expression that is asserted to be true. If the condition is false, an exception is raised—and an optional argument to the pragma can specify a string that can be retrieved when the exception is handled. The programmer can control whether the assert condition is checked at run-time.

Beyond those features, which relate to high-integrity programming, a number of new features have also been added that assist in real-time programming. There are some new task dispatching policies, a mechanism that allows different dispatching policies to be used for different sets of tasks based on their priority level, additional functionality associated with task termination, and a mechanism for monitoring processor usage on a per-task basis.

In short, Ada is building on its strengths for high-integrity systems. It has been and continues to be successfully used by a wide range of major systems developers on projects including air traffic control, commercial aviation, military aviation programs—such as the Eurofighter (Figure 1) and other defense programs at Honeywell, MBDA, Raytheon and more. Moreover, new projects are starting up and choosing Ada: a notable example is the iFACTS project in the United Kingdom, a next-generation air traffic control system sponsored by NATS that is using the SPARK Ada subset.

Ada vs. Other Languages

There are two other major technologies that users might consider for high-integrity real-time systems. One is the C family, including C++, and the other is Java. It is certainly possible to use these; the questions are more whether the language is fit for the purpose, and whether its technology and tool support are mature.

C and C++ have the benefit of a large user community. However, C was not designed with high reliability in mind, and it has become necessary to define “safe” subsets such as MISRA C to overcome this significant shortcoming. Adhering to the MISRA C subset indeed does help avoid the major traps and pitfalls, but not all of the rules are checkable by automated tools, and indeed some rules (such as prohibition against dangling references) might be enforced differently by different tools. Further, C does not scale up to very large systems; the general migration path is then to move to C++.

But C++ has the same issues as C, plus the complexity of features such as templates, exceptions and Object-Oriented Programming. Different organizations have tried to mitigate these shortcomings by defining “safe” subsets, but these vary from one developer to another. There is an attempt to define a safe subset, MISRA C++, but this is still in progress. Further, C++ does not support concurrency, a major omission in a language that is to be used for real-time programming.

Java is another option, and it is certainly reasonable to consider this language for applications where high reliability is important. Java’s semantics, with few exceptions, are well defined; it is seriously concerned with security issues; run-time checks avoid the well-known “buffer overflow” problem in C; “dead code” and potential references to uninitialized local variables are detected; and dangling references are prevented.

However, these do not imply that Java—the full language—is appropriate for either real-time or high-integrity applications. Some major issues are: Java is too slow, its semantics for thread scheduling are underspecified and can lead to priority inversions, it lacks functionality for low-level processing, the clock granularity is too coarse, garbage collection means unpredictable latencies, there is no safe way to terminate an application—as might be needed for example in a “mode change.” Furthermore, one of Java’s main attractions for general-purpose software development—Object-Oriented Programming (OOP)—has never been considered necessary for real-time systems, and another main attraction—Java’s extensive class library—is diminished because the library would need to be rewritten for real-time predictability.

Real-Time Java

Those are significant problems with Java, but one person’s problem is another person’s challenge, especially when there is a potential market to be exploited. Indeed, there have been some serious efforts to come up with a viable approach. The first was the Real-Time Specification for Java (RTSJ), under the auspices of Sun Microsystems’ Java Community Process. It originated in early 1999 and was formally approved in November 2001.

The RTSJ was intended for real-time applications, but not necessarily for ones that need to meet high-integrity standards such as DO-178B. Indeed, the RTSJ is not a subset of Java that is restricted to provide real-time predictability, but rather an extension of the full Java platform with additional classes that give real-time behavior. It is thus too large to be practical for safety-critical systems, and there is no analog to Ada’s Pragmas Restrictions and Profile to allow the user to cut out the unneeded parts.

In light of all those issues, an effort is underway to define Safety-Critical Java Technology by subsetting the RTSJ. This work was conceived in 2003 and was begun in earnest in July 2006 under The Open Group. Like the RTSJ, this is being done under Sun Microsystems’ Java Community Process. A challenge to this effort is that there are currently two commercial offerings for safety-critical Java solutions, from different vendors.

Low-Risk Technology

Ada is an established and low-risk technology for real-time high-integrity systems, and Ada 2005 continues this tradition. One of Ada’s unique benefits is its recognition of the need for programmers to define subsets, so that the appropriate analysis techniques can be performed. For example, OOP either in its entirety or in part can be excluded. Products are available from a variety of vendors, targeted to widely used RTOSs. C and C++ are also candidate technologies and have the benefit of popularity in other domains—and thus a good supply of programmers who know the languages—but they lack the reliability underpinnings of Ada.

Java is attracting interest in the real-time high-integrity marketplace, but it is nowhere near as mature a technology as Ada in this domain, and it has some intrinsic issues—such as its role as a “pure” Object Oriented language—that will continue to raise challenges for both implementors and users. Memory management is a difficult problem, and both real-time garbage collection and RTSJ-style scoped memory raise thorny issues for high-integrity systems.

AdaCore
New York, NY.
(212) 620-7300.
[www.adacore.com].

LEAVE A COMMENT