Version 1.1 of ais/ai-00358.txt
!standard 9.6 (00) 03-09-27 AI95-00358/01
!standard D.9 (00)
!class amendment 03-09-27
!status work item 03-09-27
!status received 03-09-27
!priority Medium
!difficulty Medium
!subject Application-defined scheduling
!summary
This document contains an application program interface (API) that
would enable Ada applications to use application-defined scheduling
algorithms in a way compatible with the scheduling model of the Ada 95
Real-Time Systems Annex. With this API, several application-defined
schedulers, implemented by extending a tagged type, can coexist in the
system in a predictable way together with their scheduled tasks, and
with regular fixed priority tasks directly scheduled by the run-time
system. The scheduling API uses the Priority_Specific scheduling
policy proposed in a separate API to provide a common framework for
supporting round-robin and other scheduling policies under the current
Ada's priority scheduling mechanism.
task synchronization through protected objects would be done through
the Stack Resource Policy, proposed in a separate AI. This policy can
be used in a large variety of fixed and dynamic priority scheduling
policies.
An implementation of a previous version of the Application-Defined
Scheduling proposal is available, and the implementation of the
specific API described in this paper is planned to be completed early
in 2004.
!problem
The Real-Time Annex in Ada 95 defines only one scheduling policy:
FIFO_Within_Priorities. Although fixed priority scheduling is an
excellent choice for real-time systems, there are application
requirements that cannot be fully accomplished with these policies
only. It could be possible to incorporate into the Ada standard new
dynamic scheduling policies to be used in addition to the existing
policies. The main problem is that the variety of these policies is so
great that it would be difficult to standardize on just a
few. Different applications needs would require different
policies. Instead, the IRTAW group considers that an interface should
be defined for application-defined schedulers that could be used to
implement a large variety of scheduling policies.
In summary, the motivation for this API is to provide developers of
applications with a flexible scheduling mechanism, handling both task
scheduling and synchronization, that enables them to schedule dynamic
applications that would not meet their requirements using the more
rigid fixed-priority scheduling currently provided in Ada. If we want
Ada to continue to be the reference language in the environment of
real-time systems, we need to include this essential functionality
into the language. Java is looking to support advanced flexible
scheduling mechanisms. A proposal to include similar functionality in
real-time POSIX is under discusion.
!proposal
1. Overview
-----------
A new priority-specific scheduling policy would be defined called
Application_Defined. This policy would enable tasks executing at
the associated priority level to be scheduled under an application
defined scheduler. Each application scheduler is a special software
module that can be implemented inside the run-time system or as a
special task, and that is responsible of scheduling a set of tasks
that have been attached to it. According to the way a task is
scheduled, we can categorize the tasks as:
- System-scheduled tasks: these tasks are scheduled directly by the
run-time system and/or the operating system, without intervention
of a scheduler task.
- Application-scheduled tasks: these tasks are also scheduled by the
run-time system and/or the operating system, but before they can be
scheduled, they need to be made ready by their application-defined
scheduler.
Application schedulers can be implemented in different ways. One
implementation would include the scheduler inside the run-time system
or the underlying operating system kernel, if any; the scheduler would
execute as part of the run-time operations. Another alternative is to
create a special task at the desired priority level, that would be in
charge of executing the application scheduler operations; it would
synchronize with the run-time system kernel at the appropriate points.
Because the scheduler may execute in an environment different than
that of the application tasks, it is an error to share information
between the scheduler and the rest of the application. An API is
provided for exchanging information when needed. Application
schedulers may share information among them.
Because the use of protected resources may cause priority inversions
or similar delay effects, it is necessary to provide a general
mechanism that can bound the delays caused by synchronization when
using different kinds of scheduling techniques, and also when several
schedulers are being used at the same time. This would be the Stack
Resource Policy (SRP) [5] because it is applicable to a large variety
of policies, including both fixed and deadline-based priority
policies.
2. Scheduling framework
-----------------------
The scheduling API presented in this section is designed to be
compatible with the new Round_Robin policy proposed in [4]. In that
proposal, compatible scheduling policies are allowed in the system
under the Priority_Specific Task_Dispatching_Policy, and the specific
policy is assigned to each particular priority level, with the
Priority_Policy pragma; two values are allowed:
Fifo_Within_Priorities, or Round_Robin. At each priority level, only
one policy is available, thus avoiding the potentially unpredictable
effects of mixing tasks of different policies at the same level.
We propose adding one more value that could be used with the
Priority_Policy pragma: Application_Defined; it represents tasks that
are application scheduled. If the scheduler is implemented as a
special task, its base priority must be at least equal to that of its
scheduled tasks.
3. Application scheduler
------------------------
Application schedulers are defined by extending the Scheduler abstract
tagged type defined in the new package
Ada.Application_Scheduling. This type contains primitive operations
that are invoked by the system when a scheduling event occurs. The
type is extended by adding the data structures required by the
scheduler (for example, a ready queue and a delay queue), and by
overriding the primitive operations of interest to perform the
scheduling decisions required to implement the desired scheduling
policy.
In addition, we need to extend the Scheduling_Parameters tagged type
defined in the same package to contain all the information that is
necessary to specify the scheduling parameters of each task (such as
its deadline, execution-time budget, period, and similar parameters).
To install one of these application schedulers using the
priority-specific framework, we need to specify that the desired
priority level, P, will be using an application-defined scheduler. We
do so with the following configuration pragmas:
pragma Task_Dispatching_Policy (Priority_Specific);
pragma Priority_Policy (Application_Defined, P);
pragma Locking_Policy (Preemption_Level_Within_Ceiling_Locking);
Then, we need to attach the scheduler to the chosen priority level
through the use of the following pragma:
pragma Application_Scheduler (My_Scheduler,P);
where My_Scheduler is the scheduler type and P is the desired priority
level. Before the scheduler is elaborated, no task at this priority
level can run. As an alternative My_Scheduler could be given as a
parameter to the priority pragms:
pragma Priority_Policy (Application_Defined, P, My_Scheduler);
As we mentioned before, the scheduler may be implemented inside the
run-time system, or as a user-level task. In both cases the system
must ensure that the application-scheduled tasks cannot preempt their
scheduler. Because the active priority of an application-scheduled
task may change because of the inheritance of other priorities through
the use of protected objects, it is necessary that in the user-task
implementation the scheduler also inherits the same priority. In this
way, the scheduler always takes precedence over its scheduled
tasks. It is not necessary though that this priority is inherited by
the rest of the tasks scheduled by that scheduler.
When the active priority of a task is higher than its base priority,
it always takes precedence over any application scheduling
parameters. Therefore, application-scheduled tasks take precedence
over tasks with lower active priority, and they are always preempted
by tasks with higher active priority that become ready.
Each application-defined scheduler may simultaneously make ready many
application-scheduled tasks, to run concurrently. The scheduler may
also block previously ready tasks. Among themselves, tasks that are
concurrently made ready are scheduled like FIFO_Within_Priorities
tasks. As mentioned previously, the scheduler always takes precedence
over its scheduled tasks.
For an application-scheduled task to become ready it is necessary that
its scheduler performs a ready action on it. When the application
task executes one of the following actions or experiences one of the
following situations, a scheduling event is generated for the
scheduler, unless the scheduling event to be generated is being
filtered out (discarded).
- when a task requests attachment to the scheduler
- when a task blocks or gets ready
- when a task changes its scheduling parameters
- when a task invokes the yield operation (i.e., delay 0.0 operation)
- when a task explicitly invokes the scheduler
- when a task inherits or uninherits a priority, due to the use of a
protected object, a rendezvous, or a task activation.
- when a task terminates
- when a task is aborted.
In addition to these events, the scheduler can also be notified about
other system-generated events such as the expiration of an
execution-time timer or of a group of timers, a timed notification
programmed by the own scheduler for a particular task, a timeout, or
an error notification.
All of the above events are reported to the scheduler by the system
invoking one of its primitive operations. These operations contain
information relevant to the event (such as the task Id), and an
Actions parameter that can be used by the scheduler to specify the
scheduling actions that need to be performed by the system after the
operation returns. As an example, the specification for two of these
primitive operations is shown next (the complete specification is
included in the "wording" section):
procedure Ready
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Timeout
(Sched : in out Scheduler;
Actions : in out Scheduling_Actions);
The Actions parameter is passed empty by the system, and the scheduler
may add multiple scheduling actions of the following set:
- accept of reject a task
- make a task ready at the back of the queue for its priority
- make a task ready at the front of the queue for its priority
- suspend a task
- program a timed notification associated to a given task
- program a timeout to occur; this timeout will be cancelled if some
other event occurs first
- program a timed notification to occur if a task overruns its
execution time budget; as with the timeout, this notification will
be cancelled if some other event occurs first.
The system must ensure that the execution of the scheduling actions
and the invocation of the scheduler primitive operations are all
sequential. For multiprocessor systems this may seem to be a
limitation, but for these systems several schedulers could be running
simultaneously on different processors, cooperating with each other by
synchronizing through protected objects. For single processor systems
the sequential nature of the scheduler should be no problem if the
system provides the necessary locking.
When an application-defined task is attached to its application
scheduler, the latter has to either accept it or reject it, based upon
the current state and the scheduling attributes of the candidate
task. Rejection of a task causes an exception to be raised during the
elaboration of the task. This exception and the rest of the interface
offered to both the scheduler and its scheduled tasks is contained in
a new package, Ada.Application_Scheduling, that is described in the
wording section.
4. Application-scheduled tasks
------------------------------
Application-scheduled tasks may choose to be scheduled by an
application-defined scheduler just by setting their priority to the
appropriate value. In addition, they must specify their own scheduling
parameters, that will be used by the scheduler to schedule that task
contending with the other tasks attached to the same application
scheduler. We set the scheduling parameters through the following
pragma:
pragma Application_Defined_Sched_Parameters (My_Parameters’Access);
where My_Parameters is an object of the extended scheduling parameters
type, containing specific values for each parameter. These parameters
may be changed dynamically with the Set_Parameters call. The
application scheduling parameters have no effects in tasks with other
scheduling policies.
Some scheduling algorithms require the ability to explicitly invoke
the scheduler from the application task, perhaps passing information
to the scheduler and obtaining reply information back. The API for
this explicit invocation is
procedure Invoke
(Msg : in Message_To_Scheduler'Class);
procedure Invoke
(Msg : in Message_To_Scheduler'Class;
Reply : out Reply_From_Scheduler'Class);
where the message passed to the scheduler is of an application-defined
type extended from Message_To_Scheduler, and the reply message used in
the second version of the call is extended from Reply_From_Scheduler.
5. Interactions with Protected Objects
--------------------------------------
A new Locking_Policy is defined for the SRP in a separate AI,
identified with the Prremption_Level_Within_Ceiling_Locking name. This
is a configuration pragma that affects the whole partition. Under this
locking policy, the priority ceilings of the protected objects
continue to exist, and are assigned via the usual pragma Priority. In
addition, a pragma may be used to assign a preemption level to
each task and protected object:
pragma Preemption_Level (Level);
This pragma specifies the preemption level relative to tasks or
protected objects of the same priority level. The priority of the task
or the protected object always takes precedence over it. This is
equivalent to defining the actual preemption level as:
actual=prio*2^n+level
where n is the number of bits used to represent the preemption level.
With this approach, any task or protected object that
does not specify the preemption level behaves exactly as with the
Ceiling_Locking policy. This is an important property because we can
reuse all of the concurrent software developed for that policy and
make it work together with other tasks scheduled under an
application-defined policy.
The system scheduler is in charge of verifying the SRP rule: a task
cannot be made ready if its (actual) preemption level is strictly
higher than the preemption level of the system, which is the maximum
of the (actual) preemption levels of the protected objects currently
locked. An error event is sent to the application scheduler if it
tries to violate this rule.
Some scheduling policies such as the sporadic server (SS) or the
constant bandwidth server (CBS) rely on execution time budgets to
bound the amount of bandwidth given to a certain task. When the budget
is exhausted, the scheduler makes a scheduling decision, usually
making ready some other task as a result. The problem with these
approaches is that the suspension of the current task due to the
expiration of its execution time budget should not be allowed to
preempt a critical section, i.e., should not be made while holding the
lock on a protected object. One common approach is to defer the
expiration of the budget until the protected operation finishes. Of
course this approach means that during the analysis the extra time
that the budget expiration may be delayed has to be accounted for.
To implement the deferral of the budget expiration we propose a
mechanism by which any of the scheduling events that may be notified
to the application scheduler by the system may be deferred while a
protected operation of a priority ceiling above some given value is in
progress. A mask of events to be deferred during protected operations
is specified by the scheduler. This approach is quite efficient,
because in the normal case in which critical sections are short there
will be no events pending when the protected operation finishes, and
the overhead is only increased by a simple check. If events are
pending, they are reported to the scheduler task at the end of the
protected operation. The API to set this mask is the following:
procedure Set_Protected_Event_Mask
(Mask : in Event_Mask;
Ceiling : in System.Any_Priority);
procedure Get_Protected_Event_Mask
(Mask : out Event_Mask;
Ceiling : out System.Any_Priority);
The mask may include the timed notification events, and this make them
an extremely useful way of programming future actions for the
scheduler that do not interfere with the synchronization through
protected objects.
6. Conclusions
--------------
We have proposed a new API for application-defined scheduling. With
this API, several application-defined schedulers, implemented by
extending a tagged type, can coexist in the system in a predictable
way together with their scheduled tasks, and with regular fixed
priority tasks directly scheduled by the run-time system. Task
synchronization through protected objects is also considered by using
the Stack Resource Policy, which can be used in a large variety of
fixed and dynamic priority scheduling policies. Interactions between
the application-defined schedulers and the protected objects are
facilitated by being able to defer the notification of scheduling
events to the application scheduler.
A previous version of this API has been implemented for a GNAT
run-time system executing on top of MaRTE OS, which is a free software
implementation of the POSIX minimal real-time operating system,
intended for small embedded systems. An implementation of the API
presented in this paper is planned to be completed in a few months.
!wording
Add new section D.15.
D.15 Application defined scheduling
<Precise wording to be provided as soon as possible. Package
specification is provided here>
The following language-defined package exists:
with Ada.Task_Identification, Ada.Real_Time,
Ada.Real_Time.Execution_Time,
Ada.Real_Time.Execution_Time.Group_Timers,System;
package Ada.Application_Scheduling is
--
--
--
--
--
--
--
protected type Timer_Expiration is
procedure Announce
(T : in out Ada.Real_Time.Execution_Time.Timer);
procedure Notify
(T : in out Ada.Real_Time.Execution_Time.Group_Timers.Group_Timer);
private
--
end Timer_Expiration;
type Timer_Expiration_Ref is access Timer_Expiration;
--
--
--
type Scheduling_Actions is private;
procedure Add_Accept
(Sched_Actions : in out Scheduling_Actions;
Tid : in Ada.Task_Identification.Task_Id);
procedure Add_Reject
(Sched_Actions : in out Scheduling_Actions;
Tid : in Ada.Task_Identification.Task_Id);
procedure Add_Ready
(Sched_Actions : in out Scheduling_Actions;
Tid : in Ada.Task_Identification.Task_Id);
procedure Add_Ready_At_Front
(Sched_Actions : in out Scheduling_Actions;
Tid : in Ada.Task_Identification.Task_Id);
procedure Add_Suspend
(Sched_Actions : in out Scheduling_Actions;
Tid : in Ada.Task_Identification.Task_Id);
procedure Add_Timeout
(Sched_Actions : in out Scheduling_Actions;
At_Time : in Ada.Real_Time.Time);
procedure Add_Timed_Task_Notification
(Sched_Actions : in out Scheduling_Actions;
Tid : in Ada.Task_Identification.Task_Id;
At_Time : in Ada.Real_Time.Time);
procedure Add_Timer_Expiration
(Sched_Actions : in out Scheduling_Actions;
Handler : in Timer_Expiration_Ref);
--
--
--
type Message_To_Scheduler is abstract tagged null record;
type Reply_From_Scheduler is abstract tagged null record;
procedure Invoke (Msg : in Message_To_Scheduler'Class);
--
procedure Invoke (Msg : in Message_To_Scheduler'Class;
Reply : out Reply_From_Scheduler'Class);
--
Task_Not_Application_Scheduled : exception; --
--
--
--
type Scheduler is abstract tagged private;
type Error_Cause is (SRP_Rule_Violation, Invalid_Action_For_Task);
procedure Init (Sched : out Scheduler) is abstract;
procedure New_Task
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Terminate_Task
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Ready
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Block
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Yield
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Abort_Task
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Change_Sched_Param
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Explicit_Call
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Msg : in Message_To_Scheduler'Class;
Reply : out Reply_From_Scheduler'Class;
Actions : in out Scheduling_Actions);
procedure Task_Notification
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Timeout
(Sched : in out Scheduler;
Actions : in out Scheduling_Actions);
procedure Execution_Timer_Expiration
(Sched : in out Scheduler;
Expired_Timer : in out Ada.Real_Time.Execution_Time.Timer;
Actions : in out Scheduling_Actions);
procedure Group_Timer_Expiration
(Sched : in out Scheduler;
Expired_Group : in out
Ada.Real_Time.Execution_Time.Group_Timers.Group_Timer;
Actions : in out Scheduling_Actions);
procedure Priority_Inherit
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
From_Tid : in Ada.Task_Identification.Task_Id;
Inherited_Prio : in System.Any_Priority;
Actions : in out Scheduling_Actions);
procedure Priority_Uninherit
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
From_Tid : in Ada.Task_Identification.Task_Id;
Uninherited_Prio : in System.Any_Priority;
Actions : in out Scheduling_Actions);
procedure Error
(Sched : in out Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Cause : in Error_Cause;
Actions : in out Scheduling_Actions) is abstract;
--
--
--
--
type Event_Code is
(New_Task, Terminate_Task, Ready, Block, Yield,
Change_Sched_Param, Explicit_Call,
Task_Notification, Timeout, Execution_Timer_Expiration,
Priority_Inherit, Priority_Uninherit);
type Event_Mask is private;
procedure Fill (Mask : in out Event_Mask);
procedure Empty (Mask : in out Event_Mask);
procedure Add (Event : in Event_Code;
Mask : in out Event_Mask);
procedure Delete (Event : in Event_Code;
Mask : in out Event_Mask);
function Is_Member (Event : in Event_Code;
Mask : in Event_Mask)
return Boolean;
--
--
procedure Set_Event_Mask (Mask : in Event_Mask);
procedure Get_Event_Mask (Mask : out Event_Mask);
--
--
--
procedure Set_Protected_Event_Mask
(Mask : in Event_Mask;
Ceiling : in System.Any_Priority);
procedure Get_Protected_Event_Mask
(Mask : out Event_Mask;
Ceiling : out System.Any_Priority);
--
--
--
type Scheduling_Parameters is abstract tagged null record;
type Sched_Params_Ref is access Scheduling_Parameters'Class;
procedure Set_Parameters
(Tid : in Ada.Task_Identification.Task_Id;
Param : in Scheduling_Parameters'Class);
--
--
procedure Get_Parameters
(Tid : in Ada.Task_Identification.Task_Id;
Param : out Scheduling_Parameters'Class);
--
--
private
--
end Ada.Application_Scheduling;
!discussion
!examples
In this example we show the implementation of a basic EDF scheduler
for periodic tasks. A real implementation of an EDF scheduler would
need to take into account additional event arrival patterns
(aperiodic, sporadic, etc.) and the possibility of task
suspension. The purpose of the simplified example is just to
illustrate how to use the API proposed here. The EDF scheduler would
be programmed in a package with the following specification. It uses a
priority queue that would be written in package Queues; the priority
is the deadline (earliest deadline first):
with Ada.Application_Scheduling, Queues,
Ada.Task_Identification, Ada.Real_Time;
use Queues, Ada.Application_Scheduling,
Ada.Real_Time;
package EDF_Scheduling is
--
type EDF_Parameters is new
Scheduling_Parameters with
record
Period : Time_Span;
Relative_Deadline : Time_Span;
end record;
--
type Message is new Message_To_Scheduler
with null record;
--
type EDF_Scheduler is new Scheduler with
record
Ready_Queue : Queue;
Current_Task :
Ada.Task_Identification.Task_Id;
end record;
procedure Init (Sched : out EDF_Scheduler);
procedure New_Task
(Sched : in out EDF_Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Terminate_Task
(Sched : in out EDF_Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Explicit_Call
(Sched : in out EDF_Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Msg : in Message_To_Scheduler'Class;
Reply : out Reply_From_Scheduler'Class;
Actions : in out Scheduling_Actions);
procedure Task_Notification
(Sched : in out EDF_Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Actions : in out Scheduling_Actions);
procedure Error
(Sched : in out EDF_Scheduler;
Tid : in Ada.Task_Identification.Task_Id;
Cause : in Error_Cause;
Actions : in out Scheduling_Actions);
pragma Application_Scheduler
(EDF_Scheduler, P, Stack_Resource_Policy);
end EDF_Scheduling;
The body of the package contains the scheduling operations:
with Ada.Task_Attributes;
package body EDF_Scheduling is
use Ada.Task_Identification;
type EDF_Attributes is record
Period : Time_Span;
Deadline : Time;
Ready_Time : Time;
end record;
package EDF_Attr is new Ada.Task_Attributes
(EDF_Attributes,
(To_Time_Span(0.0),Time_Last,Time_Last));
procedure Init (Sched : out EDF_Scheduler) is
begin
Make_Queue_Empty (Sched.Ready_Queue);
Sched.Current_Task := Null_Task_Id;
end Init;
--
--
procedure Do_Scheduling
(Sched : in out EDF_Scheduler;
Actions : in out Scheduling_Actions) is
begin
if Sched.Current_Task/=Sched.Current_Task
then
if Head_Of_Queue(Sched.Ready_Queue)/=
Null_Task_Id
then
Add_Activate(Actions, Head_Of_Queue
(Sched.Ready_Queue));
Sched.Current_Task :=
Head_Of_Queue(Sched.Ready_Queue);
end if;
if Sched.Current_Task/=Null_Task_Id
then
Add_Suspend (Actions,Current_Task);
end if;
end if;
end Do_Scheduling;
procedure New_Task
(Sched : in out EDF_Scheduler;
Tid : in Task_Id;
Actions : in out Scheduling_Actions)
is
Param : EDF_Parameters;
Current_Time : Ada.Real_Time.Time:=
Ada.Real_Time.Clock;
Task_Data : EDF_Attributes;
begin
Get_Parameters (Tid, Param);
--
if Schedulability_Test_OK (Param) then
Add_Accept (Actions, Tid);
--
Task_Data.Period := Param.Period;
Task_Data.Ready_Time:=
Current_Time;
Task_Data.Deadline := Current_Time +
Param.Relative_Deadline;
EDF_Attr.Set_Value(Task_Data);
Add_To_Queue (Sched.Ready_Queue, Tid);
else
Add_Reject (Actions, Tid);
end if;
Do_Scheduling (Sched,Actions);
end New_Task;
procedure Terminate_Task
(Sched : in out EDF_Scheduler;
Tid : in Task_Id;
Actions : in out Scheduling_Actions) is
begin
--
Remove_From_Queue (Sched.Ready_Queue, Tid);
Do_Scheduling(Sched,Actions);
end Terminate_Task;
procedure Task_Notification
(Sched : in out EDF_Scheduler;
Tid : in Task_Id;
Actions : in out Scheduling_Actions) is
begin
--
Add_To_Queue (Sched.Ready_Queue, Tid);
Do_Scheduling(Sched,Actions);
end Task_Notification;
procedure Explicit_Call
(Sched : in out EDF_Scheduler;
Tid : in Task_Id;
Msg : in Message_To_Scheduler'Class;
Reply : out Reply_From_Scheduler'Class;
Actions : in out Scheduling_Actions)
is
Task_Data : EDF_Attributes;
begin
--
Task_Data:=EDF_Attr.Value;
--
Task_Data.Deadline:=
Task_Data.Deadline+Task_Data.Period;
Task_Data.Ready_Time:=
Task_Data.Ready_Time+Task_Data.Period;
EDF_Attr.Set_Value(Task_Data);
--
Remove_From_Queue (Sched.Ready_Queue, Tid);
--
Add_Timed_Task_Notification
(Actions, Tid, Task_Data.Ready_Time);
Do_Scheduling(Sched,Actions);
end Explicit_Call;
procedure Error
(Sched : in out EDF_Scheduler;
Tid : in Task_Id;
Cause : in Error_Cause;
Actions : in out Scheduling_Actions) is
begin
Report_Error(Cause); --
end Error;
end EDF_Scheduling;
The application tasks are created like in the following example. The
Specification of the task with the package is below:
with EDF_Scheduling, Ada.Real_Time;
use EDF_Scheduling, Ada.Real_Time;
package EDF_Task is
My_Parameters : aliased EDF_Parameters :=
(Period => To_Time_Span(0.001_500),
Relative_Deadline =>
To_Time_Span(0.001_000));
task EDF_Scheduled_Task is
pragma Application_Defined_Sched_Parameters
(My_Parameters'access);
pragma Priority (10);
pragma Preemption_Level (34);
end EDF_Scheduled_Task;
end EDF_Task;
And the body of the package appears next. It can be seen that the task
notifies the scheduler that an instance has been completed with an
explicit invocation:
with Ada.Application_Scheduling;
package body EDF_Task is
--
task body EDF_Scheduled_Task is
Null_Message : Message;
begin
loop
--
--
Ada.Application_Scheduling.Invoke
(Null_Message);
end loop;
end EDF_Scheduled_Task;
end EDF_Task;
!appendix
Please see attached paper:
[1] Mario Aldea Rivas and Michael González Harbour.
"Application-Defined Scheduling in Ada". 2003-IRTAW proceedings.
Additional References
---------------------
[2] Mario Aldea Rivas and Michael González Harbour. "A POSIX-Ada
Interface for Application-Defined Scheduling". International
Conference on Reliable Software Technologies, Ada-Europe 2002,
Vienna, Austria, in Lecture Notes in Computer Science No. 2361,
pp.136-150, June 2002.
[3] Mario Aldea Rivas and Michael González
Harbour. "POSIX-Compatible Application-Defined Scheduling in
MaRTE OS" Proceedings of 14th Euromicro Conference on Real-Time
Systems, Vienna, Austria, IEEE Computer Society Press, pp. 67-75,
June 2002.
[4] A. Burns, M. González Harbour and A.J. Wellings. "A Round Robin
Scheduling Policy for Ada". Proceedings of the International
Conference on Reliable Software Technologies, Ada-Europe-2003,
Tolouse, France, in Lecture Notes in Computer Science, LNCS 2655,
June, 2003, ISBN 3-540-40376-0.
[5] Baker T.P., "Stack-Based Scheduling of Realtime Processes",
Journal of Real-Time Systems, Volume 3, Issue 1 (March 1991),
pp. 67-99.
****************************************************************
Questions? Ask the ACAA Technical Agent