Rationale for Ada 2012

John Barnes
Contents   Index   References   Search   Previous   Next 

5.4 Interrupt timers and budgets

It will be recalled that Ada 2005 introduced three packages for monitoring the CPU time used by tasks. They are a root package Ada.Execution_Time plus two child packages thus

this is the root package and enables the monitoring of execution time of individual tasks.

this provides facilities for defining and enabling timers and for establishing a handler which is called by the run time system when the execution time of the task reaches a given value.

this enables several tasks to share a budget and provides means whereby action can be taken when the budget expires. 
The execution time of a task, or CPU time, is the time spent by the system executing the task and services on its behalf. CPU times are represented by the private type CPU_Time declared in the root package Ada.Execution_Time.
However, it was left implementation defined in Ada 2005 as to how the time spent in interrupts was to be accounted. The Ada 2005 RM says
It is implementation defined which task, if any, is charged the execution time that is consumed by interrupt handlers and run-time services on behalf of the system. 
As noted in the AI, a common and simple implementation will charge the time consumed by the interrupt handlers to the task executing when the interrupt is generated. This is done under the assumption that the effect of interrupt handlers on the execution time clocks is negligible since the interrupt handlers are usually very short pieces of code. However, in real-time systems that undertake an intensive use of interrupts, this assumption may not be realistic. For example, Ada 2005 introduced timed events that can execute handlers in interrupt context. The facility is convenient and has low overheads, and therefore programmers are tempted to put more code into these handlers.
It is thus considered important to be able to measure time spent in interrupts and so facilities to do this are added in Ada 2012.
The root package is extended by the addition of two Boolean constants, Interrupt_Clocks_Supported and Separate_Interrupt_Clocks_Supported, and also a function Clocks_For_Interrupts so in outline it becomes
with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Real_Time;  use Ada.Real_Time;
package Ada.Execution_Time is
   type CPU_Time is private;
   function Clock(T: Task_Id := Current_Task) return CPU_Time;
   Interrupt_Clocks_Supported: constant Boolean := implementation-defined;
   Separate_Interrupt_Clocks_Supported: constant Boolean := implementation-defined;
   function Clocks_For_Interrupts return CPU_Time;
   ... -- not specified by the language
end Ada.Execution_Time;
The constant Interrupt_Clocks_Supported indicates whether the time spent in interrupts is accounted for separately from the tasks and then Separate_Interrupt_Clocks_Supported indicates whether the time is accounted for each interrupt individually.
The new function Clocks_For_Interrupts returns the CPU_Time used over all interrupts. It is initialized to zero.
Time accounted for in interrupts is not also accounted for in individual tasks. In other words there is never any double accounting.
Calling the function Clocks_For_Interrupts if Interrupt_Clocks_Supported is false raises Program_Error. Note that the existing function Clock has a parameter giving the task concerned whereas Clocks_For_Interrupts does not since it covers all interrupts.
A new child package of Ada.Execution_Time is provided for monitoring the time spent in individual interrupts. Note that this package always exists even if the Boolean constant Separate_Interrupt_Clocks_Supported is false. Its specification is
package Ada.Execution_Time.Interrupts is
   function Clock(Interrupt: Ada.Interrupts.Interrupt_Id) return CPU_Time;
   function Supported(Interrupt: Ada.Interrupts.Interrupt_Id) return Boolean;
end Ada.Execution_Time.Interrupts;
The function Supported indicates whether the time for a particular interrupt is being monitored. If it is then Clock returns the accumulated CPU_Time spent in that interrupt handler (otherwise it returns zero). However, if the overall constant Separate_Interrupt_Clocks_Supported is false then calling this function Clock for any particular interrupt raises Program_Error.
The package Ada.Execution_Time.Timers is exactly the same in Ada 2012. However, as mentioned earlier, the package Ada.Execution_Time.Group_Budgets is now defined to work on a single processor and the type Group_Budget is modified to include a discriminant giving the CPU concerned.

Contents   Index   References   Search   Previous   Next 
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by:
The Ada Resource Association:


and   Ada-Europe: