Version 1.3 of ai05s/ai05-0166-1.txt
!standard D.2.1(1.2/2) 10-02-23 AI05-0166-1/03
!standard D.2.1(6/2)
!standard 9.5.1(16)
!standard D.2.4(2/2)
!standard D.2.4(9/2)
!class Amendment 09-10-22
!status work item 09-10-22
!status received 09-10-22
!priority Medium
!difficulty Easy
!subject Yield for non-preemptive dispatching
!summary
A support package for non-preemptive dispatching is proposed that
allows a task to offer to be preempted by a higher priority task,
but not by one of equal priority. A further 'yield' procedure is
included to improve the readability and maintainability of programs.
It replaces the current need to include 'delay 0.0' to force a
preemption.
!problem
With non-preemptive dispatching the only current non-blocking
dispatching point is a non-blocking delay_statement. We need another
kind so that a task in a system scheduled by non-preemptive dispatching
can indicate that it is prepared to be preempted by tasks of higher
priority but not by those of equal priority.
!proposal
Add to package Ada.Dispatching:
procedure Yield;
--
--
Add the following library package:
package Ada.Dispatching.Non_Preemptive is
procedure Yield_To_Higher;
procedure Yield_To_Same_Or_Higher renames Yield;
end Ada.Dispatching.Non_Preemptive;
With non-preemptive dispatching the only current non-blocking
dispatching point is a non-blocking delay_statement - D.2.4(9/2).
With this new package a call to Yield_To_Higher will
cause a task switch if there is a runnable task with an active
priority higher than the calling task's active priority. Note this
can be called from within a protected object.
To program cooperative scheduling a task explicitly includes the
points at which it is able to be preempted. It does this by using
either 'delay 0.0' or 'delay until Ada.Real_Time.Time_First' (the
latter being the one available with Ravenscar). As these statements
are not actually concerned with delaying the task they are potentially
misleading (to the human reader/maintainer of the code). The procedure
Yield is equivalent to these delay statements; and would therefore
cause the same bounded error if called from within a protected
action.
!wording
Add to package Ada.Dispatching (D.2.1(1.2/2)):
procedure Yield;
Add after D.2.1(6/2):
A call of Yield is a task dispatching point (see D.2.1). It is a bounded error
to call Yield from within a protected action.
Add after 9.5.1(16):
* a call to Ada.Dispatching.Yield;
Add after D.2.4(2/2):
The following language-defined library package exists:
package Ada.Dispatching.Non_Preemptive is
procedure Yield_To_Higher;
procedure Yield_To_Same_Or_Higher renames Yield;
end Ada.Dispatching.Non_Preemptive;
A call of Yield_To_Higher is a task dispatching point for this policy. If the
task at the head of the highest priority ready queue has a higher active
priority than the calling task then calling task is preempted.
Replace D.2.4(9/2):
For this policy, a non-blocking delay-statement, a call to Yield_To_Higher and
a call to Yield_To_Same_Or_Higher or Yield are the only non-blocking events
that are task dispatching points (see D.2.1).
!discussion
This AI was raised by an industrial user of non-preemptive scheduling,
and was discussed and endorsed by the 14th IRTAW. Details are
contained in the workshop paper: Providing Additional Real-Time
Capability and Flexibility for Ada 2005, by Rod White.
!example
A task that iterates through an algorithm, but offers to be preempted
by a higher priority task after each iteration would take the form:
with Ada.Dispatching.Non_Preemptive;
...
task Iterator;
task body Iterator is
...
Improving : boolean := True;
begin
...
while Improving loop
--
--
Ada.Dispatching.Non_Preemptive.Yield_To_Higher;
end loop;
...
end Iterator;
--!corrigendum D.2.4(9/2)
!ACATS test
Add an ACATS C-Test of this package.
!appendix
****************************************************************
Questions? Ask the ACAA Technical Agent