In 1990, while porting its C EXECUTIVE real-time kernel to the i960, JMI Software Systems, Inc., invented a method for a modified use of the processor state flag in the i960's process-controls register. By using the processor in a non-conventional manner, significant savings in interrupt processing time and context switching time are achieved.
Normally, this state flag is 0 (executing) when the processor is executing a program, and 1 (interrupted) when the processor is servicing an interrupt. With the conventional use of the processor state flag, each user task running under C EXECUTIVE, or any other kernel, would have its own procedure stack. When an interrupt occurs, the hardware would switch to the interrupt stack. The first interrupt which occurs would create an interrupt record and frame at the top of the interrupt stack. Succeeding, or nested, interrupts would then create additional records and frames on the interrupt stack.
The problem occurs when the kernel, as the result of processing an interrupt, determines that a context switch must be made to a higher priority task. User task information from the interrupt record and frame must be copied into a task control block, since the interrupt stack will be overwritten when an interrupt occurs during execution of the higher priority task. This copy operation not only takes more than a few instructions, but, in addition, must also be accomplished during a time-critical interrupt processing sequence. Both interrupt response time and preemptive context switching could be improved if the kernel did not have to copy the saved interrupt record and frame from the interrupt stack to a task control block.
Stated another way, at the worst possible time, when the kernel is trying to preempt lower priority processing to respond to a higher priority event, the kernel must stop to copy an interrupt record and frame from one place to another.
In order to improve the performance of the i960, JMI uses the processor state flag in an inverted manner, therefore eliminating the need to copy data from the interrupt stack. When a process is executing, C EXECUTIVE sets the processor state flag to 1 (interrupted). When an interrupt occurs, the processor assumes it is already on the interrupt stack (since the state flag says so!), and creates the interrupt record and frame on the current stack, which is the task procedure stack.
If the interrupt occurred while a user task was executing (with the state flag set to interrupted), C EXECUTIVE immediately sets the processor state flag to 0 (executing).
If another interrupt occurs during the processing of the first interrupt, causing a nested interrupt, the processor will automatically switch to the interrupt stack. The kernel now leaves the processor state flag set to 1 (interrupted), and all succeeding interrupts will create frames on the interrupt stack.
Therefore, if a preemption is to be made to a higher priority task, the kernel does not have to copy data from the interrupt stack, since the user task information is already safely preserved in the interrupt record and frame on the interrupted task's procedure stack.
Using the above method also permits the optimization of saving global registers in local registers during interrupt processing. Normally, global registers must be saved on the stack, which involves memory loads and stores. However, since the interrupt record and frame containing task data is on the task procedure stack, the global registers may be saved in the task local registers, where they will be safely preserved in the case of a context switch.
The following summary shows the number of instructions and number of memory accesses saved using JMI's new method:
Interrupt and context switch: 13 fewer instructions (including a multi-cycle "flushreg"), and 33 fewer memory accesses
Interrupt without context switch: 1 less instruction, and 20 fewer memory accesses
Context switch with no interrupt: 1 less instruction
Note that this method improves performance in all three situations, but the biggest improvement is for the most important situation - reacting to new events in a timely fashion, a real-time kernel's most important function.
This method uses standard i960 core features, and has been qualified on the following i960 variants: KB, CA/CF, SA/SB, Jx. Intel is one of JMI's customers using C EXECUTIVE, with Reverse State Use, on the i960.
The i960 Reverse State Use invention is a clear example of how JMI optimizes time-critical portions of its kernel, while keeping 95% of C EXECUTIVE in portable ANSI C code, common to all target CPU architectures and all compilers. This combination results in high reliability and high performance.
Please contact JMI Software Systems if you have any questions about JMI's Reverse State Use invention.
Go to JMI home page