enabling the scheduling of aperiodic and sequential tasks amongst other cyclic tasks while preserving the overall periodicity of the system: making offline schedulability analysis possible. Due to the variety of different execution server implementations (Buttazzo, 2011), the Cyclic Task Specification does not pre-
scribe a specific implementation. Instead, a library provides a general execution server interface to facilitate the creation and termination of execution servers, and to add and remove tasks from these servers. Run-times and users use this interface to provide their execution server implementations without requiring additional compiler support outside the new Execution_Server task aspect. The Ada.Execution_Servers package provides the general interface (Appendix A). Implementations derive from the abstract tagged type Execution_Server:
type Execution_Server (<>) is abstract tagged limited private;
The Execution_Server object need not directly implement the execution server; instead, it may act as a proxy to other run-time objects. The type uses an un- known discriminant to force an Execution_Server object’s initialisation — and, if needed, registration of the execution server with the run-time — at the time of the object’s creation through the abstract function New_Execution_Server:
function New_Execution_Server
(Priority : System.Any_Priority; Period : Time_Span;
Phase : Time_Span := Real_Time.Time_Span_Zero; Execution_Budget : Time_Span := Real_Time.Time_Span_Last; Relative_Deadline : Time_Span := Real_Time.Time_Span_Last; CPU : CPU_Range := Not_A_Specific_CPU) return Execution_Server is abstract;
The Execution_Server object requires initialisation with its parameters at the
time of object creation since the run-time can add tasks to the object before the end of the declarative part the object is a member.
At minimum, each execution server requires a priority, period, phase and CPU assignment to provide the periodic attributes of the server. Each server also has an execution budget and relative deadline property, the latter permitting the server to operate under any of the existing task dispatching policies. The properties are specifiable as part of the initialisation procedure with functions available in the Ada.Execution_Servers package to read these core server pa- rameters at run-time. It is recommended to use New_Execution_Server to initialise new Execution_Server objects to simplify the identification of server parameters, for both users and tools operating on the software.
2. Simplifying the case when the task is in-between cycles and the cycle period shortens.
Execution Servers
library packages
49 THE CYCLIC TASK SPECIFICATION
The Ada.Execution_Servers package only offers environment defined execution servers with static properties. Tasks are assigned to these servers via their Execu- tion_Server aspect and no facility exists to remove member tasks. Consequently, these servers suit schedulability analysis by ensuring timing properties and members do not change at run-time.
Two child packages support greater run-time and user flexibility for non-hard real-time systems: Ada.Execution_Servers.Dynamics and Ada.Execution_Serv- ers.User_Servers (Appendix A). The Dynamics package extends the Execu- tion_Server type with the Dynamic_Execution_Server type, providing standard procedures to dynamically change execution server properties at run-time in addition to adding and removing member tasks.
Similarly, the User_Servers package offers the same flexibility as the Dynam- ics package — with User_Execution_Server extending from Dynamic_Execu- tion_Server — but enables users to implement their own execution servers. This distinction provides a visible and semantic separation of environment and user supplied execution servers, with the run-time required to call the user’s Add_Task_To_Server procedure when adding a task specified via the task’s Execution_Server aspect. The run-time does not need do this for other execution servers, offering flexibility in their implementation.
Conceptually, the Specification models execution servers like periodic tasks,
with execution servers consisting of cycles which commence at periodic in- tervals as governed by the server’s period and phase properties. These cycles, called execution windows, provide a window for tasks assigned to the server
to execute. Consequently, instead of directly executing like a periodic task, execution servers dispatch member tasks in their place, with tasks dispatched from a first-in, first-out queue.
When a member task temporarily inherits a priority because of intertask com- munication (ARM D.1), the task leaves the execution server and adopts the inherited priority. While outside the execution server, the task does not con- sume the server’s execution budget nor shall the task block when the execution window closes until its base priority restores.
Execution server implementations have considerable flexibility to choose how they behave. The first decision an implementation needs to consider is when an execution window closes. Two primary methods exist:
▶ The execution window closes once an absolute deadline passes, with the deadline calculated using the server’s relative deadline property. ▶ The execution window closes when the execution budget of the cycle
is exhausted. The server's execution budget property sets the budget of the cycle.
An execution server may choose to employ both techniques to constrain how long a window remains open for if its budget is not consumed within an al- lotted time. Alternatively, an execution server may choose another method to determine when to close an execution window.
model
implementation choices
Further, execution servers have the prerogative to choose how member and non-member tasks consume their execution budgets, and what happens when an execution window is open but the server has no tasks to dispatch. For the latter, the server may let lower priority tasks execute inside its window or may block the processor until it can dispatch a member task.
For Ravenscar Profile systems, most of the cyclic task behaviour is available. Re- moved are the Ada.Cyclic_Tasks.Dynamics, Ada.Execution_Servers.Dynamics
and Ada.Execution_Servers.User_Servers packages, as dynamically changing cyclic task properties introduces non-deterministic tasking behaviour. Also removed are the deadline and execution budget responses Abort_Cycle and Abort_Task as they introduce asynchronous transfer of control and task ter-
mination.
A number of simple examples demonstrate the power and flexibility of the
Cyclic Task Specification.
A simple periodic task counts the number of elapsed seconds, printing the value of the counter each cycle. Using the new syntax:
task Counter
with Priority => 15, Cyclic_Task => Periodic, Cycle_Period => Seconds (1);
task body Counter is
J : Natural := 0;
begin
Put_Line ("Counter Start"); Put (J);
cycle
J := J + 1; Put (J);
end Counter;
Notice how the body of the task does not contain any task timing information; instead, that information can be found in a clear and concise format on the task specification. The only cyclic information the user needs to care about in the body of the task is their cyclic code and the initialisation of the task.
A user though may desire a collection of counter tasks that increment at differ- ent rates. Reusing the same body, the task declaration would become:
task type Counter (Rate_In_Seconds : Positive) with Priority => 15,
Cyclic_Task => Periodic,
Cycle_Period => Seconds (Rate_In_Seconds);