Version 1.3 of ai05s/ai05-0170-1.txt
!standard D.14(9/2) 10-06-04 AI05-0170-1/03
!standard D.14(11/2)
!standard D.14(13/2)
!standard D.14(18/2)
!standard D.14.3(0)
!class Amendment 09-10-22
!status work item 09-10-22
!status received 09-10-22
!priority Medium
!difficulty Easy
!subject Monitoring the time spent in Interrupt Handlers
!summary
Ada 2005 defines execution time clocks and timers for tasks, and
leaves the accounting of the execution time of interrupts as
implementation-defined. Implementation advice is provided to enhance
execution time clocks and timers by appropriately accounting for
execution time of interrupts when possible on the underlying platform.
!problem
Ada 2005 defines execution-time clocks to monitor execution times and
execution-time timers and group budgets to trigger actions when the
execution time of a task or a task group reaches a specific
value. This functionality is very useful to detect timing violations
as well as to implement advanced scheduling policies such as those
making resource reservations.
The Ada standard leaves as "implementation defined" the way in which
the execution time of interrupt handlers is accounted for:
"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." (RM D.14 (11/2))
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 sort 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 has introduced
timed events that can execute handlers in interrupt context. The
facility is convenient and has low overheads, and therefore
programmers are tempted to putting more code into these handlers.
As is shown in two papers at the 14th IRTAW it is possible with moderate
effort to monitor and manage the execution time of interrupt handlers
separately from the execution time of the tasks. With this modification
Execution Time Clocks provide a more realistic value of the time a
task has executed and, what is more important, execution time overruns
detected using Execution Time Timers and Group Execution Time Budgets
are more accurate. Therefore the first part of this proposal is to add
in the Ada standard implementation advice that will guide
implementors on the approach that is considered more adequate to reach
the needs of real-time applications.
If execution time of interrupts is monitored separately from that of
the tasks, it is easy to make the accounting of these execution times
available to the application. This information is useful to real-time
analysis and, therefore, the second part of this proposal is to add
facilities to allow the application to obtain the execution time of
interrupts.
Once execution time accounting is made for interrupts, it is not
difficult to also provide facilities to notify about execution time
overruns by interrupt service routines. These are useful to detect
timing violations inside interrupt code. This is the third part of our
proposal.
!proposal
See wording and discussion.
!wording
Add to package Ada.Execution_Time in D.14: [Where? After D.14(9/2)?? Editor.]
Interrupt_Clocks_Supported : constant Boolean := <implementation-defined>;
Separate_Interrupt_Clocks_Supported : constant Boolean :=
<implementation-defined>;
function Clock_For_Interrupts return CPU_Time;
Change 11/2 to:
The execution time or CPU time of a given task is defined as the time spent
by the system executing that task, including the time spent executing run-time
or system services on its behalf. The mechanism used to measure execution time
is implementation defined. The Boolean constant Interrupt_Clocks_Supported is
set to True if the implementation separately accounts for the execution time
of interrupt handlers. If it is set to False it is implementation defined which
task, if any, is charged the execution time that is consumed by interrupt
handlers. The Boolean constant Separate_Interrupt_Clocks_Supported is set to
True if the implementation separately accounts for the execution time of
individual interrupt handlers. If set to True the package
Ada.Execution_Time.Interrrupts must be supported (see D.14.3).
Add to end of 13/2:
The execution time value for the Clock_For_Interrupts is initialised to zero.
Add to Dynamic Semantics [Where? After D.14(18/2)?? Editor.]
The function Clock_For_Interrupts returns the total cumulative time spent
executing within all interrupt handlers. This time is not allocated to any
task execution time clock. If Interrupt_Clocks_Supported is set to False
the function will return a value equal to Time_Of(0).
Add a new D.14.3
This clause describes a language-defined package to measure the execution
time of interrupt handlers.
Static Semantics
The following language-defined library exists:
with Ada.Interrupts;
package Ada.Execution_Time.Interrupts is
function Clock (I : Ada.Interrupts.Interrupt_ID)
return CPU_Time;
function Supported (I : Ada.Interrupts.Interrupt_ID)
return Boolean;
end Ada.Execution_Time.Interrupts;
The execution time or CPU time of a given interrupt I is defined as the time
spent by the system executing interrupt handlers identified by I, including
the time spent executing run-time or system services on its behalf.
The mechanism used to measure execution time is implementation defined.
Time spent executing interrupt handlers is distinct from time spent
executing any task.
For each interrupt ID, the execution time value is initially set to zero.
Dynamic Semantics
The function Clock returns the current cumulative execution time of the
interrupt identified by I. If Separate_Interrupt_Clocks_Supported is
set to False the function will always return a value equal to
Ada.Execution_Time.Time_Of(0).
The function Supported returns True if the implementation is monitoring
the execution time of interrupt I. Otherwise it returns False. For any
interrupt ID I for which Supported(I) returns False, the function Clock(I)
will return a value equal to Ada.Execution_Time.Time_Of(0).
!discussion
This AI contains a proposal to add to the Ada standard
implementation advice on how to handle the measurement of the
execution time of interrupt handlers separately from the execution
time of user tasks.
The most interesting aspect of the new service is that it can
significantly enhance the accuracy of the execution time clocks and
timers of user tasks, because they are not arbitrarily charged with
the execution times of interrupt service handlers.
This support for managing the execution time of interrupt handlers
does not require any language modification or the addition of any new
API. However, once the interrupt execution time is measured, it can be
made available to Ada applications via special clocks that
measure the execution time of the interrupt handlers associated with a
given interrupt Id.
Moreover, it is possible to extend the current execution time timers
to use the newly defined execution time clocks for interrupt handlers,
thus introducing the ability for the system to detect execution time
violations in interrupt handlers.
Since all this functionality may not be available on all platforms it
is only proposed as implementation advice, to be implemented when
appropriate.
In [1] and [2] the overheads incurred by the implementation of these
new services have been measured, and found that they are very low in
comparison with the execution times of common interrupt
handlers.
Regarding the proposed API, it would be possible to define a Task_Id
for pseudo tasks representing interrupt handlers, but this would
create conflicts because they are not normal Ada tasks. Services
such as Set_Priority would need to treat them as a special case,
adding the need for new checks in potentially many places.
We believe that using Interrupt_ID for identifying the execution time
clocks is compatible with the proposed approach for attaching
interrupts to a specific processor in multiprocessor systems. It seems
that using pseudo-task IDs instead would require defining these for
each processor, which would add complexity to the API.
Parts number 2 and 3 of this proposal define new optional Ada packages
as "implementation advice". An alternative would be to make these
packages mandatory if the Real-Time Annex is supported, and allow the
implementation to provide dummy implementations for the subprograms, for
instance clocks that always return zero (meaning that interrupt time
is not measured) or timers which never expire (because the clocks on
which they are based do not advance).
Original Proposal is as follows.
This proposal contains three parts, listed in order
of importance. Each one is based on the previous one and adds new
services that are useful to real-time applications.
Part 1. Accounting of execution time of interrupts
--------------------------------------------------
Add the following "Implementation Advice" in RM D.14, "Execution Time"
When appropriate, the execution time consumed by interrupt handlers
and run-time services on behalf of the system should not be charged
to the execution time of application tasks.
Part 2. Interrupt execution time clocks
---------------------------------------
Add the following implementation advice in RM D.14, "Execution Time"
If the execution time consumed by interrupt handlers is accounted
for separately from the execution time of application tasks, the
time consumed should be made available to the application by means
of the following language-defined package:
with Ada.Interrupts;
package Ada.Execution_Time.Interrupts is
function Clock
(I : Ada.Interrupts.Interrupt_ID)
return CPU_Time;
private
. . .
end Ada.Execution_Time.Interrupts;
The Ada.Execution_Time.Interrupts package defines one
execution-time clock for each Interrupt_ID. The Clock function
returns the execution time spent by interrupt handlers while
handling the interrupt specified by I.
Part 3. Interrupt execution time timers
---------------------------------------
Add the following implementation advice in RM D.14.1, "Execution Time
Timers":
If the execution time consumed by interrupt handlers is accounted
for separately from the execution time of application tasks, and if
package Ada.Execution_Time.Interrupts is implemented, execution
time timers based on the execution time of interrupt handlers
should be made available to the application by means of the
following language-defined package:
with Ada.Interrupts;
package Ada.Execution_Time.Timers.Interrupts is
type Timer ( I : Ada.Interrupts.Interrupt_ID)
is new Ada.Execution_Time.Timers.Timer
(Ada.Task_Identification.Null_Task_Id'access )
with private;
private
. . .
end Ada.Execution_Time.Timers.Interrupts;
The Ada.Execution_Time.Timers.Interrupts defines execution time
timers based on the execution-time clocks defined in package
Ada.Execution_Time.Interrupts.
The Timer type extends the Timer type defined in the Timers
package and inherits and/or overrides all of its primitive
operations, including the ability to set handlers that will be
executed if the execution-time clock associated with the interrupt
identified by I reaches a specific value or consumes a specified
interval.
The Set_Handler procedures have the same effect as for regular
execution time timers except that their expiration is associated
with the execution time of the interrupt handlers that are
handling the interrupt identified by I.
Note that according to the scheduling rules for interrupts, the
handler of an interrupt execution-time timer may not be able to
execute until the interrupt handler that triggers it (and possibly
other interrupt handlers) has completed its own execution.
Implementation Permissions: Implementations may limit the number
of timers that can be defined for each interrupt Id. If this limit is
exceeded then Timer_Resource_Error is raised.
Note: This proposal uses constant Null_Task_Id as the Task_ID
discriminant, since a task Id is not needed for interrupt execution
time timers. This would require making the Null_Task_Id constant
"aliased" in the Ada.Task_Identification package.
References
----------
[1] Kristoffer Nyborg Gregertsen, Amund Skavhaug "Execution-time
control for interrupt handling". 14th International Real-Time Ada
Workshop, Portovenere, Italy, October 2009.
[2] Mario Aldea Rivas and Michael Gonzalez Harbour "Execution time
monitoring and interrupt handlers". 14th International Real-Time Ada
Workshop, Portovenere, Italy, October 2009.
!example
** TBD **
--!corrigendum D.14(29/2)
!ACATS test
Add an ACATS C-Test of this package.
!appendix
****************************************************************
Questions? Ask the ACAA Technical Agent