D.16.1 Multiprocessor Dispatching Domains
This subclause allows implementations on multiprocessor
platforms to be partitioned into distinct dispatching domains during
program startup.
Static Semantics
The following language-defined
library package exists:
with Ada.Real_Time;
with Ada.Task_Identification;
package System.Multiprocessors.Dispatching_Domains
with Nonblocking, Global =>
in out synchronized is
Dispatching_Domain_Error :
exception;
type Dispatching_Domain (<>)
is limited private;
System_Dispatching_Domain :
constant Dispatching_Domain;
function Create (First : CPU; Last : CPU_Range)
return Dispatching_Domain;
function Get_First_CPU (Domain : Dispatching_Domain)
return CPU;
function Get_Last_CPU (Domain : Dispatching_Domain)
return CPU_Range;
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;
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;
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.
For a task type (including
the anonymous type of a
single_task_declaration),
the following language-defined representation aspect may be specified:
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.
Legality Rules
The Dispatching_Domain aspect shall not be specified
for a task interface.
Dynamic Semantics
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.
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.
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).
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.
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.
The function Get_Dispatching_Domain returns the dispatching
domain on which the task is assigned.
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.
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.
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 domain (and is not Not_A_Specific_CPU).
Implementation Requirements
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.
Implementation Advice
Each dispatching domain should have separate and
disjoint ready queues.
Documentation Requirements
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.
Implementation Permissions
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
parallel construct.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe