CVS difference for ais/ai-00307.txt

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

--- ais/ai-00307.txt	2004/07/27 23:00:57	1.12
+++ ais/ai-00307.txt	2004/11/14 06:37:11	1.13
@@ -1,4 +1,4 @@
-!standard D.14 (00)                                  04-06-25  AI95-00307/09
+!standard D.14 (00)                                  04-11-11  AI95-00307/10
 !standard D.14.1 (00)
 !class amendment 02-08-28
 !status Amendment 200Y 04-06-24
@@ -15,7 +15,7 @@
 !summary
 
 Modern real-time scheduling policies require that applications have
-the ability to the measure execution time of tasks, and to detect
+the ability to measure the execution time of tasks, and to detect
 execution time overruns. This functionality is provided by a new
 package that defines execution time clocks and a child of this package
 which provides timers.
@@ -27,16 +27,16 @@
 execution time of each task. Measurement is always very
 difficult, because, with effects like cache misses, pipelined and
 superscalar processor architectures, etc., the execution time is
-highly unpredictable. There are models that allow calculation of
+highly unpredictable. There are models that allow the calculation of
 worst-case execution time (WCET) for some architectures, but they are
 generally very complex and not widely available for all architectures.
 A language defined means of measuring execution time is desirable.
 
 In hard real-time systems it is essential to monitor the execution
 times of all tasks and detect situations in which the estimated WCET
-is exceeded. This detection was usually available in systems scheduled
-with cyclic executives, because the periodic nature of its cycle
-allowed checking that all initiated work had been completed at each
+is exceeded. This detection is usually available in systems scheduled
+with cyclic executives, because the periodic nature of a cycle
+allows checking that all initiated work has been completed at each
 cycle. In event-driven concurrent systems the same capability should
 be available, and this can be accomplished with execution time clocks
 and timers.
@@ -47,7 +47,7 @@
 example, sporadic servers in fixed priority systems, or the constant
 bandwidth server in EDF-scheduled systems). Support for execution time
 clocks and timers would ease implementation of such flexible
-scheduling algorithms in Ada 95.
+scheduling algorithms.
 
 The Real-Time extensions to POSIX have recently incorporated support for
 execution time monitoring. Real-Time POSIX supports execution time clocks and
@@ -106,7 +106,7 @@
    function ">=" (Left, Right : CPU_Time) return Boolean;
 
    procedure Split
-      (T : CPU_Time; SC : out Seconds_Count; TS : out Time_Span);
+      (T : in CPU_Time; SC : out Seconds_Count; TS : out Time_Span);
 
    function Time_Of (SC : Seconds_Count; TS : Time_Span) return CPU_Time;
 
@@ -130,11 +130,11 @@
 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. For each task, the execution time value is set to zero at
-some unspecified point between the task creation and the start of the
-task's activation.
+some unspecified point between the creation of the task and the start
+of the activation of the task.
 
 CPU_Time_First and CPU_Time_Last are the smallest and largest values
-of the Time type, respectively.
+of the CPU_Time type, respectively.
 
 Dynamic Semantics
 
@@ -147,8 +147,7 @@
 The effects of the operators on CPU_Time and Time_Span are as for the
 operators defined for integer types.
 
-The function Clock returns the amount of execution time of the task
-associated with the execution-time clock of the task represented by T.
+The function Clock returns the current execution time of the task T.
 
 The effects of the Split and Time_Of operations are defined as
 follows, treating values of type CPU_Time, Time_Span, and
@@ -238,81 +237,76 @@
    type Timer (T : access Ada.Task_Identification.Task_ID) is
       limited private;
 
-   type Handler is not null access protected procedure (TM : in out Timer);
+   type Timer_Handler is access protected procedure (TM : in out Timer);
 
    Min_Handler_Ceiling : constant System.Any_Priority :=
     implementation-defined;
 
-   procedure Arm (TM: in out Timer; Interval : Time_Span; H : Handler);
-   procedure Arm (TM: in out Timer; Abs_Time : CPU_Time;  H : Handler);
-   procedure Disarm(TM : in out Timer);
+   procedure Set_Handler(TM: in out Timer; In_Time : in Time_Span;
+                          Handler : in Timer_Handler);
+   procedure Set_Handler(TM: in out Timer; At_Time : in CPU_Time;
+                          Handler : in Timer_Handler);
+   function Current_Handler(TM: Timer) return Timer_Handler;
+   procedure Cancel_Handler(TM : in out Timer;
+                            Cancelled : out Boolean);
 
-   function Timer_Has_Expired(TM : Timer) return Boolean;
    function Time_Remaining(TM : Timer) return Time_Span;
 
-   Timer_Error : @b<exception>;
-   Timer_Resource_Error : @b<exception>;
+   Timer_Resource_Error : exception;
 
 private
    ... --  not specified by the language
 end Ada.Execution_Time.Timers;
 
-The type Timer needs finalization (see 7.6).
+The type Timer represents an execution-time event for a single task and is
+capable of detecting execution time overruns. The access discriminant T
+identifies the task concerned. The type Timer needs finalization (see 7.6).
+
+An object of type Timer is said to be *set* if it is associated with a
+(non-null) Timer_Handler and *cleared* otherwise. All Timer objects are
+initially cleared. The Timer_Handler identifies a protected procedure to
+be executed by the implementation when the timer expires.
 
 Dynamic Semantics
+
+When a Timer object is created, or upon the first call of a Set_Handler
+procedure with the timer as parameter, the resources required to operate a
+CPU-time timer based on the associated execution-time clock will be
+allocated and initialized. If this operation would exceed the limit of the
+maximum number of timers in the system, Timer_Resource_Error is raised.
+
+A call of a procedure Set_Handler associates a Timer_Handler with a Timer.
+The first procedure Set_Handler loads the timer with an interval specified
+by the Time_Span parameter. In this state the timer counts execution time
+and, when the CPU clock associated with the timer measures the passage of
+In_Time, it is said to have expired. The second procedure Set_Handler
+loads the timer with the absolute value specified by At_Time. In this
+state the timer monitors execution time and, when the CPU clock associated
+with the timer reaches the value At_Time, it is said to have expired. If
+the value of At_Time had already been reached by the clock at the time of
+the call, the timer is said to have expired.
+
+A call of a procedure Set_Handler for a Timer that is already set replaces
+the handler and the time of execution and the Timer remains set. A call
+with a null value of Handler clears the Timer.
+
+When a Timer expires, the associated protected procedure Timer_Handler is
+executed with a parameter equal to the Timer. The initial action of the
+execution of the Timer_Handler is to clear the event.
+
+The procedure Cancel_Handler clears the timer if it was set. Cancelled is
+assigned True if the timer was set prior to it being cleared, otherwise it
+is assigned False.
+
+The function Current_Handler returns the Timer_Handler associated with the
+timer if the timer is set, otherwise it returns null.
+
+The function Time_Remaining returns the CPU time interval that remains
+until the timer will expire if the timer is set, otherwise it returns
+Time_Span_Zero.
 
-Type Timer represents a software object that is capable of detecting
-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 type has operations for the
-application tasks to arm or disarm a timer, and to determine whether a timer
-has expired or not (Timer_Has_Expired). In addition, when arming the timer, an
-access to a protected procedure (type Handler) is passed. This procedure
-will be called by the implementation when the timer expires.
-
-The constant Min_Handler_Ceiling is the priority value that will insure that
-no ceiling violation will occur when a handler is executed.
-
-When a Timer object is created, or upon the first call to one of its Arm
-procedures, the resources required to operate a CPU-time timer based on
-the associated execution-time clock will be allocated and initialized.
-The timer is initialized in the disarmed state. If this operation would
-exceed the limit of the maximum number of timers in the system, the
-Timer_Resource_Error exception is raised.
-
-The Arm 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 Arm 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 monitors 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.
-
-When a Timer expires, the protected procedure Handler is invoked by the system
-with a parameter equal to the Timer.
-
-The Disarm procedure sets the timer to the disarmed state. In this
-state the timer will not expire.
-
-The Time_Has_Expired function returns True if the timer is in the
-armed state and has expired, and returns False if the timer is in the
-armed state but has not yet expired. If the timer is in the disarmed
-state, the Timer_Error exception is raised.
-
-The Time_Remaining function returns, when the timer is in the armed state, the
-CPU time interval that remains until the timer will expire, or a value
-representing zero if the timer has expired. If the timer is in the disarmed
-state, the Timer_Error exception is raised.
-
-The Timer_Error exception is raised by Timer_Has_Expired, or
-Time_Remaining if an attempt is made to use a timer that is in the
-disarmed state.
+The constant Min_Handler_Ceiling is the priority value that will ensure
+that no ceiling violation will occur when a handler is executed.
 
 For all the operations and types defined in this package, Tasking_Error
 is raised if the task identified by T has terminated. Program_Error
@@ -322,7 +316,17 @@
 
 For a given Timer object, the implementation shall perform the operations
 declared in this package atomically with respect to any of these
-operations on the same Timer object.
+operations on the same Timer object. The replacement of a handler by a
+call of Set_Handler, shall be performed atomically with respect to the
+execution of the Timer_Handler.
+
+AARM note:
+This prevents various race conditions. In particular it ensures that if
+ an event occurs when Set_Handler is changing the handler then either
+the new or old handler is executed in response to the appropriate event.
+It is never possible for a new handler to be executed in response to
+an old event.
+end AARM note
 
 When an object of type Timer is finalized, the system resources used by
 the timer shall be deallocated.
@@ -330,8 +334,11 @@
 Implementation Permissions
 
 Implementations may limit the number of timers that can be defined for
-each task. If this limit is exceeded the Timer_Resource_Error exception
-is raised.
+each task. If this limit is exceeded then Timer_Resource_Error is raised.
+
+Notes
+
+A Timer_Handler can be associated with several Timer objects.
 
 !discussion
 
@@ -352,7 +359,7 @@
 has required a restructuring of the earlier solution. The consequence
 is that the Timer is no longer a protected object. Timer expirations
 are notified by the system by calling a protected procedure that is
-passed to it by an access parameter in the Timer operations.
+passed to it by a parameter in the Timer operations.
 
 A prototype implementations was developed for the initial proposal, using the
 MaRTE operating system that provides a POSIX.13 interface and includes
@@ -394,7 +401,7 @@
 Initialize and Finalize. Initialize took a parameter that identified
 the execution time clock to be used. These operations appeared unnecessary
 to reviewers; the parameter could be moved to an access discriminant
-of the protected type or a parameter of the Arm operation. The
+of the protected type or a parameter of the Set_Handler operation. The
 reviewers preferred the later solution.
 
 Without these operations, a library implementation of the package on top
@@ -405,19 +412,9 @@
 some "magic", but most implementations will not need extra support. In
 either case, the overhead is small and bounded.
 
-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, 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.
+An earlier version of the timer had procedures Arm and Disarm and three
+states, armed, armed but expired, and disarmed. It was changed to bring it
+into line with the style of AI-297 on real-time timers.
 
 
 !example
@@ -468,7 +465,7 @@
       Period : constant Duration:=1.0E-2;
    begin
       loop
-         Ada.Execution_Time.Timers.Arm
+         Ada.Execution_Time.Timers.Set_Handler
             (The_Timer, Real_Time.To_Time_Span(WCET),
              Control.Budget_Expired'Access);
          select
@@ -477,7 +474,7 @@
          then abort
             null; -- Do_useful_work;
          end select;
-         Ada.Execution_Time.Timers.Disarm(The_Timer);
+         Ada.Execution_Time.Timers.Cancel_Handler(The_Timer);
          Next_Start := Next_Start + Real_Time.To_Time_Span(Period);
          delay until Next_Start;
       end loop;
@@ -509,7 +506,7 @@
    protected Control is
      entry Wait_Budget_Expiry;
      procedure Budget_Expired(T : in out Ada.Execution_Time.Timers.Timer);
-     pragma Priority(Ada.Execution_Time.Timers.Min_Announce_Ceiling);
+     pragma Priority(Ada.Execution_Time.Timers.Min_Handler_Ceiling);
    private
      Expired : Boolean := False;
    end Control;
@@ -539,7 +536,7 @@
          The_Timer : Ada.Execution_Time.Timers.Timer(My_Id'Access);
          Low_Prio : System.Priority:=System.Priority'First;
       begin
-         Ada.Execution_Time.Timers.Arm
+         Ada.Execution_Time.Timers.Set_Handler
            (The_Timer, Real_Time.To_Time_Span(WCET),
             Control.Budget_Expired'Access);
          Control.Wait_Budget_Expiry; -- wait for timer overrun
@@ -588,7 +585,7 @@
    @b<function> "@>=" (Left, Right : CPU_Time) @b<return> Boolean;
 
    @b<procedure> Split
-      (T : CPU_Time; SC : @b<out> Seconds_Count; TS : @b<out> Time_Span);
+     (T : @b<in> CPU_Time; SC : @b<out> Seconds_Count; TS : @b<out> Time_Span);
 
    @b<function> Time_Of (SC : Seconds_Count; TS : Time_Span) @b<return> CPU_Time;
 
@@ -612,11 +609,11 @@
 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. For each task, the execution time value is set to zero at
-some unspecified point between the task creation and the start of the
-task's activation.
+some unspecified point between the creation of the task and the start
+of the activation of the task.
 
 CPU_Time_First and CPU_Time_Last are the smallest and largest values
-of the Time type, respectively.
+of the CPU_Time type, respectively.
 
 @i<@s8<Dynamic Semantics>>
 
@@ -629,8 +626,7 @@
 The effects of the operators on CPU_Time and Time_Span are as for the
 operators defined for integer types.
 
-The function Clock returns the amount of execution time of the task
-associated with the execution-time clock of the task represented by T.
+The function Clock returns the current execution time of the task T.
 
 The effects of the Split and Time_Of operations are defined as
 follows, treating values of type CPU_Time, Time_Span, and
@@ -716,84 +712,79 @@
 @b<with> Ada.Real_Time; @b<use> Ada.Real_Time;
 @b<package> Ada.Execution_Time.Timers @b<is>
 
-   @b<type> Timer (T : access Ada.Task_Identification.Task_ID) @b<is>
+   @b<type> Timer (T : @b<access> Ada.Task_Identification.Task_ID) @b<is>
       @b<limited private>;
 
-   @b<type> Handler @b<is not null access protected procedure> (TM : @b<in out> Timer);
+   @b<type> Timer_Handler @b<is access protected procedure> (TM : @b<in out> Timer);
 
    Min_Handler_Ceiling : @b<constant> System.Any_Priority :=
     @ft<@i<implementation-defined>>;
 
-   @b<procedure> Arm (TM: @b<in out> Timer; Interval : Time_Span; H : Handler);
-   @b<procedure> Arm (TM: @b<in out> Timer; Abs_Time : CPU_Time;  H : Handler);
-   @b<procedure> Disarm(TM : @b<in out> Timer);
+   @b<procedure> Set_Handler(TM: @b<in out> Timer; In_Time : @b<in> Time_Span;
+                       Handler : @b<in> Timer_Handler);
+   @b<procedure> Set_Handler(TM: @b<in out> Timer; At_Time : @b<in> CPU_Time;
+                       Handler : @b<in> Timer_Handler);
+   @b<function> Current_Handler(TM: Timer) @b<return> Timer_Handler;
+   @b<procedure> Cancel_Handler(TM : @b<in out> Timer;
+                                 Cancelled : @b<in out> Boolean);
 
-   @b<function> Timer_Has_Expired(TM : Timer) @b<return> Boolean;
    @b<function> Time_Remaining(TM : Timer) @b<return> Time_Span;
 
-   Timer_Error : @b<exception>;
    Timer_Resource_Error : @b<exception>;
 
 @b<private>
    ... --  not specified by the language
 @b<end> Ada.Execution_Time.Timers;>
 
-The type Timer needs finalization (see 7.6).
+The type Timer represents an execution-time event for a single task and is
+capable of detecting execution time overruns. The access discriminant T
+identifies the task concerned. The type Timer needs finalization (see 7.6).
+
+An object of type Timer is said to be set if it is associated with a
+(non-null) Timer_Handler and cleared otherwise. All Timer objects are
+initially cleared. The Timer_Handler identifies a protected procedure to
+be executed by the implementation when the timer expires.
 
 @i<@s8<Dynamic Semantics>>
+
+When a Timer object is created, or upon the first call of a Set_Handler
+procedure with the timer as parameter, the resources required to operate a
+CPU-time timer based on the associated execution-time clock will be
+allocated and initialized. If this operation would exceed the limit of the
+maximum number of timers in the system, Timer_Resource_Error is raised.
+
+A call of a procedure Set_Handler associates a Timer_Handler with a Timer.
+The first procedure Set_Handler loads the timer with an interval specified
+by the Time_Span parameter. In this state the timer counts execution time
+and, when the CPU clock associated with the timer measures the passage of
+In_Time, it is said to have expired. The second procedure Set_Handler
+loads the timer with the absolute value specified by At_Time. In this
+state the timer monitors execution time and, when the CPU clock associated
+with the timer reaches the value At_Time, it is said to have expired. If
+the value of At_Time had already been reached by the clock at the time of
+the call, the timer is said to have expired.
+
+A call of a procedure Set_Handler for a Timer that is already set replaces
+the handler and the time of execution and the Timer remains set. A call
+with a null value of Handler clears the Timer.
+
+When a Timer expires, the associated protected procedure Timer_Handler is
+executed with a parameter equal to the Timer. The initial action of the
+execution of the Timer_Handler is to clear the event.
+
+The procedure Cancel_Handler clears the timer if it was set. Cancelled is
+assigned True if the timer was set prior to it being cleared, otherwise it
+is assigned False.
+
+The function Current_Handler returns the Timer_Handler associated with the
+timer if the timer is set, otherwise it returns null.
+
+The function Time_Remaining returns the CPU time interval that remains
+until the timer will expire if the timer is set, otherwise it returns
+Time_Span_Zero.
 
-Type Timer represents a software object that is capable of detecting
-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 type has operations for the
-application tasks to arm or disarm a timer, and to determine whether a timer
-has expired or not (Timer_Has_Expired). In addition, when arming the timer, an
-access to a protected procedure (type Handler) is passed. This procedure
-will be called by the implementation when the timer expires.
-
-The constant Min_Handler_Ceiling is the priority value that will insure that
-no ceiling violation will occur when a handler is executed.
-
-When a Timer object is created, or upon the first call to one of its Arm
-procedures, the resources required to operate a CPU-time timer based on
-the associated execution-time clock will be allocated and initialized.
-The timer is initialized in the disarmed state. If this operation would
-exceed the limit of the maximum number of timers in the system, the
-Timer_Resource_Error exception is raised.
-
-The Arm 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 Arm 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 monitors 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.
-
-When a Timer expires, the protected procedure Handler is invoked by the system
-with a parameter equal to the Timer.
-
-The Disarm procedure sets the timer to the disarmed state. In this
-state the timer will not expire.
-
-The Time_Has_Expired function returns True if the timer is in the
-armed state and has expired, and returns False if the timer is in the
-armed state but has not yet expired. If the timer is in the disarmed
-state, the Timer_Error exception is raised.
-
-The Time_Remaining function returns, when the timer is in the armed state, the
-CPU time interval that remains until the timer will expire, or a value
-representing zero if the timer has expired. If the timer is in the disarmed
-state, the Timer_Error exception is raised.
-
-The Timer_Error exception is raised by Timer_Has_Expired, or
-Time_Remaining if an attempt is made to use a timer that is in the
-disarmed state.
+The constant Min_Handler_Ceiling is the priority value that will ensure
+that no ceiling violation will occur when a handler is executed.
 
 For all the operations and types defined in this package, Tasking_Error
 is raised if the task identified by T has terminated. Program_Error
@@ -803,16 +794,21 @@
 
 For a given Timer object, the implementation shall perform the operations
 declared in this package atomically with respect to any of these
-operations on the same Timer object.
+operations on the same Timer object. The replacement of a handler by a
+call of Set_Handler, shall be performed atomically with respect to the
+execution of the Timer_Handler.
 
+
 When an object of type Timer is finalized, the system resources used by
 the timer shall be deallocated.
 
 @i<@s8<Implementation Permissions>>
 
 Implementations may limit the number of timers that can be defined for
-each task. If this limit is exceeded the Timer_Resource_Error exception
-is raised.
+each task. If this limit is exceeded then Timer_Resource_Error is raised.
+
+@xindent<@s9<NOTES@hr
+A Timer_Handler can be associated with several Timer objects.>>
 
 
 !ACATS test

Questions? Ask the ACAA Technical Agent