D.16.1 Multiprocessor Dispatching Domains
This subclause allows implementations on multiprocessor platforms to
be partitioned into distinct dispatching domains during program startup.
The following language-defined library package exists:
with Nonblocking, Global => in out synchronized is
Dispatching_Domain_Error : exception
Dispatching_Domain (<>) is limited private
System_Dispatching_Domain : constant
Create (First, Last
: CPU; Last : CPU_Range
Get_First_CPU (Domain : Dispatching_Domain) return
Get_Last_CPU (Domain : Dispatching_Domain) return CPU_Range CPU
type CPU_Set is array(CPU range <>) of Boolean;
function Create (Set : CPU_Set) return Dispatching_Domain;
function Get_CPU_Set (Domain : Dispatching_Domain) return CPU_Set;
(T : Ada.Task_Identification.Task_Id :=
(Domain : in out
CPU : in
CPU_Range := Not_A_Specific_CPU;
T : in
(CPU : in
T : in
(T : Ada.Task_Identification.Task_Id :=
(Delay_Until_Time : in
Ada.Real_Time.Time; CPU : in
... -- not specified by the language
A dispatching domain The
represents a set series
of processors on which a task may execute. Each processor is contained
within exactly one dispatching domain Dispatching_Domain
An object of type Dispatching_Domain identifies
a dispatching domain.
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 System_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
Aspect Description for Dispatching_Domain:
Domain (group of processors) on which a given task should run.
The Dispatching_Domain aspect shall not be specified for a task interface.
The expression specified for the Dispatching_Domain aspect of a task
is evaluated each
time an object of the task type is created for
each task object
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 The
Dispatching_Domain value is then associated with the task object whose
task declaration specifies the aspect
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
If both the dispatching domain Dispatching_Domain
and CPU are specified for a task, and the CPU value is not contained
within the set range
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
The function Create with First and Last parameters
creates and returns a dispatching domain 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.
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.
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 one
The function Get_Dispatching_Domain returns the dispatching
the task is assigned.
A call of the procedure Assign_Task assigns task T to the CPU within
the dispatching domain 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
T is already assigned to a dispatching
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
that is already assigned
to that domain
has no effect.
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
. The exception
Dispatching_Domain_Error is propagated if CPU is not one of the processors
of the dispatching domain 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
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.
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
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.
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.
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
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.
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:
“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.
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.
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.
The implementation may defer the effect of a Set_CPU
or an Assign_Task operation until the specified task leaves an ongoing
These operations can change the set of CPUs that
a parallel operation is allowed to use. This could require the ability
to move or suspend one or more threads to execute them on a different
CPU. However, parallel constructs are primarily intended to improve performance
of code, and the overhead needed to support such a rarely used operation
could be substantial. Therefore, rather than requiring support we allow
the implementation to wait to implement these operations until the parallel
construct (and thus the extra threads) have completed.
Extensions to Ada 2005
The package System.Multiprocessors.Dispatching_Domains
and the aspect Dispatching_Domains are new.
Inconsistencies With Ada 2012
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
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. As
such, a use clause conflict is possible; see the introduction of Annex
A for more on this topic. 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
Corrigendum: Added wording to clarify that
all tasks can execute on all CPUs of the system dispatching domain by
Corrigendum: 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