CVS difference for ais/ai-00307.txt

Differences between 1.1 and version 1.2
Log of other versions for file ais/ai-00307.txt

--- ais/ai-00307.txt	2002/08/29 03:33:21	1.1
+++ ais/ai-00307.txt	2003/01/23 00:49:34	1.2
@@ -1,4 +1,4 @@
-!standard 9.6 (00)                                   02-08-28  AI95-00307/01
+!standard 9.6 (00)                                   03-01-15  AI95-00307/02
 !standard D.9 (00)
 !class amendment 02-08-28
 !status work item 02-08-28
@@ -12,10 +12,18 @@
 
 Modern real-time scheduling policies require that applications have
 the ability to measure execution time of tasks, and to detect
-execution time overruns. Two mechanisms are proposed here to achieve
-these requirements. Prototype implementations exist for both. Their
-advantages and disadvantages are discussed, so that one of them can be
-chosen.
+execution time overruns. Two mechanisms were proposed to achieve these
+requirements. One was based on a library-level package, and the other
+one was integrated into the Ada 95 language by creating a new Time
+type that could be used in the languages time constructs such as the
+delay until statement or various forms of the select
+statement. Prototype implementations exist for both.
+
+After discussion by the ARG it was decided that the package
+mechanism was preferable, and a few changes were suggested. This
+document describes the package mechanism only, and includes the
+changes requested by the ARG. A discussion of these changes can be
+found at the end of the "Discussion" section.
 
 !problem
 
@@ -53,288 +61,9 @@
 
 !proposal
 
-Two proposals are presented here:
-  - Execution time fully integrated into the language
-  - Execution time provided as a library package
+Proposal: Execution time provided as a library package
+------------------------------------------------------
 
-A discussion of both is provided in the "discussion" section.
-
-Proposal A: Execution time fully integrated into the language
--------------------------------------------------------------
-
-The following additions are proposed for sections 9.6, D.X (new
-section in annex D), and D.9:
-
-Section 9.6: Delay Statements, Duration, and Time
--------------------------------------------------
-
-In paragraph #6, add a reference to the new section D.X (Execution
-Time).
-
-In paragraph #28, add a reference to the new section D.X (Execution
-Time).
-
-D.X Execution Time
-------------------
-
-This clause specifies an execution-time clock package.
-
-Static Semantics
-
-The following language-defined library package exists:
-
-with Ada.Task_Identification;
-package Ada.CPU_Time is
-   type Clock_ID is private;
-
-   type Time is private;
-   Time_First : constant Time;
-   Time_Last  : constant Time;
-   Time_Unit  : constant := implementation-defined-real-number;
-
-   type Time_Span is private;
-   Time_Span_First :  constant Time_Span;
-   Time_Span_Last  :  constant Time_Span;
-   Time_Span_Zero  :  constant Time_Span;
-   Time_Span_Unit  :  constant Time_Span;
-
-   Tick : constant Time_Span;
-
-   function CPU_Clock
-     (T : Ada.Task_Identification.Task_Id
-        := Ada.Task_Identification.Current_Task)
-     return Clock_Id;
-
-   function Clock (C : Clock_Id) return Time;
-   function Clock_Id_Of (T : Time) return Clock_Id;
-
-   function "+"  (Left : Time; Right : Time_Span) return Time;
-   function "+"  (Left : Time_Span; Right : Time) return Time;
-   function "-"  (Left : Time; Right : Time_Span) return Time;
-   function "-"  (Left : Time; Right : Time) return Time_Span;
-
-   function "<"  (Left, Right : Time) return Boolean;
-   function "<=" (Left, Right : Time) return Boolean;
-   function ">"  (Left, Right : Time) return Boolean;
-   function ">=" (Left, Right : Time) return Boolean;
-
-   function "+"  (Left, Right : Time_Span) return Time_Span;
-   function "-"  (Left, Right : Time_Span) return Time_Span;
-   function "-"  (Right : Time_Span) return Time_Span;
-   function "*"  (Left : Time_Span; Right : Integer) return Time_Span;
-   function "*"  (Left : Integer;   Right : Time_Span) return Time_Span;
-   function "/"  (Left, Right : Time_Span) return Integer;
-   function "/"  (Left : Time_Span; Right : Integer) return Time_Span;
-
-   function "abs" (Right : Time_Span) return Time_Span;
-
-   function "<"  (Left, Right : Time_Span) return Boolean;
-   function "<=" (Left, Right : Time_Span) return Boolean;
-   function ">"  (Left, Right : Time_Span) return Boolean;
-   function ">=" (Left, Right : Time_Span) return Boolean;
-
-   function To_Duration  (TS : Time_Span) return Duration;
-   function To_Time_Span (D : Duration)   return Time_Span;
-
-   function Nanoseconds  (NS : Integer) return Time_Span;
-   function Microseconds (US : Integer) return Time_Span;
-   function Milliseconds (MS : Integer) return Time_Span;
-
-   type Seconds_Count is range implementation-defined;
-
-   procedure Split
-      (T : Time; SC : out Seconds_Count; TS : out Time_Span);
-
-   function Time_Of
-      (SC : Seconds_Count; TS : Time_Span; C : Clock_Id) return Time;
-
-   Time_Error         : exception;
-   Incompatible_Times : exception;
-
-private
-   . . .  --  not specified by the language
-end Ada.CPU_Time;
-
-In this Annex, 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 behalf of it. The
-mechanism used to measure execution time is implementation
-defined. The implementation shall also define to whom will be charged
-the execution time that is consumed by interrupt handlers and run-time
-services on behalf of the system.
-
-The type Clock_ID represents the execution-time clock of a given Ada
-task.
-
-The type Time is a time type as defined by ARM95, section 9.6; values
-of this type may be used in a delay_until_statement. The set of the
-type Time corresponds one-to-one with an implementation-defined range
-of mathematical integers. Once initialized, a value of the type Time
-is associated with a given execution-Time Clock, and thus with a given
-task.
-
-The Time value I represents the half-open execution-time interval that
-starts with E+I*Time_Unit and is limited by E + (I+1)*Time_Unit, where
-Time_Unit is an implementation-defined real number and E is an
-unspecified origin point, which may be different for each task, but is
-the same for all the values of the type Time that are relative to a
-given task. The initial time may, for example, be set to zero at the
-task's activation time.
-
-Values of the type Time_Span represent length of execution time
-duration, and are not dependent upon any particular execution-time
-clock (or task). The set of values of this type corresponds one-to-one
-with an implementation-defined range of mathematical integers. The
-Time_Span value corresponding to the integer I represents the
-execution-time duration I*Time_Unit.
-
-Time_First and Time_Last are the smallest and largest values of the
-Time type, respectively. Similarly, Time_Span_First and Time_Span_Last
-are the smallest and largest values of the Time_Span type,
-respectively.
-
-Time_Unit is the smallest amount of execution time representable by
-the Time type; it is expressed in seconds. Time_Span_Unit is the
-difference between two succesive values of the Time type. It is also
-the smallest positive value of type Time_Span. Time_Unit and
-Time_Span_Unit represent the same execution time duration. A clock
-tick is an execution time interval during which the clock value (as
-observed by calling the Clock function) remains constant. Tick is the
-average length of such intervals.
-
-The function To_Duration converts the value TS to a value of type
-Duration. Similarly, the function To_Time_Span converts the value D to
-a value of type Time_Span. For both operations, the result is rounded
-to the nearest exactly representable value (away from zero if exactly
-halfway between two exactly representable values).
-
-To_Duration (Time_Span_Zero) returns 0.0 and To_Time_Span (0.0)
-returns Time_Span_Zero.
-
-The functions Nanoseconds, Microseconds, and Miliseconds convert the
-input parameter to a value of the type Time_Span. NS, US, and MS are
-interpreted as a number of nanoseconds, microseconds, and milliseconds
-respectively. The result is rounded to the nearest exactly
-representable value (away from zero if exactly halfway between two
-exactly representable values).
-
-The effects of the operators on Time and Time_Span are as for the
-operators defined for integer values.
-
-The function CPU_Clock returns the identifier of the execution-time
-clock associated to a given Ada task. By default, if no task is
-specified, the execution-time clock identifier associated to the
-caller task is returned.
-
-The function Clock returns the amount of execution time of the task
-associated with the execution-time clock specified by C.
-
-The funcion Clock_Id_Of returns the identifier of the execution-time
-clock associated to the Time parameter T.
-
-The effects of the Split and Time_Of operations are defined as
-follows, treating values of type Time, Time_Span, and Seconds_Count as
-mathematical integers. The effect of Split (T, SC, TS) is to set SC
-and TS to values such that T*Time_Unit = SC*1.0 + TS*Time_Unit, and
-0.0 <= TS*Time_Unit < 1.0. The value returned by Time_Of(SC,TS,C) is
-the value T of the execution-time clock C such that T*Time_Unit=SC*1.0
-+ TS*Time_Unit.
-
-The exception Time_Error is raised by the function Clock if the
-Clock_Id parameter is not valid. This exception is also raised by
-operators "+" and "-", and the function Clock_Id_Of, if an execution
-time parameter is not valid (for example, if it is not
-initialized). The exception Time_Error is also raised by a
-delay_until_statement if an invalid execution time parameter is used
-(see section D.8).
-
-The exception Incompatible_Times is raised by operator "-" if the
-execution time parameters correspond to different execution-time
-clocks.
-
-Implementation Requirements
-
-The range of Time values shall be sufficient to uniquely represent the
-range of execution times from the task start-up to 50 years of
-execution time later. Tick shall be no greater than 1 millisecond.
-
-Time_Span_First shall be no greater than -3600 seconds, and
-Time_Span_Last shall be no less than 3600 seconds.
-
-Documentation Requirements
-
-The implementation shall document the values of Time_First, Time_Last,
-Time_Span_First, Time_Span_Last, Time_Span_Unit, and Tick.
-
-The implementation shall document the properties of the underlying
-mechanism used to measure execution times, such as the range of
-values supported and any relevant aspects of the underlying hardware
-or operating system facilities used.
-
-Metrics
-
-The implementation shall document the following metrics:
-
-   - An upper bound on the execution-time duration of a clock
-     tick. This is a value D such that if t1 and t2 are any execution
-     times of a given task such that t1<t2 and Clock[t1]=Clock[t2]
-     then t2-t1 <= D.
-
-   - An upper bound on the size of a clock jump. A clock jump is the
-     difference between two successive distinct values of an execution
-     -time clock (as observed by calling the Clock function with the
-     same Clock_Id)
-
-   - An upper bound on the execution time of a call to the Clock
-     function, in processor clock cycles.
-
-   - Upper bounds on the execution times of the operators of the types
-     Time and Time_Span, in processor clock cycles.
-
-Implementation Permissions
-
-Implementations targeted to machines with word size smaller than 32
-bits need not support the full range and granularity of the Time and
-Time_Span types.
-
-
-Implementation Advice
-
-When appropriate, implementations should provide configuration
-mechanisms to change the value of Tick.
-
-
-D.9 Delay Accuracy
-------------------
-
-Dynamic Semantics
-
-Add the following after paragraph #4
-
-    The effect of the delay_statement for CPU_Time.Time is defined in
-    terms of CPU_Time.Clock:
-
-    If C is a value of the execution-time clock, Clk, of a given task
-    read after a (possibly different) task resumes execution following
-    a delay_until_statement with a CPU_Time.Time value T associated to
-    the Clk execution-time Clock), then C >= T.
-
-Add the following after paragraph #5:
-
-    A simple delay_until_statement with a CPU_Time.Time value T
-    associated to the execution-time clock of the calling task raises
-    the predefined exception Program_Error (there is a deadlock
-    condition because the calling task becomes blocked until its
-    execution time reaches the value T and its execution-time clock
-    can not advance because the calling task is blocked).
-
-    A delay_until_statement with an invalid CPU_Time.Time value (for
-    example, an uninitialized value) raises CPU_Time.Time_Error.
-
-
-Proposal B: Execution time provided as a library package
---------------------------------------------------------
-
 A new section D.X is proposed for Annex D:
 
 D.X Execution Time
@@ -349,20 +78,16 @@
 with Ada.Task_Identification;
 package Ada.Real_Time.Execution_Time is
 
-   type Clock_ID is private;
-
    type CPU_Time is private;
    CPU_Time_First : constant CPU_Time;
    CPU_Time_Last  : constant CPU_Time;
    CPU_Time_Unit  : constant := implementation-defined-real-number;
    CPU_Tick : constant Time_Span;
 
-   function CPU_Clock
+   function Clock
      (T : Ada.Task_Identification.Task_ID
-        := Ada.Task_Identification.Current_Task)
-      return Clock_ID;
-
-   function Clock(C : Clock_ID) return CPU_Time;
+          := Ada.Task_Identification.Current_Task)
+     return CPU_Time;
 
    function "+"  (Left : CPU_Time; Right : Time_Span) return CPU_Time;
    function "+"  (Left : Time_Span; Right : CPU_Time) return CPU_Time;
@@ -377,13 +102,13 @@
    procedure Split
       (T : CPU_Time; SC : out Seconds_Count; TS : out Time_Span);
 
-   function Time_Of
-      (SC : Seconds_Count; TS : Time_Span; C : Clock_Id) return Time;
+   function Time_Of (SC : Seconds_Count; TS : Time_Span) return CPU_Time;
 
-   protected type Timer is
-      procedure Initialize (C : Clock_ID);
-      procedure Finalize;
+   protected type Timer
+     (T : access Ada.Task_Identification.Task_ID)
+   is
       procedure Arm (Interval : Time_Span);
+      procedure Arm (Abs_Time : CPU_Time);
       procedure Disarm;
       entry Time_Exceeded;
       function Time_Was_Exceeded return Boolean;
@@ -408,20 +133,16 @@
 the execution time that is consumed by interrupt handlers and run-time
 services on behalf of the system.
 
-The type Clock_ID represents the execution-time clock of a given Ada
-task.
-
 The type CPU_Time represents the execution time of a task. The set of
 the type CPU_Time corresponds one-to-one with an implementation-defined
 range of mathematical integers.
 
 The CPU_Time value I represents the half-open execution-time interval
-that starts with E+I*CPU_Time_Unit and is limited by E +
+that starts with I*CPU_Time_Unit and is limited by
 (I+1)*CPU_Time_Unit, where CPU_Time_Unit is an implementation-defined
-real number and E is an unspecified origin point, which may be
-different for each task, but is the same for all the values of the
-type CPU_Time that are relative to a given task. The initial time may,
-for example, be set to zero at the task's activation time.
+real number. For each task, the execution time value is set to zero at
+some unspecified point between the task creation and the end of the
+task's activation.
 
 CPU_Time_First and CPU_Time_Last are the smallest and largest values
 of the Time type, respectively.
@@ -435,48 +156,52 @@
 The effects of the operators on Time and Time_Span are as for the
 operators defined for integer values.
 
-The function CPU_Clock returns the identifier of the execution-time
-clock associated to a given Ada task. By default, if no task is
-specified, the execution-time clock identifier associated to the
-caller task is returned.
-
 The function Clock returns the amount of execution time of the task
-associated with the execution-time clock specified by C.
+associated with the execution-time clock of the task represented by T.
 
 The effects of the Split and Time_Of operations are defined as
 follows, treating values of type CPU_Time, Time_Span, and
 Seconds_Count as mathematical integers. The effect of Split (T, SC,
 TS) is to set SC and TS to values such that T*CPU_Time_Unit = SC*1.0 +
 TS*CPU_Time_Unit, and 0.0 <= TS*CPU_Time_Unit < 1.0. The value
-returned by Time_Of(SC,TS,C) is the value T of the execution-time
-clock C such that T*CPU_Time_Unit=SC*1.0 + TS*CPU_Time_Unit.
+returned by Time_Of(SC,TS) is the execution-time value T such that
+T*CPU_Time_Unit=SC*1.0 + TS*CPU_Time_Unit.
 
 Package Execution_Time contains a protected object type called Timer,
 which represents a software object that is capable of detecting
-execution time overruns. This protected object type has visible
-operations for the application tasks to initialize or finalize a
-CPU-time timer, to arm or disarm a timer, and to determine whether a
-timer has expired or not (Time_Was_Exceeded). In addition, Timer has
-an entry (Time_Exceeded) that can be used by application tasks to
-block until an execution time overrun is detected, or as an event that
-triggers the abortion of the instructions of a select statement with
-an abortable part.
-
-The Timer.Initialize protected procedure allocates and initializes the
-resources required to operate a CPU-time timer based on the execution
-time clock specified by C. If the operation would exceed the limit of
-the maximum number of timers in the system, the Storage_Error
-exception is raised. The timer is initialized in the disarmed state.
-
-The Timer.Finalize protected procedure deallocates the system
-resources used by the timer. No other calls to the timer operations of
-the associated timer may be made, except another Initialize
-call. Constraint_Error will be raised if such attempt is detected.
-
-The Timer.Arm protected procedure loads the associated timer with the
-value specified by Interval and sets it to the armed state. In this state
-the timer counts execution time and, when the CPU clock associated
-with the timer measures the passage of Interval, it is said to have
+execution time overruns. Each timer is attached to a specific execution
+time clock, which is the clock of the task specified by the access
+discriminant T. This protected object type has visible operations for
+the application tasks to arm or disarm a timer, and to determine
+whether a timer has expired or not (Time_Was_Exceeded). In addition,
+Timer has an entry (Time_Exceeded) that can be used by application
+tasks to block until an execution time overrun is detected, or as an
+event that triggers the abortion of the instructions of a select
+statement with an abortable part.
+
+When a Timer is created, the resources required to operate a CPU-time
+timer based on the associated execution-time clock shall be allocated
+and initialized. If this operation would exceed the limit of the
+maximum number of timers in the system, the Storage_Error exception is
+raised. The timer is initialized in the disarmed state.
+
+When a Timer is destroyed, the system resources used by the timer
+shall be deallocated.
+
+The Timer.Arm protected procedure that takes a Time_Span parameter
+loads the associated timer with the relative value specified by
+Interval and sets it to the armed state. In this state the timer
+counts execution time and, when the CPU clock associated with the
+timer measures the passage of Interval, it is said to have expired. If
+the timer was already armed, it is rearmed.
+
+The Timer.Arm protected procedure that takes a CPU_Time parameter
+loads the associated timer with the absolute value specified by
+Abs_Time and sets it to the armed state. In this state the timer
+counts execution time and, when the CPU clock associated with the
+timer reaches the value Abs_Time, it is said to have expired. If the
+value of Abs_Time had already been reached by the clock at the time of
+the call, the timer is set to the armed state and is said to have
 expired. If the timer was already armed, it is rearmed.
 
 The Timer.Disarm protected procedure sets the timer to the disarmed
@@ -530,7 +255,7 @@
    - An upper bound on the size of a clock jump. A clock jump is the
      difference between two successive distinct values of an execution
      -time clock (as observed by calling the Clock function with the
-     same Clock_Id)
+     same Task_Id)
 
    - An upper bound on the execution time of a call to the Clock
      function, in processor clock cycles.
@@ -592,24 +317,17 @@
 have this functionality supported in a homogeneous way for all the
 implementations that choose to support it.
 
-Two possible implementations
-----------------------------
+The package solution
+--------------------
 
 One important requirement of any execution-time functionality that may
 be incorporated into the Ada language is that it is implementable on
-top of the POSIX execution-time clocks and timers. In this document
-two different ways of providing the execution-time monitoring
-functionality are proposed, that satisfy the above requirement.
-
-The first proposal integrates execution time clocks fully into the Ada
-Language, by creating a new Time type that can be used with all the
-forms of the delay until statement. A new package defining this new
-type is proposed, which includes operations to handle and manage
-values of that type. The price to pay for this integrated approach is
-that modifications are required to the compiler and to the run-time
-system.
+top of the POSIX execution-time clocks and timers. Two different ways
+of providing the execution-time monitoring functionality were proposed,
+that satisfied the above requirement. The ARG chose the package
+solution because it does not require changes to the compiler.
 
-The second proposal defines a new package that includes all the
+The package proposal defines a new package that includes all the
 operations required to access the execution-time monitoring
 functionality. Some of these operations belong to a protected object
 type that represents execution-time timers. This approach does not
@@ -620,19 +338,21 @@
 
 Prototype implementations
 -------------------------
-
-Prototype implementations have been developed for both proposals,
-using the MaRTE operating system that provides a POSIX.13 interface
-and includes execution-time clocks and timers.
-
-The implementation of proposal A, with execution-time functionality
-integrated into the language, requires small modifications to
-the compiler and to the run-time, which are described in document [1].
-The modifications were implemented in a short period of time and
-should not represent a large effort to current compiler implementors.
 
-The implementation of proposal B is very simple, because it does not
-require modifications to the compiler nor to the runtime system.
+Prototype implementations were developed for both of the initial
+proposals, using the MaRTE operating system that provides a POSIX.13
+interface and includes execution-time clocks and timers.
+
+The implementation of the proposal with the execution-time
+functionality integrated into the language requires small
+modifications to the compiler and to the run-time, which are described
+in document [1].  The modifications were implemented in a short period
+of time and should not represent a large effort to current compiler
+implementors.
+
+The implementation of the package-based proposal is very simple,
+because it does not require modifications to the compiler nor to the
+runtime system.
 
 Implementations on bare machines or systems without POSIX
 execution-time clocks and timers would be a bit more complex because
@@ -648,78 +368,136 @@
 Conclusion
 ----------
 
-The IRTAW group recommends the first approach, with execution-time
-functionality integrated in the Ada Language, because it provides a
-simpler model to programmers. However, the group feels that there is a
-strong need to have the execution-time functionality in Ada, so if the
-second proposal, with a library implementation, has more probability
-of success, the group would also recommend its adoption.
+The IRTAW group feels that there is a strong need to have the
+execution-time functionality in Ada.
 
 The IRTAW group is not opposed to having this new functionality
 defined as optional in the Real-Time Systems Annex.
 
-!examples
+Discussion of changes requested by the ARG
+------------------------------------------
 
-Example 1: Stopped task
+Clock_Id
+--------
+A value of the Clock_Id type was used in the first proposal to
+identify each execution-time clock. The ARG questioned its need and
+requested that a Task_Id be used for identifying the execution-time
+clock of a given task. The origin of the Clock_Id type in the original
+proposal was the POSIX API, but it is true that it is not necessary in
+the Ada implementation. In a run-time implementation the (internal)
+clock id would be part of the task control block, and fully
+accessible. In a library-level implementation the (internal) clock_id
+could be obtained via a task attribute, using package
+Ada.Task_Attributes. Although in this case there is some performance
+penalty due to the task attribute, it is implementable.
+
+Consequently the Clock_Id has been removed from this proposal,
+although it is requested that the performance issue is discussed by
+the ARG.
+
+Time_Of
+-------
+
+The ARG pointed out that Time_Of should return a CPU_Time. This was a
+typo in the previous proposal; it is now fixed.
+
+The ARG also suggests that Time_Of does *not* take a Task_Id
+parameter. The reason for having it was that an implementation could
+choose to have the Task_Id as part of an Execution_Time value, in case
+we wished to disallow operations between CPU_Time values of different
+tasks. So if CPU_Time values of different tasks are not comparable and
+we create an exception for disallowing operations among them, we
+should keep the Task_Id parameter; if not, we can delete it. In the
+present proposal it has been deleted.
+
+Initial value of the clock
+---------------------------
+
+The initial proposal left the initial value of the execution time
+clock of each task unspecified. The ARG requested that the value
+be forced to start at zero. Although in some implementations this
+requirement may imply setting the CPU-Time clock, there is value in
+being able to determine a task's absolute execution time, and
+therefore the proposal has been changed as requested.
+
+Because the execution time value may be set to zero during the task's
+activation, the requirement is that the value is set to zero at
+some unspecified point between the task creation and the end of the
+task's activation.
+
+Initialize and Finalize
 -----------------------
 
-The following is an example of a periodic task that limits its own execution
-time to some predefined amount called WCET (worst-case execution
-time). If an execution time overrun is detected, the task aborts the
-remainder of its execution, until the next period.
+The initial proposal had two protected operations inside the Timer:
+Initialize and Finalize. Initialize took a parameter that identified
+the execution time clock to be used. The ARG proposed suppressing
+these operations, and moving the parameter to an access discriminant
+of the protected type or a parameter of the Arm operation, with a
+preference for the later solution.
+
+The Initialize and Finalize operations can be removed but the
+implication is that in a library implementation of the package on top
+of the POSIX execution-time services, the protected type will have to
+include a component derived from Ada.Finalize.Controlled to ensure
+that appropriate initialization and finalization are made. I have no
+experience with using controlled types, so I cannot comment on whether
+this is a good idea or not. While the issue is discussed, the
+Initialize and Finalize operations have been removed from the
+interface.
+
+Given that it is forecasted that most implementations of package
+Ada.Real_Time.Execution_Time will be made on top of the POSIX
+execution-time services, if the Initialize operation is removed, the
+parameter that identifies the clock should be an access discriminant,
+and *not* a parameter to Arm. The reason is that in the POSIX API
+Execution-Time timers are system objects that require allocation and
+deallocation of resources, and therefore it is not reasonable to
+allocate these resources each time a Timer is being used. The common
+use is to allocate the resources once, and then use the timer many
+times. It is also necessary to take into account that an application
+may want to establish more than one timer per task, and therefore the
+resources cannot be preallocated: for example, a system may be
+implementing a sporadic server for a given task using a CPU-Time
+Timer, but that task itself may use another timer to finish some
+particular any-time algorithm that it may be executing.
+
+In summary, the Initialize and Finalize operations have been deleted
+(with a request that the ARG discusses the issue of using a controlled
+type), and the identification of the task is made as an access
+discriminant.
 
-Example 1 implemented with proposal A:
---------------------------------------
+Relative and absolute Arm
+-------------------------
 
-with Ada.Real_Time, Ada.CPU_Time;
-use Ada;
-use type Ada.CPU_Time.Time;
-use type Ada.Real_Time.Time;
+The initial proposal only had a relative ARM operation. The ARG
+suggested adding also an absolute version. The current proposal
+includes the suggested operation.
 
-...
 
-   task body Periodic_Stopped is
-      C : CPU_Time.Clock_ID := CPU_Time.CPU_Clock;
-         -- My execution-time clock identifier
-      Overrun : CPU_Time.Time;
-      Next_Start : Real_Time.Time:=Real_Time.Clock;
-      WCET : constant Duration:=1.0E-3;
-      Period : constant Duration:=1.0E-2;
-   begin
-      loop
-         Overrun := CPU_Time.Clock (C) + CPU_Time.To_Time_Span (WCET);
-         select
-            delay until Overrun; -- Execution-time-clock-based delay
-            Handle_the_error;
-         then abort
-            Do_useful_work;
-         end select;
-         Next_Start := Next_Start + Real_Time.To_Time_Span(Period);
-         delay until Next_Start; -- Real-time-clock-based delay
-      end loop;
-   end Periodic_Stopped;
-...
+!examples
 
+Example 1: Stopped task
+-----------------------
 
-Example 1 implemented with proposal B:
-------------------------------------
+The following is an example of a periodic task that limits its own execution
+time to some predefined amount called WCET (worst-case execution
+time). If an execution time overrun is detected, the task aborts the
+remainder of its execution, until the next period.
 
-with Ada.Real_Time, Ada.Real_Time.Execution_Time;
+with Ada.Real_Time, Ada.Real_Time.Execution_Time, Ada.Task_Identification;
 use Ada;
 use type Ada.Real_Time.Time;
 
 ...
 
    task body Periodic_Stopped is
-      C : Real_Time.Execution_Time.Clock_ID :=
-         Real_Time.Execution_Time.CPU_Clock;
-         -- My execution-time clock identifier
-      The_Timer : Real_Time.Execution_Time.Timer;
+      My_Id : aliased Task_Identification.Task_Id:=
+         Periodic_Stopped'Identity;
+      The_Timer : Ada_Real_Time_Execution_Time.Timer(My_Id'Access);
       Next_Start : Real_Time.Time:=Real_Time.Clock;
       WCET : constant Duration:=1.0E-3;
       Period : constant Duration:=1.0E-2;
    begin
-      The_Timer.Initialize(C);
       loop
          The_Timer.Arm(Real_Time.To_Time_Span(WCET));
          select
@@ -750,41 +528,8 @@
 completes the work before the instant of the priority change then it
 aborts the Supervisor task.
 
-Example 2 implemented with proposal A
--------------------------------------
-
-with Ada.CPU_Time, Ada.Dynamic_Priorities, System;
-use Ada;
-use type CPU_Time.Time;
-...
-
-   task body Worker is
-      task Supervisor is
-         pragma Priority(System.Priority'Last);
-      end Supervisor;
-
-      task body Supervisor is
-         C : CPU_Time.Clock_ID := CPU_Time.CPU_Clock (Worker'Identity);
-         WCET : constant Duration:=1.0E-3;
-         Overrun : CPU_Time.Time :=
-            CPU_Time.Clock (C) + CPU_Time.To_Time_Span (WCET);
-         Low_Prio : System.Priority:=System.Priority'First;
-      begin
-         delay until Overrun; -- CPU-time-based delay
-         Dynamic_Priorities.Set_Priority(Low_Prio,Worker'Identity);
-      end Supervisor;
-   begin
-      Do_useful_work;
-      abort Supervisor;
-   end Worker;
-
-...
-
-Example 2 implemented with proposal B
--------------------------------------
-
 with Ada.Real_Time,Ada.Real_Time.Execution_Time,
-   Ada.Dynamic_Priorities, System;
+   Ada.Dynamic_Priorities, System, Ada.Task_Identification;
 use Ada;
 
 ...
@@ -795,13 +540,11 @@
       end Supervisor;
 
       task body Supervisor is
-         C : Real_Time.Execution_Time.Clock_ID :=
-            Real_Time.Execution_Time.CPU_Clock (Worker'Identity);
          WCET : constant Duration:=1.0E-3;
-         The_Timer : Real_Time.Execution_Time.Timer;
+         My_Id : aliased Task_Identification.Task_Id:=Supervisor'Identity;
+         The_Timer : Ada_Real_Time_Execution_Time.Timer(My_Id'Access);
          Low_Prio : System.Priority:=System.Priority'First;
       begin
-         The_Timer.Initialize(C);
          The_Timer.Arm(Real_Time.To_Time_Span(WCET));
          The_Timer.Time_Exceeded; -- wait for timer overrun
          Dynamic_Priorities.Set_Priority(Low_Prio,Worker'Identity);
@@ -813,24 +556,20 @@
 
 ...
 
-Example 3. Justification of the Clock_Id_Of function
-----------------------------------------------------
+Discussion on the names used
+----------------------------
 
-The function Clock_id_Of included in proposal A is not strictly
-necessary and is only included for convenience. The clock information
-is inside the Time type anyway, so the function can be used for
-example to check the validity of an operation without getting the
-exception if two times are based upon different clocks:
-
-   if Clock_Id_Of(T1)=Clock_Id_Of(T2) then
-       TS:=T2-T1;
-   else
-       -- handle the error (T1 and T2 incompatible)
-   end if;
-
-If Clock_Id_Of was not available, then the only way to find out if two
-time types are compatible is via the Incompatible_Times exception, which
-in some environments may not be convenient.
+One reviewer commented that the names are perhaps not quite
+appropriate. For many users, time exceeded will be an error,
+but for others (undertaking imprecise computation etc) it
+is not an error but part of the algorithm (e.g. give this
+routine X amount of computation time). This reviewer suggests
+different names:
+
+Timer_Expired instead of Time_Exceeded
+Timer_Has_Expired instead of Time_Was_Exceeded
+Time_To_Expiration instead of Time_Remaining
+Timer_Disarmed instead of Time_Error
 
 !appendix
 

Questions? Ask the ACAA Technical Agent