CVS difference for ai05s/ai05-0167-1.txt

Differences between 1.5 and version 1.6
Log of other versions for file ai05s/ai05-0167-1.txt

--- ai05s/ai05-0167-1.txt	2010/10/19 03:13:37	1.5
+++ ai05s/ai05-0167-1.txt	2011/01/25 05:47:49	1.6
@@ -1,4 +1,4 @@
-!standard  D.16.1                               10-10-18    AI05-0167-1/04
+!standard  D.16.1                               11-01-23    AI05-0167-1/05
 !standard  C.3.2
 !class Amendment 09-10-22
 !status work item 09-10-22
@@ -11,15 +11,15 @@
 
 Facilities are provided to allow a multiprocessor platform to be
 partitioned into a number of non-overlapping dispatching domains (DDs).
-Every task is scheduled within a DD. A task may also be assigned
-to execute on just one CPU from within its DD.
+Every task is scheduled within a DD. A task may also be assigned to
+execute on just one CPU from within its DD.
 
 !problem
 
 An increasing number of embedded applications are now executed on
 multiprocessor and multicore platforms. For non-real-time programs
-it is usually acceptable for the mapping of tasks to CPUs to
-be implementation defined and hidden from the program. For real-time
+it is usually acceptable for the mapping of tasks to CPUs to be
+implementation defined and hidden from the program. For real-time
 programs it may not be acceptable for the mapping of tasks to CPUs
 to be hidden from the program.
 
@@ -40,14 +40,16 @@
 
 
 The following package (and pragma CPU) is defined in AI05-171:
+
+   package System.Multiprocessors is
+      pragma Preelaborate(Multiprocessors);
+
+      type CPU_Range is range 0 .. <implementation-defined>;
+      Not_A_Specific_CPU : constant CPU_Range := 0;
+      subtype CPU is CPU_Range range 1 .. CPU_Range'Last;
 
-package System.Multiprocessors is
-  pragma Preelaborate(Multiprocessors);
-  type CPU_Range is range 0 .. <implementation-defined>;
-  Not_A_Specific_CPU : constant CPU_Range := 0;
-  subtype CPU is CPU_Range range 1 .. CPU_Range'Last;
-  function Number_Of_CPUs return CPU;
-end System.Multiprocessors;
+      function Number_Of_CPUs return CPU;
+   end System.Multiprocessors;
 
 
 The details of the proposal are contained in !wording.
@@ -57,13 +59,13 @@
 
 All dispatching domains have the same range of priorities System.Any_Priority.
 
-There is a default dispatching domain that initially contains
-all the processors and on which the environment task executes.
-All tasks will therefore execute on this domain unless they
-contain a CPU or Dispatching_Domain pragma. A task executing in
-the default domain can be assigned to another dispatching domain.
-A task will always activate in the dispatching domain of its
-activating task (as the activating task will be blocked).
+There is a default dispatching domain that initially contains all
+the processors and on which the environment task executes. If no
+tasks are explicitly assigned to other domains, then all tasks will
+execute on this default domain. A task executing in the default
+domain can be assigned to another dispatching domain. A task will
+always activate in the dispatching domain of its activating task (as
+the activating task will be blocked).
 
 For protected objects there is no need for affinities, it is the
 tasks that have domains and possibly an assigned CPU. PO code
@@ -77,8 +79,9 @@
 
 D.16.1 Multiprocessor Dispatching Domains
 
-This clause allows implementations on multiprocessor platforms to
-be partitioned into distinct dispatching domains.
+This clause allows implementations on multiprocessor platforms to be
+partitioned into distinct dispatching domains during program
+startup.
 
 Static Semantics
 
@@ -86,6 +89,7 @@
 
 with Ada.Real_Time;
 package System.Multiprocessors.Dispatching_Domains is
+   pragma Preelaborate(Dispatching_Domains);
 
    Dispatching_Domain_Error : exception;
 
@@ -95,32 +99,32 @@
 
    function Create(First, Last : CPU) return Dispatching_Domain;
 
-   function Get_First_CPU(DD : Dispatching_Domain) return CPU;
+   function Get_First_CPU(Domain : Dispatching_Domain) return CPU;
 
-   function Get_Last_CPU(DD : Dispatching_Domain) return  CPU;
+   function Get_Last_CPU(Domain : Dispatching_Domain) return CPU;
 
    function Get_Dispatching_Domain(T : Task_Id := Current_Task)
             return Dispatching_Domain;
 
-   procedure Assign_Task(DD  : in out Dispatching_Domain;
-                           P : in CPU_Range := Not_A_Specific_CPU;
-                           T : in Task_Id := Current_Task);
+   procedure Assign_Task(Domain : in out Dispatching_Domain;
+                         CPU : in CPU_Range := Not_A_Specific_CPU;
+                         T : in Task_Id := Current_Task);
 
-   procedure Set_CPU(P : in CPU_Range; T : in Task_Id := Current_Task);
+   procedure Set_CPU(CPU : in CPU_Range; T : in Task_Id := Current_Task);
 
    function Get_CPU(T : in Task_Id := Current_Task) return CPU_Range;
 
    procedure Delay_Until_And_Set_CPU(
-       Delay_Until_Time : in Ada.Real_Time.Time; P : in CPU_Range);
+       Delay_Until_Time : in Ada.Real_Time.Time; CPU : in CPU_Range);
 
 private
-  -- not defined by the language
+   ... -- not specified by the language
 end System.Multiprocessors.Dispatching_Domains;
 
 The type Dispatching_Domain represents a series of processors on which a task
 may execute. Each processor is contained within exactly one Dispatching_Domain.
 System_Dispatching_Domain contains the processor or processors on which the
-environmental task executes. At program start-up all processors are contained
+environment task executes. At program start-up all processors are contained
 within System_Dispatching_Domain.
 
 
@@ -140,63 +144,82 @@
 Legality Rules
 
 A Dispatching_Domain pragma is allowed only immediately within a
-task_definition. At most one such pragma shall appear within a
-given construct.
+task_definition. At most one such pragma shall appear within a given
+task_definition.
 
 Dynamic Semantics
-
-The Dispatching_Domain value, indicated by the use of pragma
-Dispatching_Domain, determines the dispatching domain on
-which the task will execute; the task is said to be assigned to that
-Dispatching_Domain. A task will activate on the dispatching
-domain of its activating task. A task without a Dispatching_Domain pragma
-will activate and execute on the same dispatching domain as its activating
-task.
-
-If a task contains a CPU pragma and a
-Dispatching_Domain pragma, and the CPU value is not contained within
-the range of processors for the Dispatching_Domain value (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(1)).
-
-The function Create creates and returns a Dispatching_Domain containing all
-the processors in the range First .. Last. These processors are removed from
-System_Dispatching_Domain. A call of Create will cause the exception
-Dispatching_Domain_Error to be propagated 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.
-
-Calls to Create can only be made from the environment task prior to the call
-of the main subprogram.
 
-The function Get_First_CPU returns the number of the first processor in DD.
+A pragma Dispatching_Domain assigns the task to the specified domain. During
+activation, a task executes in the domain of the activating task; afterward, it
+executes in the domain to which it is assigned. If the task is not assigned to
+any domain, it executes in that of the activating task.
+
+[Author's question:
+
+The above matches my understanding of the minutes, but I'm still having trouble
+with it. Activation is over when a task reaches its "begin" -- do we really want
+to insist that it move to a different domain, and therefore a different CPU, at
+that time? Suppose we say:
+
+    Assign_Task(DD_3, CPU_7, My_Task);
+
+And suppose My_Task is then activated by the environment task, which is running
+in System_Dispatching_Domain, on CPU_2. So during activation, My_Task runs in
+System_Dispatching_Domain, but it certainly can't run on CPU_7, because that's
+part of DD_3.  But that contradicts the semantics of Assign_Task below.
+
+To me it seems much simpler if a task is assigned to a domain once and for all
+(doesn't switch domains at the "begin"), and always runs on its assigned CPU
+(before and after "begin"), and that CPU is always part of that domain.  (Except
+the Not_A_Specific_CPU case, of course).  We can change CPU affinity, but not
+the domain, of a task, right?
+
+End Author's Question]
+
+If a task contains a CPU pragma and a Dispatching_Domain pragma, and the CPU
+value is not contained within the range of processors for the Dispatching_Domain
+value (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(1)).
+
+The function Create creates and returns a Dispatching_Domain containing all the
+processors in the range First .. Last. 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
+after the call to the main subprogram.
+
+[Author's Question: Is that last sentence what we want?  The minutes say
+"Program_Error", but everything else here raises Dispatching_Domain_Error, so I
+used that. But more importantly: It's OK to create domains after tasks start
+running? And it's bad to create domains in the main procedure?]
 
-The function Get_Last_CPU returns the number of the last processor in DD.
+The function Get_First_CPU returns the first CPU in Domain; Get_Last_CPU
+returns the last one.
 
 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 processor P within
-Dispatching_Domain DD. Task T can now execute only on processor P unless
-P designates Not_A_Specific_CPU, in which case it can execute on any processor
-within DD. The exception Dispatching_Domain_Error is propagated if T is already
-assigned to a Dispatching_Domain other than System_Dispatching_Domain, or
-if P is not one of the processors of DD (and is not Not_A_Specific_CPU).
-A call of Assign_Task is a task dispatching point for task T. If T is
-the Current_Task the effect is immediate, otherwise the effect is as
-soon as practical. Assigning a task to System_Dispatching_Domain that is
-already assigned to that domain has no effect.
-
-A call of procedure Set_CPU assigns task T to processor P.
-Task T can now execute only on processor P, unless P 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 P 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. If T is
-the Current_Task the effect is immediate, otherwise the effect is as
+A call of the procedure Assign_Task assigns task T to the CPU within
+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 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. If T is the Current_Task the effect is immediate, otherwise the effect is as
+soon as practical. Assigning a task to System_Dispatching_Domain 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_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.
+If T is the Current_Task the effect is immediate, otherwise the effect is as
 soon as practical.
 
 The function Get_CPU returns the processor assigned to task T, or
@@ -209,7 +232,7 @@
 of the calling task's Dispatching_Domain (and is not Not_A_Specific_CPU).
 
 
-Implementation Requirement
+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
@@ -226,7 +249,7 @@
 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 range of processors.
+also document this set of processors.
 
 
 Implementation Permissions
@@ -243,12 +266,12 @@
 with System.Multiprocessors;
 
 
-function Get_CPU(I: Interrupt_Id) return System.Multiprocessors.CPU_Range;
+function Get_CPU(Interrupt: Interrupt_Id) return System.Multiprocessors.CPU_Range;
 
 
-The function Get_CPU returns the processor on which the handler for I is
-executed. If the handler can execute on more than one processor the
-value System.Multiprocessors.Not_A_Specific_CPU is returned.
+The function Get_CPU returns the processor on which the handler for Interrupt is
+executed. If the handler can execute on more than one processor the value
+System.Multiprocessors.Not_A_Specific_CPU is returned.
 
 
 !discussion
@@ -365,7 +388,7 @@
 
 The following is an earlier version of the package that
 supports the creation of dispatching domains (DDs).
-One DD is defined to be the 'System' DD; the environmental task
+One DD is defined to be the 'System' DD; the environment task
 and any derived from that task are allocated to the 'System' DD.
 
 The collection of CPUs, represented by an integer ordering
@@ -445,7 +468,7 @@
 the `System' dispatching domain to this new domain. A CPU cannot be
 moved if it has a task assigned to it. The `System' dispatching
 domain must not be emptied of CPUs as it always contains the
-environmental task.
+environment task.
 
 Get_First_CPU -- returns the number of the first CPU in the domain.
 Get_Last_CPU -- returns the number of the last CPU in the domain.
@@ -491,6 +514,89 @@
 
 
 !appendix
+
+From: Bob Duff
+Sent: Sunday, January 23, 2011 5:30 PM
+
+New version of AI05-0167-1, Managing affinities for programs executing on
+multiprocessors. [Editor's note: This is version /05 of this AI.]
+
+I basically did what the minutes say, but:
+
+(Alan, and everybody, see "???" below.)
+
+Where does the name "system DD" come from?
+
+   System_Dispatching_Domain : constant Dispatching_Domain;
+
+Seems like "default" would be a better name for it, and seems like "dispatching"
+is unnecessary noise.  So how about:
+
+   Default_Domain : constant Dispatching_Domain;
+
+?
+
+> Tucker suggests rewording:
+>
+> ?The exception Dispatching_Domain_Error is propagated if T is already
+> assigned to a Dispatching_Domain other than System_Dispatching_Domain,
+> or if P is not one of the processors of DD (and is not
+> Not_A_Specific_CPU); assigning a task to the System_Dispatching_Domain
+> has no effect.? And drop the last sentence.
+
+I don't see how that makes sense.  If a task is already assigned to some
+non-system domain, then attempting to assign it back to the system domain should
+be an error, shouldn't it?
+
+Dynamic Semantics
+
+A pragma Dispatching_Domain assigns the task to the specified domain.
+During activation, a task executes in the domain of the activating task; afterward, it executes in the domain to which it is assigned.
+If the task is not assigned to any domain, it executes in that of the activating task.
+
+----------------
+
+???The above matches my understanding of the minutes, but I'm still having
+trouble with it. Activation is over when a task reaches its "begin" -- do we
+really want to insist that it move to a different domain, and therefore a
+different CPU, at that time? Suppose we say:
+
+    Assign_Task(DD_3, CPU_7, My_Task);
+
+And suppose My_Task is then activated by the environment task, which is running
+in System_Dispatching_Domain, on CPU_2. So during activation, My_Task runs in
+System_Dispatching_Domain, but it certainly can't run on CPU_7, because that's
+part of DD_3.  But that contradicts the semantics of Assign_Task below.
+
+To me it seems much simpler if a task is assigned to a domain once and for all
+(doesn't switch domains at the "begin"), and always runs on its assigned CPU
+(before and after "begin"), and that CPU is always part of that domain.  (Except
+the Not_A_Specific_CPU case, of course).  We can change CPU affinity, but not
+the domain, of a task, right?
+
+----------------
+
+If a task contains a CPU pragma and a Dispatching_Domain pragma, and the CPU
+value is not contained within the range of processors for the Dispatching_Domain
+value (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(1)).
+
+The function Create creates and returns a Dispatching_Domain containing all the
+processors in the range First .. Last. 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
+after the call to the main subprogram.
+
+???Is that last sentence what we want?  The minutes say "Program_Error", but
+everything else here raises Dispatching_Domain_Error, so I used that.  But more
+importantly: It's OK to create domains after tasks start running?  And it's bad
+to create domains in the main procedure?
+
+
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent