CVS difference for ai12s/ai12-0234-1.txt

Differences between 1.14 and version 1.15
Log of other versions for file ai12s/ai12-0234-1.txt

--- ai12s/ai12-0234-1.txt	2019/03/10 01:52:10	1.14
+++ ai12s/ai12-0234-1.txt	2019/03/12 04:55:53	1.15
@@ -1,7 +1,8 @@
-!standard C.6.1(0)                                  19-03-09  AI12-0234-1/05
+!standard C.6.1(0)                                  19-03-11  AI12-0234-1/06
 !standard C.6.2(0)
-!standard C.6.3(0)
 !class Amendment 17-06-09
+!status Amendment 1-2012 19-03-11
+!status ARG Approved 8-0-2  19-03-11
 !status work item 17-06-09
 !status received 17-05-19
 !priority Low
@@ -71,19 +72,15 @@
 
 !wording
 
-C.6.1 Atomic Operations
 
-This clause presents the specifications of the package Atomic_Operations and
-its child packages, which provide facilities for manipulating
-object of atomic types and for creating lock-free data types.
-The subprograms of these packages are Intrinsic subprograms (see 6.3.1)
-in order to provide convenient access to machine operations that can
-provide these capabilities if they are available in the target environment.
+C.6.1  The Package System.Atomic_Operations
 
-C.6.2  The Package System.Atomic_Operations
-
 The library package System.Atomic_Operations is the parent of a set of child
-units that provide facilities for manipulating objects of atomic types.
+units that provide facilities for manipulating objects of atomic types
+and for supporting lock-free synchronization.
+The subprograms of this subsystem are Intrinsic subprograms (see 6.3.1)
+in order to provide convenient access to machine operations that can
+provide these capabilities if they are available in the target environment.
 
 Static Semantics
 
@@ -98,15 +95,15 @@
 
 A call to a subprogram is said to be *lock-free* if the subprogram
 is guaranteed to return from the call while keeping the processor of
-logical thread of control busy for the duration of the call.
+the logical thread of control busy for the duration of the call.
 
 In each child package, a function Is_Lock_Free(...) is provided to check
 whether the operations of the child package can all be provided lock-free
 for a given object. Is_Lock_Free returns True if operations defined in
 the child package are lock-free when applied to the
-object denoted by Item, otherwise Is_LocK_Free returns False.
+object denoted by Item, and Is_Lock_Free returns False otherwise.
 
-C.6.3  The Generic Package System.Atomic_Operations.Exchange
+C.6.2  The Generic Package System.Atomic_Operations.Exchange
 
 The language-defined generic package System.Atomic_Operations.Exchange
 provides the following operations:
@@ -120,9 +117,6 @@
 
 Static Semantics
 
-The library function Ada.Atomic_Operations.Atomic_Compare_And_Exchange has the
-following declaration:
-
 The library package System.Atomic_Operations.Exchange has the
 following declaration:
 
@@ -135,32 +129,33 @@
                              Value : Atomic_Type) return Atomic_Type
      with Convention => Intrinsic;
 
-   function Atomic_Compare_And_Exchange (Item     : aliased in out Atomic_Type;
-                                         Expected : aliased in out Atomic_Type;
-                                         Desired  : Atomic_Type) return Boolean
+   function Atomic_Compare_And_Exchange (Item    : aliased in out Atomic_Type;
+                                         Prior   : aliased in out Atomic_Type;
+                                         Desired : Atomic_Type) return Boolean
      with Convention => Intrinsic;
 
    function Is_Lock_Free (Item : aliased Atomic_Type) return Boolean
      with Convention => Intrinsic;
 
-end Atomic_Operations.Exchange;
+end System.Atomic_Operations.Exchange;
 
-Atomic_Exchange writes the value denoted by Value into Item, and returns
-the previous value denoted by Item.
+Atomic_Exchange atomically assigns the value of Value to Item, and returns
+the previous value of Item.
 
-Atomic_Compare_And_Exchange compares the value denoted by Item with the
-value denoted by Expected. If equal, the operation is a read-modify-write
-operation that writes the value denoted by Desired into Item. If they are
-not equal, the operation is a read and the value denoted by Item is
-written into Expected.
-If Desired is written into Item then True is returned. Otherwise, False is returned.
+Atomic_Compare_And_Exchange compares the value of Item with the
+value of Prior. If equal, the operation is a read-modify-write
+operation that assigns the value of Prior to Item. If they are
+not equal, the operation is a read and the value of Item is
+assigned to Prior. If Prior is assigned to Item then True is 
+returned. Otherwise, False is returned.
 
 Examples
 
-Example of a spinlock using Atomic_Exchange
+Example of a spin lock using Atomic_Exchange
 
 type Atomic_Boolean is new Boolean with Atomic;
-package Exchange is new Atomic_Operations.Exchange (Atomic_Type => Atomic_Boolean);
+package Exchange is new 
+   Atomic_Operations.Exchange (Atomic_Type => Atomic_Boolean);
 
 Lock : aliased Atomic_Boolean := False;
 
@@ -168,15 +163,14 @@
 
 begin --  Some critical section, trying to get the lock:
 
-  --  Obtain the Spinlock
-  while (Exchange.Atomic_Exchange (Item => Lock, Value => Atomic_Boolean(True))
-  loop
+  --  Obtain the lock
+  while Exchange.Atomic_Exchange (Item => Lock, Value => True) loop
      null;
   end loop
 
   ... -- do stuff
 
-  lock := False; -- Release the lock
+  Lock := False; -- Release the lock
 end;
 
 !discussion
@@ -3392,6 +3386,78 @@
 anything).
 
 Of course, that will cause all of the numbers to shift, so I didn't do it now.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, March 11, 2019   9:37 PM
+
+I thought to ask this during the meeting, but we were talking about other 
+things and I forgot about it.
+
+The specification of the new package (after the changes of the meeting) is:
+
+generic
+   type Atomic_Type is private with Atomic;
+package System.Atomic_Operations.Exchange
+   with Pure, Nonblocking is
+
+   function Atomic_Exchange (Item  : aliased in out Atomic_Type;
+                             Value : Atomic_Type) return Atomic_Type
+     with Convention => Intrinsic;
+
+   function Atomic_Compare_And_Exchange (Item    : aliased in out Atomic_Type;
+                                         Prior   : aliased in out Atomic_Type;
+                                         Desired : Atomic_Type) return Boolean
+     with Convention => Intrinsic;
+
+   function Is_Lock_Free (Item : aliased Atomic_Type) return Boolean
+     with Convention => Intrinsic;
+
+end System.Atomic_Operations.Exchange;
+
+
+My understanding is that Value and Desired parameters are just values and are 
+not treated atomically. This is definitely the case if the actual type for 
+Atomic_Type is an elementary type.
+
+But what happens if Atomic_Type is a composite type? In that case, parameter 
+passing is by-reference, and thus Value and Desired seem to require atomic 
+reads. It's unlikely that any hardware operations actually do such an 
+operation atomically (the read would be separate from the rest of operation, 
+meaning the entire operation wouldn't quite be atomic), and we probably don't 
+want to insist that they are atomic WRT to the rest of the operation anyway.
+
+Do we need to say something about this case, in particular, that the reads of 
+Value/Desired are atomic but possibly separate from the rest of the operation.
+
+Actually, the problem seems to be the reverse. We never say what part of the 
+Compare_and_Swap operation is performed atomically. It can't be intended to 
+perform *all* of it that way -- I note that the Intel instruction only takes 
+one address, so there can only be one parameter (Item) whose operations are 
+fully atomic. The "Desired" and "Prior" parameters are in registers, so their 
+reads and writes clearly are separate from the core instruction. The wording 
+doesn't seem to make this distinction (which has to be done for the 
+by-reference case at a minimum).
+
+The current wording (after today's changes) is:
+
+  Atomic_Compare_And_Exchange compares the value of Item with the
+  value of Prior. If equal, the operation is a read-modify-write
+  operation that assigns the value of Prior to Item. If they are
+  not equal, the operation is a read and the value of Item is
+  assigned to Prior. If Prior is assigned to Item then True is
+  returned. Otherwise, False is returned.
+
+I don't know what a "read-modify-write" operation is, in normative Ada terms. 
+Maybe we should just describe it as "atomic"? Not sure if that's enough. (This
+is somewhat a problem with the test-and-set and arithmetic operations as well,
+they're described as being "atomic" -- we probably need to somehow describe 
+what is indivisible and what isn't. However, in those cases the parameters are
+guaranteed to be by-copy unless declared "aliased", so it should be clear that
+the values are not managed atomically.)
+
+Thoughts? Ideas? Randy's lost it? ;-)
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent