Java and Linux Make Natural Partners for Soft Real-Time Solutions

Fractal Realms series. Backdrop of fractal elements, grids and symbols on the subject of education, science and technology

Modern soft real-time systems tend to be much larger, more dynamic and more complex than previous generations of products. They typically include multiple layers of software, some of which incorporate networking infrastructures that must be securely networked with other computers as part of the greater Internet. To address such challenges, developers are looking to larger, more complete development solutions where the tools themselves are part of a universal framework.

Linux as an open source OS solution and Java as a ubiquitous language have come to play such a role. Among the benefits of Linux are its support for all popular embedded CPU architectures and single board computers, self-hosted development and an abundance of ready-to-run open-source software components. Java builds upon these benefits by enabling developers to quickly and easily develop powerful new capabilities as custom software, and allowing them to integrate into their custom software solutions a huge variety of off-the-shelf Java software components.

There are a number of general challenges associated with soft real-time development that differ from those normally associated with real-time development. Soft real-time systems tend to be large, dynamic and complex. Because of their size and complexity, it is not practical to use the rigorous analysis disciplines for development of this software that are typically used for hard real-time development. Rather than determine resource needs through meticulous analysis, the soft real-time developer typically determines resource needs empirically, measuring how components behave. Developers use statistical and heuristic techniques to increase the probability that deadlines will be met and to maximize the utility provided by the soft real-time system whenever it is not possible to satisfy all deadlines because of work overloads.

The quip, “Hard real-time is hard. Soft real-time is harder,” accurately indicates the increased difficulty in building complex soft real-time systems. In general, developers choose to use soft real-time techniques whenever they are not able to statically guarantee availability of all the resources required for reliable compliance with hard real-time deadlines.

This usually results from a combination of several possible factors. For one thing, it is not always possible to determine an absolute upper bound on the frequency or magnitude of workload processing requests, and the software that processes the workload has unpredictable execution times. For this class of system, it would be too costly to guarantee availability of all the resources required to ensure hard real-time operation in the worst-case scenarios. In addition, there could be conflict for resources because the desire to maximize the utility of available computation resources often requires utilization of resources that cannot always be guaranteed available at a given time.

Because of their size and complexity, and the frequent need for dynamic reconfiguration of the processing workload, soft real-time systems often need much more underlying support infrastructure than is typically provided by commercial real-time operating systems. Traditionally, mission-critical soft real-time systems have most commonly run on commercial variants of Unix, such as AIX, HP-UX and Solaris. During recent years, Linux has matured significantly. It has now demonstrated its value in many high-reliability commercial deployments. With this proven reliability, Linux is increasingly deployed in mission-critical applications that were previously dominated by commercial Unix operating systems.

Because Linux is supported by a very large community of open-source developers, Linux configurations are available to run on every popular microprocessor CPU architecture and board. For this same reason, a wealth of device drivers is available to support all sorts of different communication protocols and I/O devices, including USB and Firewire (IEEE 1394). More recent initiatives, such as the carrier-grade Linux effort, establish standard mechanisms for implementation of high-availability systems, including support for warm-standby operation and application failover, as well as support for hot-swappable devices. Real-time virtual machines running on top of Linux provide library access to all of the devices supported by the Linux configuration.

As a POSIX-compatible operating system, Linux also offers a stable platform on which to deploy legacy software components written in C or C++. Many open-source legacy software components are freely available to be incorporated into Linux-based system designs. Even though Java makes an ideal programming language for complex, dynamic real-time systems, almost all existing deployments exploit a combination of Java code to implement the more dynamic and highest levels of the system hierarchy, along with C or C++ code to implement the lower layers of the system hierarchy. These lower layers are often characterized by more static behavior and more demanding performance and/or memory footprint requirements.

Among the other reasons Linux is increasingly used in mission-critical systems are the various improvements introduced with the newly released Linux 2.6 kernel. This adds significant enhancements to support improved scalability, reliability and security. Among these features, there is improved support for multiprocessor systems, larger memory configurations and better real-time predictability with tighter real-time responsiveness.

As a programming language supported on top of Linux, Java is an appropriate platform for development of large and complex dynamic systems. Its high-level support for portable and scalable object-oriented development supports easy development, integration and maintenance of large systems comprised of independently developed software components. Most programmers find that they are approximately twice as productive developing Java code than C++ code, and up to ten times more productive during the integration and maintenance of embedded real-time Java software.

Historically, doing real-time software with Java has been difficult because traditional Java virtual machines experience occasional long execution pauses while they perform automatic garbage collection. Depending on the memory configuration, these pauses may last up to thirty seconds at a time. Real-time virtual machines allow soft real-time execution of standard-edition Java components, supporting reliable compliance with timing constraints ranging from 1 to 100 ms. These virtual machines provide real-time garbage collection, real-time fixed-priority scheduling, priority inheritance for all Java synchronization locks, and priority-ordered wait and synchronization queues. The use of real-time virtual machines has now been proven, with a variety of commercially deployed products having demonstrated millions of hours of successful “five nines” and higher reliability.

Motivated by the specialized needs of developers who are building real-time mission-critical systems, vendors of real-time virtual machines have enhanced the traditional Java development tool chain to support capabilities that are critical to this developer community. For example, traditional Java virtual machines support only interpreted and JIT-compiled execution of Java programs. But many mission-critical developers also require the ability to perform ahead-of-time compilation and static linking of Java software components, similar to what they would do with more traditional C or C++ tools.

Java developers often take the availability of high-quality debugger and profiling tools for granted. Many immature embedded virtual machine implementations do not support any commercial run-time performance profilers. However, experience has taught that understanding the performance implications associated with the behavior of large, complex, dynamic systems often requires the ability to profile the running application. Therefore, mature real-time virtual machines generally provide run-time profiling capabilities.

Vendors of real-time virtual machines have also found it necessary to support special debugging capabilities that had not been viewed as important to traditional desktop and enterprise developers. For example, traditional Java virtual machine debuggers can only debug interpreted code. Whenever debugging is enabled, the virtual machine is forced to ignore its compiled method implementations so that the debugger can monitor the program behavior. Virtual machines designed for mission-critical real-time systems also support the ability to debug compiled programs. This was motivated by the mission-critical developer dogma: “Test what you ship. Ship what you test!”

It is important to have the ability to make on-the-fly adjustments to work buffer sizes and linked data structures, and to dynamically load and unload Java classes. Such capabilities support the dynamic reconfiguration of software that is required to perform the load balancing and workload (re)distribution that is typically required in fault-tolerant and high-availability real-time systems. In these sorts of systems, accurate real-time garbage collection and deterministic thread scheduling and synchronization provide the solid foundations upon which the highly dynamic real-time system is built.

Besides supporting the ability to balance system workloads and to migrate the redundant computations required to support warm-standby operation for fault-tolerant computation, dynamic class loading and unloading also empowers developers with significant new capabilities. When errors are found in deployed software, dynamic class loading supports the ability to dynamically load corrective patches into the running system, often without requiring the system to be rebooted.

Similarly, when system functionality must be enhanced in response to evolving end-user requirements and/or new communication protocols, the new functionality can be added to the running system, once again without requiring any downtime. Finally, many mission-critical systems have the need to support temporary specialized capabilities. These temporary capabilities can be dynamically loaded into the running system and then unloaded after the temporary need for this capability is no longer present.

Among the various frameworks that are available to support the deployment and field maintenance of Java software is the OSGi (Open Software Gateway Initiative) framework. This standard, which supports software configuration management on deployed systems, is available both as open-source libraries and commercially supported products. The OSGi framework keeps track of which software versions of each relevant software bundle are running at any given time on each deployed system. OSGi management tools help automate the process of distributing new software versions to targeted devices, and of automating the process of installation, initialization and startup of the new software versions.

A typical Linux-Java deployment architecture is shown in Figure 1. Note that middleware is available both as native libraries (typically implemented in C or C++) and as Java components running on top of the real-time virtual machine. Almost all deployed soft real-time Java systems include a combination of native and Java application software. In many cases, the same team takes responsibility for implementing both Java and native software and partitions between the two languages. This requires consideration of the tradeoffs in performance, memory footprint, real-time latency, dynamic behavior, software engineering difficulty and access to low-level device hardware. In other cases, it is common for newly developed software that is written in Java to be combined with legacy software written in C or C++. Either approach works well.

Linux and Java are already being used together in a variety of mission-critical soft real-time systems. However, many of these have not yet authorized public disclosure of their activities.

San Diego, CA.
(858) 457-2700.