Ada Reference Manual (Ada 2022) — Legal Information

# D.16.1 Multiprocessor Dispatching Domains

1/3
This subclause allows implementations on multiprocessor platforms to be partitioned into distinct dispatching domains during program startup.

#### Static Semantics

2/3
The following language-defined library package exists:
3/5
with Ada.Real_Time;
with Ada.Task_Identification;
package System.Multiprocessors.Dispatching_Domains
with Nonblocking, Global => in out synchronized is
4/3
Dispatching_Domain_Error : exception;
5/3
type Dispatching_Domain (<>) is limited private;
6/3
System_Dispatching_Domain : constant Dispatching_Domain;
7/4
function Create (First : CPU; Last : CPU_Range) return Dispatching_Domain;
8/3
function Get_First_CPU (Domain : Dispatching_Domain) return CPU;
9/4
function Get_Last_CPU (Domain : Dispatching_Domain) return CPU_Range;
9.1/4
type CPU_Set is array(CPU range <>) of Boolean;
9.2/4
function Create (Set : CPU_Set) return Dispatching_Domain;
9.3/4
function Get_CPU_Set (Domain : Dispatching_Domain) return CPU_Set;
10/3
function Get_Dispatching_Domain
(T : Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task)
return Dispatching_Domain;
11/3
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);
12/3
procedure Set_CPU
(CPU : in CPU_Range;
T : in Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task);
13/3
function Get_CPU
(T : Ada.Task_Identification.Task_Id :=
Ada.Task_Identification.Current_Task)
return CPU_Range;
14/3
procedure Delay_Until_And_Set_CPU
(Delay_Until_Time : in Ada.Real_Time.Time; CPU : in CPU_Range);
15/3
private
... -- not specified by the language
end System.Multiprocessors.Dispatching_Domains;
16/4
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.
17/3
For a task type (including the anonymous type of a single_task_declaration), the following language-defined representation aspect may be specified:
18/3
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

19/3
The Dispatching_Domain aspect shall not be specified for a task interface.

#### Dynamic Semantics

20/4
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.
21/3
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.
22/4
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).
23/4
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.
24/4
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.
25/4
The function Get_Dispatching_Domain returns the dispatching domain on which the task is assigned.
26/4
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.
27/4
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.
28/3
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.
29/4
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

30/3
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.
30.1/4
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

31/3
Each dispatching domain should have separate and disjoint ready queues.

#### Documentation Requirements

32/3
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

33/3
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.
34/5
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