Design Article
Time partitioning drives faster software integration for telematics and infotainment: Part 3 - Redistributing the processor load
Andy Gryc and Paul Leroux, QNX Software Systems
5/21/2008 9:07 AM EDT
Part 2 goes into hands-free phone simulation code development.
Using partitioning to solve the problem
Let's see if we can do better than the priority-based model (with resulting system "hangs") used in Part 2, without having to migrate to a faster CPU or modify source code. The goal is to distribute the processor time more effectively by appropriately redistributing the load for each subsystem: Outgoing audio, incoming audio, navigation, and system. We also want to improve utilization of idle CPU time, so as to realize greater overall performance. To achieve this goal, we will use time partitioning.
Without using threads, a developer can create code that appears to do multiple things at once. However, this approach can be quite difficult, and requires careful design and a great deal of attention to detail. The developer would need to customize and tinker with the various code paths to ensure that all the tasks run in a timely fashion. The introduction of threads to the programmer's toolkit solves this problem, allowing the developer to concentrate on the problem at hand, rather than on the entire system.
Time partitioning, which a variety of operating systems now support, provides another leap in abstraction and simplification for the developer. It exists one level above threading and priorities, and it allows the system designer to focus on subsystem development. Using this technique, the system designer can group subsystems into separate compartments, or partitions, and allocate a guaranteed portion of CPU time to each partition.
Consider the example in the figure below, where we have placed the four major subsystems of the hands-free phone module into separate partitions and allocated a CPU budget for each partition: 35% for outgoing audio, 25% for incoming audio, 15% for navigation, and 25% for system tasks.

In effect, partitioning carves up a processor into smaller virtual CPUs, simplifying the job of integrating multiple software subsystems. As a developer, you no longer have to worry about the priorities of threads outside of your subsystem: Those threads won't impact your performance, even if they run at a higher priority than yours. Moreover, it's easy to test whether your subsystem works within the CPU budgets defined by the system designer. At integration time, the OS will enforce the resource budgets, preventing any subsystem from consuming resources needed by other subsystems. Each subsystem will perform as expectedand as previously tested.
In many systems, CPU utilization is sporadic, resulting in idle CPU cycles. Some forms of partitioning take advantage of these idle cycles: If a partition doesn't consume all of its allocated CPU cycles, the partitioning scheduler dynamically reallocates those idle cycles to partitions that could benefit from the extra processing time. This "adaptive partitioning" approach, which has been implemented in the QNX Neutrino RTOS, allows a system to handle peak demands and permits 100% CPU utilization.
In some implementations, such as Neutrino adaptive partitioning, partitions can communicate with one another without any need for special programming (mailboxes, APIs, etc.). As a result, development teams can introduce partitions to the system architecture without having to modify existing code. The developers simply launch existing POSIX-based applications in a partition, and the scheduler ensures that partitions receive their allocated budget. Processes and threads don't need know that they are, in fact, running in partitions.
Also note: Some partitioning operating systems also let the system designer assign a separate memory budget to each partition, thereby ensuring that each subsystem always has sufficient memory to perform its designated task. While this series of articles focuses on time partitioning, memory partitioning also provides a useful technique for simplifying integration efforts.



