D.16.1 Multiprocessor Dispatching Domains
{
AI05-0167-1}
{
AI05-0299-1}
This subclause allows implementations on multiprocessor platforms to
be partitioned into distinct dispatching domains during program startup.
Static Semantics
{
AI05-0167-1}
The following language-defined library package exists:
with Ada.Real_Time;
with Ada.Task_Identification;
package System.Multiprocessors.Dispatching_Domains
is
Dispatching_Domain_Error :
exception;
type Dispatching_Domain (<>)
is limited private;
System_Dispatching_Domain :
constant Dispatching_Domain;
{
AI12-0033-1}
function Create (First : CPU; Last : CPU_Range)
return Dispatching_Domain;
function Get_First_CPU (Domain : Dispatching_Domain)
return CPU;
{
AI12-0033-1}
function Get_Last_CPU (Domain : Dispatching_Domain)
return CPU_Range;
{
AI12-0033-1}
type CPU_Set
is array(CPU
range <>)
of Boolean;
{
AI12-0033-1}
function Create (Set : CPU_Set)
return Dispatching_Domain;
{
AI12-0033-1}
function Get_CPU_Set (Domain : Dispatching_Domain)
return CPU_Set;
function Get_Dispatching_Domain
(T : Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task)
return Dispatching_Domain;
procedure Assign_Task
(Domain :
in out Dispatching_Domain;
CPU :
in CPU_Range := Not_A_Specific_CPU;
T :
in Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task);
procedure Set_CPU
(CPU :
in CPU_Range;
T :
in Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task);
function Get_CPU
(T : Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task)
return CPU_Range;
procedure Delay_Until_And_Set_CPU
(Delay_Until_Time :
in Ada.Real_Time.Time; CPU :
in CPU_Range);
private
... -- not specified by the language
end System.Multiprocessors.Dispatching_Domains;
{
AI05-0167-1}
{
AI12-0082-1}
A
dispatching domain represents a set of processors
on which a task may execute. Each processor is contained within exactly
one dispatching domain. An object of type Dispatching_Domain identifies
a dispatching domain. System_Dispatching_Domain identifies a domain that
contains the processor or processors on which the environment task executes.
At program start-up all processors are contained within this domain.
Dispatching_Domain
The value of aspect Dispatching_Domain is an
expression,
which shall be of type Dispatching_Domains.Dispatching_Domain. This aspect
is the domain to which the task (or all objects of the task type) are
assigned.
Aspect Description for Dispatching_Domain:
Domain (group of processors) on which a given task should run.
Legality Rules
{
AI05-0167-1}
The Dispatching_Domain aspect shall not be specified for a task interface.
Dynamic Semantics
{
AI05-0167-1}
{
AI12-0033-1}
The expression specified for the Dispatching_Domain aspect of a task
type is evaluated each time an object of the task type is created (see
9.1). If the identified dispatching domain
is empty, then Dispatching_Domain_Error is raised; otherwise the newly
created task is assigned to the domain identified by the value of the
expression.
{
AI05-0167-1}
If a task is not explicitly assigned to any domain, it is assigned to
that of the activating task. A task always executes on some CPU in its
domain.
{
AI05-0167-1}
{
AI12-0082-1}
If both the dispatching domain and CPU are specified for a task, and
the CPU value is not contained within the set of processors for the domain
(and is not Not_A_Specific_CPU), the activation of the task is defined
to have failed, and it becomes a completed task (see
9.2).
{
AI05-0167-1}
{
AI12-0033-1}
The function Create with First and Last parameters creates and returns
a dispatching domain containing all the processors in the range First
.. Last. The function Create with a Set parameter creates and returns
a dispatching domain containing the processors for which Set(I) is True.
These processors are removed from System_Dispatching_Domain. A call of
Create will raise Dispatching_Domain_Error if any designated processor
is not currently in System_Dispatching_Domain, or if the system cannot
support a distinct domain over the processors identified, or if a processor
has a task assigned to it, or if the allocation would leave System_Dispatching_Domain
empty. A call of Create will raise Dispatching_Domain_Error if the calling
task is not the environment task, or if Create is called after the call
to the main subprogram.
{
AI05-0167-1}
{
AI12-0033-1}
The function Get_First_CPU returns the first CPU in Domain, or CPU'First
if Domain is empty; Get_Last_CPU returns the last CPU in Domain, or CPU_Range'First
if Domain is empty. The function Get_CPU_Set(D) returns an array whose
low bound is Get_First_CPU(D), whose high bound is Get_Last_CPU(D), with
True values in the Set corresponding to the CPUs that are in the given
Domain.
{
AI05-0167-1}
{
AI12-0082-1}
The function Get_Dispatching_Domain returns the dispatching domain on
which the task is assigned.
{
AI05-0167-1}
{
AI05-0278-1}
{
AI12-0033-1}
A call of the procedure Assign_Task assigns task T to the CPU within
the dispatching domain Domain. Task T can now execute only on CPU, unless
CPU designates Not_A_Specific_CPU in which case it can execute on any
processor within Domain. The exception Dispatching_Domain_Error is propagated
if Domain is empty, T is already assigned to a dispatching domain other
than System_Dispatching_Domain, or if CPU is not one of the processors
of Domain (and is not Not_A_Specific_CPU). A call of Assign_Task is a
task dispatching point for task T unless T is inside of a protected action,
in which case the effect on task T is delayed until its next task dispatching
point. If T is the Current_Task the effect is immediate if T is not inside
a protected action, otherwise the effect is as soon as practical. Assigning
a task already assigned to System_Dispatching_Domain to that domain has
no effect.
{
AI05-0167-1}
{
AI05-0278-1}
{
AI12-0082-1}
A call of procedure Set_CPU assigns task T to the CPU. Task T can now
execute only on CPU, unless CPU designates Not_A_Specific_CPU, in which
case it can execute on any processor within its dispatching domain. The
exception Dispatching_Domain_Error is propagated if CPU is not one of
the processors of the dispatching domain on which T is assigned (and
is not Not_A_Specific_CPU). A call of Set_CPU is a task dispatching point
for task T unless T is inside of a protected action, in which case the
effect on task T is delayed until its next task dispatching point. If
T is the Current_Task the effect is immediate if T is not inside a protected
action, otherwise the effect is as soon as practical.
{
AI05-0167-1}
The function Get_CPU returns the processor assigned to task T, or Not_A_Specific_CPU
if the task is not assigned to a processor.
{
AI05-0167-1}
{
AI12-0082-1}
A call of Delay_Until_And_Set_CPU delays the calling task for the designated
time and then assigns the task to the specified processor when the delay
expires. The exception Dispatching_Domain_Error is propagated if P is
not one of the processors of the calling task's dispatching domain (and
is not Not_A_Specific_CPU).
Implementation Requirements
{
AI05-0167-1}
The implementation shall perform the operations Assign_Task, Set_CPU,
Get_CPU and Delay_Until_And_Set_CPU atomically with respect to any of
these operations on the same dispatching_domain, processor or task.
{
AI12-0048-1}
Any task that belongs to the system dispatching domain can execute on
any CPU within that domain, unless the assignment of the task has been
specified.
Reason: This ensures that priorities
and deadlines are respected within the system dispatching domain. There
is no such guarantee between different domains.
We only need to talk about the system dispatching
domain here, because Assign_Task and Set_CPU already have such wording
for tasks that are assigned explicitly to a dispatching domain and specify
Not_a_Specific_CPU.
Ramification: If no dispatching domains
are created, all tasks can execute on all processors. (As always, implementation-defined
dispatching policies may have other rules, so a partition that does not
specify any language-defined dispatching policy may do anything at all
and in particular does not need to follow this rule.
Discussion: A task can be assigned to
a specific CPU by specifying the aspect CPU for a task, or by calling
a dynamic operation like Set_CPU or Assign_Task.
Implementation Advice
{
AI05-0167-1}
Each dispatching domain should have separate and disjoint ready queues.
Implementation Advice: Each dispatching
domain should have separate and disjoint ready queues.
To be honest: {
AI12-0048-1}
“Ready queue” here doesn't mean the conceptual "ready
queue" as defined in
D.2.1 (one per
processor); this rule is talking about the ready queues used by the implementation.
Documentation Requirements
{
AI05-0167-1}
The implementation shall document the processor(s) on which the clock
interrupt is handled and hence where delay queue and ready queue manipulations
occur. For any Interrupt_Id whose handler can execute on more than one
processor the implementation shall also document this set of processors.
Documentation Requirement: The processor(s)
on which the clock interrupt is handled; the processors on which each
Interrupt_Id can be handled.
Implementation Permissions
{
AI05-0167-1}
An implementation may limit the number of dispatching domains that can
be created and raise Dispatching_Domain_Error if an attempt is made to
exceed this number.
Extensions to Ada 2005
{
AI05-0167-1}
{
AI05-0278-1}
The package System.Multiprocessors.Dispatching_Domains
and the aspect Dispatching_Domains are new.
Inconsistencies With Ada 2012
{
AI12-0033-1}
Corrigendum: We now explicitly allow empty
dispatching domains, as it would be difficult to avoid declaring them
when a system is configured at runtime. Therefore, assigning a task to
an empty domain now raises Dispatching_Domain_Error; creating such a
domain should not raise Dispatching_Domain_Error. If an implementation
does something different in these cases, and a program depends on that
difference, the program could malfunction. This seems very unlikely (if
no exception is ever raised, the task assigned to the empty domain could
never run; if the exception is raised earlier, the program can't do anything
useful).
Incompatibilities With Ada 2012
{
AI05-0033-1}
Corrigendum: The subtypes of the parameter
or result of several routines were changed to support empty domains.
These changes will cause rules requiring subtype conformance to fail
on these routines (such as 'Access). We believe such uses are unlikely.
In addition, type CPU_Set and function Get_CPU_Set, along with an overloaded
Create are newly added to this package. If Multiprocessors.Dispatching_Domains
is referenced in a
use_clause,
and an entity
E with the same
defining_identifier
as a new entity in this package is defined in a package that is also
referenced in a
use_clause,
the entity
E may no longer be use-visible, resulting in errors.
This should be rare and is easily fixed if it does occur.
Wording Changes from Ada 2012
{
AI12-0048-1}
Corrigendum: Added wording to clarify that all tasks can execute
on all CPUs of the system dispatching domain by default.
{
AI12-0082-1}
Corrigndum: Added a definition to clarify that a "dispatching
domain" is a concept which is identified by an object of type Dispatching_Domain;
more than one object might identify the same dispatching domain (for
instance, the result of function Get_Dispatching_Domain is a different
object but identifies the same dispatching domain).
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe