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

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

--- ai12s/ai12-0234-1.txt	2018/06/16 03:03:27	1.9
+++ ai12s/ai12-0234-1.txt	2019/03/06 03:20:41	1.10
@@ -10,7 +10,7 @@
 !problem
 
 On multiprocessor platforms, relying on locks for synchronization can be problematic.
-One issue is that while a task is blocked, it can be difficult or impossible to 
+One issue is that while a task is blocked, it can be difficult or impossible to
 offer guarantees for progress.  Other problems associated with locks includes
 deadlock, livelock, and priority inversion. Locking can also be a significant
 detriment to performance, and reduce opportunities for parallelism.
@@ -18,17 +18,17 @@
 Lock-free data structures guarantee system-wide progress, while wait-free
 data structures, in addition to being lock-free, also guarantee per-thread progresss.
 
-Lock-free data structures can also be used to improve performance by increasing 
-the amount of time spent executing in parallel since access to the data structure 
+Lock-free data structures can also be used to improve performance by increasing
+the amount of time spent executing in parallel since access to the data structure
 does not need to be serialised.
 
-If one wanted to construct such a structure in Ada, one might use Atomic objects. 
-But Ada does not provide any compare-and-swap operation (or other read-write locked 
+If one wanted to construct such a structure in Ada, one might use Atomic objects.
+But Ada does not provide any compare-and-swap operation (or other read-write locked
 operations, like atomic increment). The RM has Implementation Advice that package
 Machine_Code include such operations - C.1(11-12), but that is the absolute
-opposite of a portable operation. One could write such a library in another 
+opposite of a portable operation. One could write such a library in another
 language such as C and call that library from Ada, but then that involves at
-least one subprogram call in addition to a single instruction insertion, 
+least one subprogram call in addition to a single instruction insertion,
 which is significantly higher overhead than what might be desired, and having
 to rely on the existence of other languages for a given target is also undesirable
 and less portable. Should Ada provide some simple primitives
@@ -37,18 +37,18 @@
 
 !proposal
 
-The solution is to provide a set of standard library calls that map to commonly 
+The solution is to provide a set of standard library calls that map to commonly
 available atomic hardware instructions such as compare and swap,
-test and set, and atomic increment. These subprograms are to be intrinsic calls, 
-and the generic libraries will assert an error if a particular target platform 
+test and set, and atomic increment. These subprograms are to be intrinsic calls,
+and the generic libraries will assert an error if a particular target platform
 does not support such atomic operations.
 
-The libraries are generic libraries in order to support operations on discrete 
-types of different sizes, and we require that the actual types for the generics 
+The libraries are generic libraries in order to support operations on discrete
+types of different sizes, and we require that the actual types for the generics
 be  atomic types, so that Ada's semantics of atomic types can be associated
 with these primitive operations.
 
-This proposal depends on the ability to specify the Atomic aspect for a generic 
+This proposal depends on the ability to specify the Atomic aspect for a generic
 formal type (AI12-0282-1). This is needed to ensure that the actual types used
 to instantiate the generic libraries defined by this AI are atomic types.
 
@@ -56,17 +56,17 @@
 
 A.19 Atomic Operations
 
-This clause presents the specifications of the package Atomic_Operations and 
+This clause presents the specifications of the package Atomic_Operations and
 several child packages, which provide facilities for atomically manipulating discrete
 types, and for creating lock-free data types.
 
 A.19.1  The Package Atomic_Operations
 
 The package Atomic_Operations is the root of the atomic operations subsystem.
- 
+
 Static Semantics
 
-The library package Atomic_Operations has the following declaration: 
+The library package Atomic_Operations has the following declaration:
 
 with System.Storage_Elements;
 
@@ -83,7 +83,7 @@
    --    with Atomic, Size => System.Storage_Elements.Storage_Element'Size;
 
    Atomic_Support_Error : exception;
-   
+
    function Atomic_Test_And_Set (Item : aliased in out Test_And_Set_Type) return Boolean
      with Convention => Intrinsic
      with Post => Item /= 0;
@@ -97,19 +97,19 @@
 
    procedure Atomic_Signal_Fence
      with Convention => Intrinsic;
-   
+
 end Ada.Atomic_Operations;
 
 
 Test_And_Set_Type represents the resulting state of a call to Atomic_Test_And_Set.
 
-Atomic_Support_Error is raised during elaboration of a child package of 
+Atomic_Support_Error is raised during elaboration of a child package of
 Ada.Atomic_Operations if the implementation cannot map the instantiation to
 atomic operations of the target system.
 
 function Atomic_Test_And_Set (Item : aliased in out Test_And_Set_Type) return Boolean
   with Convention => Intrinsic;
-     
+
 Performs an atomic test-and-set operation on Item. Item is set to some
 implementation defined "set" value and the return value is True
 if and only if the previous contents were "set".
@@ -130,7 +130,7 @@
 
 This procedure acts as a synchronization fence between a thread and
 signal handlers in the same thead.
-   
+
 A.19.2  The Generic Package Atomic_Operations.Storage
 
 The language-defined generic package Atomic_Operations.Storage provides a set of
@@ -203,14 +203,14 @@
 When in doubt, use the strong variation.
 If Desired is written into Item then True is returned. Otherwise, False is returned.
 
-Returns True if objects always generate lock-free atomic instructions for the 
+Returns True if objects always generate lock-free atomic instructions for the
 target architecture.
 
 function Atomic_Always_Lock_Free (Item : aliased Atomic_Type) return Boolean
 with Convention => Intrinsic;
 
-Returns True if objects always generate lock-free atomic instructions for the 
-target architecture. Item may be used ot determine alignment. The compiler may 
+Returns True if objects always generate lock-free atomic instructions for the
+target architecture. Item may be used ot determine alignment. The compiler may
 also ignore this parameter.
 
 function Atomic_Is_Lock_Free (Item : aliased Atomic_Type) return Boolean;
@@ -220,7 +220,7 @@
 
 A.19.3  The Generic Package Atomic_Operations.Signed_Arithmetic
 
-The language-defined generic package Atomic_Operations.Signed_Arithmetic 
+The language-defined generic package Atomic_Operations.Signed_Arithmetic
 provides a set of operations for adding and subtracting values atomically to
 signed integer types.
 
@@ -275,8 +275,8 @@
 
 A.19.4  The Generic Package Atomic_Operations.Modular_Arithmetic
 
-The language-defined generic package Atomic_Operations.Modular_Arithmetic 
-provides a set of operations for atomically adding, subtracting, and  
+The language-defined generic package Atomic_Operations.Modular_Arithmetic
+provides a set of operations for atomically adding, subtracting, and
 bitwise manipulation, for modular integer types.
 
 generic
@@ -401,7 +401,7 @@
 
 Many lock free algorithms involve atomic primitives such as compare and swap
 instructions or load and store instuctions. Most target platforms provide some
-form of instruction of these category. A limitation of these instructions is 
+form of instruction of these category. A limitation of these instructions is
 that they typically can only be applied to a single elementary integer type of
 1, 2, 4, or 8 bytes in size.
 
@@ -412,7 +412,7 @@
 The C and C++ memory model support several different memory orders. The most
 restrictive memory order is called sequentially consistent, where all threads
 are synchronised such that updates to shared variables are seen by all threads,
-and the order seen by all threads is the same. Due to the higher level of 
+and the order seen by all threads is the same. Due to the higher level of
 synchronisation, this is also the most inefficient memory order, but it is the
 default memory order because it is the safest, and produces the least number
 of surprising results. Moving towards lower level of synchronisation,there are
@@ -426,15 +426,15 @@
 memory order in theory should be able to write more efficient code, though it is
 can be much trickier to get code to work properly, since there are more unexpected
 behaviours due to the lack of synchronisation between threads. One other point
-that should be mentioned is that these atomic primitives would need to be 
+that should be mentioned is that these atomic primitives would need to be
 have the Intrinsic convention, because they can require the disabling of certain
 compiler optimisations, such as hoisting or sinking code across boundaries where
 atomic primitives are being used. For instance the Acquire/Release memory order
 has this requirement in particular.
 
-For the approach of this AI, it probably would be best for now to not bother 
-with supporting the lower synchronisation memory orders, and instead provide a 
-library which implicitly assumes the sequentially consistent memory order, 
+For the approach of this AI, it probably would be best for now to not bother
+with supporting the lower synchronisation memory orders, and instead provide a
+library which implicitly assumes the sequentially consistent memory order,
 which is both safer to use, and easier to understand.
 
 The library of intrinsic primitives might be of interest to those wishing to
@@ -443,9 +443,9 @@
 
 We considered whether these libraries should be "future proofed" by providing
 an extra parameter for the memory model. The type of that parameter could be
-an enumeration which for now only contains Sequentially_Consistent, but could 
-be extended in the future to name other memory models. We decided that 
-there is not likely to be backwards compatibility issues since these are 
+an enumeration which for now only contains Sequentially_Consistent, but could
+be extended in the future to name other memory models. We decided that
+there is not likely to be backwards compatibility issues since these are
 intrinsic suprograms. For example, they cannot be passed as actual subprograms
 to generic libraries. Also, if needed, in the future we could add overloaded
 calls to these libraries that accept a memory order parameter, without introducing
@@ -1166,15 +1166,15 @@
 From: Erhard Ploedereder
 Sent: Thursday, March 29, 2018  9:34 PM
 
-No doubt. We always can implement everything in software, but is that what the 
+No doubt. We always can implement everything in software, but is that what the
 user wants? Surely, if he is trying to write a lock-free programm, he is going
 to be pissed to find that compare-and-swap was implementended with a lock or
 semaphore. This is not just a performance question. It also impacts issues
 like risk of priority inversion and anything that relates to blocking.
 
-His usual route is to provide a target-dependent solution. It will look a bit 
+His usual route is to provide a target-dependent solution. It will look a bit
 different, depending on which operation is available that is synchronized by
-the memory bus. He sure would hate not to be told that his compare-and-swap 
+the memory bus. He sure would hate not to be told that his compare-and-swap
 is not mapped to such an operation. If the compiler is mum about this, there
 is a good chance that the issue is not discovered during porting of the
 software.
@@ -1192,7 +1192,7 @@
 From: Randy Brukardt
 Sent: Thursday, March 29, 2018  11:05 PM
 
-> No doubt. We always can implement everything in software, but is that 
+> No doubt. We always can implement everything in software, but is that
 > what the user wants?
 
 It clearly depends on the user. If the user is just using atomics as the
@@ -1200,43 +1200,43 @@
 that they care how it is implemented. For the expert...
 
 > Surely, if he is trying to write
-> a lock-free programm, he is going to be pissed to find that 
+> a lock-free programm, he is going to be pissed to find that
 > compare-and-swap was implementended with a lock or semaphore.
-> This is not just a performance question. It also impacts issues like 
+> This is not just a performance question. It also impacts issues like
 > risk of priority inversion and anything that relates to blocking.
 
 Understood. But as Bob notes, that's how C does it. Not that that is the best
-example :-), but it at least seems to give a data point that it's acceptable 
+example :-), but it at least seems to give a data point that it's acceptable
 to some part of the community.
 
-> His usual route is to provide a target-dependent solution. It will 
-> look a bit different, depending on which operation is available that 
+> His usual route is to provide a target-dependent solution. It will
+> look a bit different, depending on which operation is available that
 > is synchronized by the memory bus.
-> He sure would hate not to be told that his compare-and-swap is not 
-> mapped to such an operation. If the compiler is mum about this, there 
-> is a good chance that the issue is not discovered during porting of 
+> He sure would hate not to be told that his compare-and-swap is not
+> mapped to such an operation. If the compiler is mum about this, there
+> is a good chance that the issue is not discovered during porting of
 > the software.
 
-Compilers that are mum violate the Standard. Unfortunately, there's no good 
+Compilers that are mum violate the Standard. Unfortunately, there's no good
 way to enforce that rule.
- 
-> So, I would have less problems with a set of procedures that 
-> encapsulated the particular primitives, combined with a mandate to 
-> support all that match a bus-synchronized operation and a mandate to 
+
+> So, I would have less problems with a set of procedures that
+> encapsulated the particular primitives, combined with a mandate to
+> support all that match a bus-synchronized operation and a mandate to
 > REJECT calls to any for which said operation does not exist.
 
-The problem is I don't think we can do that in the Standard, since there is 
-zero chance that we could formally define what a "bus-synchronized operation" 
-is. And any Legality Rule requires that. Moreover, such a rule isn't testable 
-by the ACATS (it does not allow looking at generated code), so it would be 
+The problem is I don't think we can do that in the Standard, since there is
+zero chance that we could formally define what a "bus-synchronized operation"
+is. And any Legality Rule requires that. Moreover, such a rule isn't testable
+by the ACATS (it does not allow looking at generated code), so it would be
 effectively meaningless. (And given my experience, probably not enforced by a
 large number of compilers.)
 
-We could (as Robert Dewar used to note) write Implementation Advice to that 
+We could (as Robert Dewar used to note) write Implementation Advice to that
 effect. But that hardly seems better than the original option.
- 
-> A software emulation of these instructions that is not lock- and 
-> wait-free ist the worst of all solutions for embedded systems with 
+
+> A software emulation of these instructions that is not lock- and
+> wait-free ist the worst of all solutions for embedded systems with
 > deadlines.
 
 The only other option that makes sense to me is to forget the atomic library
@@ -1252,38 +1252,38 @@
 From: Edward Fish
 Sent: Thursday, March 29, 2018  11:32 PM
 
-> No doubt. We always can implement everything in software, but is that 
+> No doubt. We always can implement everything in software, but is that
 > what the user wants? [...] His usual route is to provide a target-dependent
 > solution.
 
-I think the user would typically want general, portable code rather than 
+I think the user would typically want general, portable code rather than
 target-dependent without some indicator/specifier that some dependent form is
 needed; as an example records and representations. If there is not
 representation, then I generally assume that the form sought structure-wise is
-more in the ideal plane than not, whereas with a representation-specification 
-the particulars matter to the point where "ideal" isn't possible. (e.g. When 
+more in the ideal plane than not, whereas with a representation-specification
+the particulars matter to the point where "ideal" isn't possible. (e.g. When
 you're interfacing with foreign programs/protocols and have to have field A of
 x-bits, field B of y-bits, 2-bits padding, and field C of 14-bits.)
 
-> It will look a bit different, depending on which operation is 
+> It will look a bit different, depending on which operation is
 > available that is synchronized by the memory bus.
-> He sure would hate not to be told that his compare-and-swap is not 
-> mapped to such an operation. If the compiler is mum about this, there 
-> is a good chance that the issue is not discovered during porting of 
+> He sure would hate not to be told that his compare-and-swap is not
+> mapped to such an operation. If the compiler is mum about this, there
+> is a good chance that the issue is not discovered during porting of
 > the software.
 
 But there's the crux of the issue: should a compare-and-swap be in error in an
-ISA which doesn't have a compare-and-swap instruction? or should the compiler 
+ISA which doesn't have a compare-and-swap instruction? or should the compiler
 construct the proper SW-construct? -- If such low-level controls are required,
 Ada *DOES* allow for instruction-insertion, albeit implementation-defined.
 
-> So, I would have less problems with a set of procedures that 
-> encapsulated the particular primitives, combined with a mandate to 
-> support all that match a bus-synchronized operation and a mandate to 
+> So, I would have less problems with a set of procedures that
+> encapsulated the particular primitives, combined with a mandate to
+> support all that match a bus-synchronized operation and a mandate to
 > REJECT calls to any for which said operation does not exist.
 >
-> A software emulation of these instructions that is not lock- and 
-> wait-free ist the worst of all solutions for embedded systems with 
+> A software emulation of these instructions that is not lock- and
+> wait-free ist the worst of all solutions for embedded systems with
 > deadlines.
 
 It looks like there's a bit of tension between (a) general purpose and
@@ -1296,11 +1296,11 @@
 Sent: Thursday, March 29, 2018  11:55 PM
 
 ...
-> No doubt. We always can implement everything in software, but is that 
-> what the user wants? Surely, if he is trying to write a lock-free 
-> programm, he is going to be pissed to find that compare-and-swap was 
+> No doubt. We always can implement everything in software, but is that
+> what the user wants? Surely, if he is trying to write a lock-free
+> programm, he is going to be pissed to find that compare-and-swap was
 > implementended with a lock or semaphore.
-> This is not just a performance question. It also impacts issues like 
+> This is not just a performance question. It also impacts issues like
 > risk of priority inversion and anything that relates to blocking.
 
 BTW, could you provide a reference that a relative (but not complete) newby
@@ -1330,40 +1330,40 @@
 The tasks are periodic, i.e., released at some time intervals.
 
 T1 runs, grabs said lock to perform the software-emulated compare-and-swap,
-but before it is done with it, T4 is released by time-tigger, preempts T1, 
+but before it is done with it, T4 is released by time-tigger, preempts T1,
 runs a bit - meanwhile T2 and T3 are released, too.
 
 Then T4 asks for the same lock, but can't get it. Shucks. Needs to wait until
-T1 finishes with the CAS. But T2 and T3 have higher priority than T1. So, T1 
-needs to wait until T2 and T3 have finished their work. Then, much later, T1 
+T1 finishes with the CAS. But T2 and T3 have higher priority than T1. So, T1
+needs to wait until T2 and T3 have finished their work. Then, much later, T1
 gets to run, completes the CAS and releases the lock.
 Then, finally, T4 gets to do its CAS.
 
-Now, there was a reason for T4 having high priority, namely, the fact that it 
-has the tightest deadline (a general principle in fixed-priority embedded 
-scheduling, known to be optimal). Which is likely to be long past in the 
+Now, there was a reason for T4 having high priority, namely, the fact that it
+has the tightest deadline (a general principle in fixed-priority embedded
+scheduling, known to be optimal). Which is likely to be long past in the
 scenario above.
 
-It T4 controls the brakes in your car, you no longer perceive this as being 
-merely a performance issue. Dead people do not reflect on such things any 
+It T4 controls the brakes in your car, you no longer perceive this as being
+merely a performance issue. Dead people do not reflect on such things any
 more.
 
-You just saw a priority inversion in action (named so, because T4 behaves for 
-a while as if it had lowest priority 1). There are scheduling schemes that 
+You just saw a priority inversion in action (named so, because T4 behaves for
+a while as if it had lowest priority 1). There are scheduling schemes that
 avoid priority inversion, but only if the locks are a concept provided by the
-run-time system and well understood by the scheduler  (ICPP, OCPP, Priority 
+run-time system and well understood by the scheduler  (ICPP, OCPP, Priority
 Inheritance, ... Deadline-floor protocol, etc.)
 
-You can't find these buggers by testing, because they are highly intermittent, 
-i.e., things need to happen at just the right time to cause the prioity 
+You can't find these buggers by testing, because they are highly intermittent,
+i.e., things need to happen at just the right time to cause the prioity
 inversion.
 
-CAS and friends in the ISA use the synchronization of the memory bus over each 
-memory access instruction to avoid the need for a lock to make the operation 
+CAS and friends in the ISA use the synchronization of the memory bus over each
+memory access instruction to avoid the need for a lock to make the operation
 atomic, even in the case of multicore.
 
 What makes them dangerous is when users apply them to build their own locks to
-protect some data, because these locks are then unknown to the scheduler. => 
+protect some data, because these locks are then unknown to the scheduler. =>
 severe risk of priority inversions, if these löcks cause waits.
 
 ****************************************************************
@@ -1372,20 +1372,20 @@
 Sent: Friday, March 30, 2018  5:58 PM
 
 > Here is a canonical scenario for a priority inversion:
-> 
-> 4 tasks T1 - T4, numbers indicate priority. High number = high 
+>
+> 4 tasks T1 - T4, numbers indicate priority. High number = high
 > priority.
 > The tasks are periodic, i.e., released at some time intervals.
-> 
-> T1 runs, grabs said lock to perform the software-emulated 
-> compare-and-swap, but before it is done with it, T4 is released by 
+>
+> T1 runs, grabs said lock to perform the software-emulated
+> compare-and-swap, but before it is done with it, T4 is released by
 > time-tigger, preempts T1, runs a bit - meanwhile
 > T2 and T3 are released, too.
-> 
-> Then T4 asks for the same lock, but can't get it. Shucks. 
-> Needs to wait until T1 finishes with the CAS. But T2 and T3 have 
-> higher priority than T1. So, T1 needs to wait until T2 and T3 have 
-> finished their work. Then, much later, T1 gets to run, completes the 
+>
+> Then T4 asks for the same lock, but can't get it. Shucks.
+> Needs to wait until T1 finishes with the CAS. But T2 and T3 have
+> higher priority than T1. So, T1 needs to wait until T2 and T3 have
+> finished their work. Then, much later, T1 gets to run, completes the
 > CAS and releases the lock.
 > Then, finally, T4 gets to do its CAS.
 
@@ -1393,61 +1393,61 @@
 there was a reason I dislike preemption :-).
 
 I also note that this doesn't happen if the lock is part of a protected object,
-is a protected action can't be preempted (caused via ceiling priority or 
+is a protected action can't be preempted (caused via ceiling priority or
 whatever) unless no higher priority task can use it.
 
-> Now, there was a reason for T4 having high priority, namely, the fact 
-> that it has the tightest deadline (a general principle in 
-> fixed-priority embedded scheduling, known to be optimal). Which is 
+> Now, there was a reason for T4 having high priority, namely, the fact
+> that it has the tightest deadline (a general principle in
+> fixed-priority embedded scheduling, known to be optimal). Which is
 > likely to be long past in the scenario above.
-> 
-> It T4 controls the brakes in your car, you no longer perceive this as 
-> being merely a performance issue. Dead people do not reflect on such 
+>
+> It T4 controls the brakes in your car, you no longer perceive this as
+> being merely a performance issue. Dead people do not reflect on such
 > things any more.
 
-This is of course why I want checking on the introduction of parallel 
+This is of course why I want checking on the introduction of parallel
 execution. Mere mortals cannot see these sorts of issues; the easier it is to
-introduce parallelism, the more likely it is for these sorts of effects to 
-occur. (I'm happy to have such checking turned off by experts; it necessarily 
-has to be quite conservative and it wouldn't do to force many things to be 
+introduce parallelism, the more likely it is for these sorts of effects to
+occur. (I'm happy to have such checking turned off by experts; it necessarily
+has to be quite conservative and it wouldn't do to force many things to be
 written as tasks -- which are even less structured.)
- 
-> You just saw a priority inversion in action (named so, because T4 
+
+> You just saw a priority inversion in action (named so, because T4
 > behaves for a while as if it had lowest priority 1).
-> There are scheduling schemes that avoid priority inversion, but only 
-> if the locks are a concept provided by the run-time system and well 
+> There are scheduling schemes that avoid priority inversion, but only
+> if the locks are a concept provided by the run-time system and well
 > understood by the scheduler  (ICPP, OCPP, Priority Inheritance, ...
 > Deadline-floor protocol, etc.)
-> 
-> You can't find these buggers by testing, because they are highly 
-> intermittent, i.e., things need to happen at just the right time to 
+>
+> You can't find these buggers by testing, because they are highly
+> intermittent, i.e., things need to happen at just the right time to
 > cause the prioity inversion.
 
 Right. Tasking issues in general are impossible to find, because of that fact
 -- even if you get them to happen, you can't reproduce them. I seriously have
-no idea how people do that -- even debugging Janus/Ada's cooperative 
+no idea how people do that -- even debugging Janus/Ada's cooperative
 multitasking is very difficult -- and it's repeatable if you can get rid of
 any timing effects.
 
-> CAS and friends in the ISA use the synchronization of the memory bus 
-> over each memory access instruction to avoid the need for a lock to 
+> CAS and friends in the ISA use the synchronization of the memory bus
+> over each memory access instruction to avoid the need for a lock to
 > make the operation atomic, even in the case of multicore.
-> 
-> What makes them dangerous is when users apply them to build their own 
-> locks to protect some data, because these locks are then unknown to 
-> the scheduler. => severe risk of priority inversions, if these löcks 
+>
+> What makes them dangerous is when users apply them to build their own
+> locks to protect some data, because these locks are then unknown to
+> the scheduler. => severe risk of priority inversions, if these löcks
 > cause waits.
 
-Makes sense. This suggests that you would prefer that anyone that needs 
+Makes sense. This suggests that you would prefer that anyone that needs
 portable synchronization avoid atomic objects altogether (one presumes that
 the compiler has selected an implementation [of protected objects - ED] known
-to the scheduler and/or truly atomic -- if the compiler implementer is 
+to the scheduler and/or truly atomic -- if the compiler implementer is
 clueless to these issues you  have no hope anyway). Is that a fair conclusion??
 
 I'm primarily interested here in the effect on "checked" synchronization for
-parallel execution. That needs to be defined so that a ny moderately 
-competent Ada programmer can do the right thing. Since "parallel" is often 
-used as an optimization, it will often be introduced after the fact, so the 
+parallel execution. That needs to be defined so that a ny moderately
+competent Ada programmer can do the right thing. Since "parallel" is often
+used as an optimization, it will often be introduced after the fact, so the
 only thing preventing problems is the checking.
 
 ****************************************************************
@@ -1455,12 +1455,12 @@
 From: Erhard Ploedereder
 Sent: Friday, March 30, 2018  6:59 PM
 
-> I also note that this doesn't happen if the lock is part of a 
-> protected object, as a protected action can't be preempted (caused via 
+> I also note that this doesn't happen if the lock is part of a
+> protected object, as a protected action can't be preempted (caused via
 > ceiling priority or whatever) unless no higher priority task can use it.
 
 True only under a scheduling based on ceiling protocols. Under "plain"
-fixed-priority preemptive scheduling or even with priority inheritance, the 
+fixed-priority preemptive scheduling or even with priority inheritance, the
 preemption can happen.
 
 ****************************************************************
@@ -1471,9 +1471,9 @@
 > This is of course why I want checking on the introduction of parallel
 > execution.
 
-But the issue here (preemption of execution) is purely a sequential issue: 
-this is to say, if you have Task-1 and Task-2 where Task-1 where Task-2 is 
-executing and there's a free processor for Task-1 there is no issue. (This 
+But the issue here (preemption of execution) is purely a sequential issue:
+this is to say, if you have Task-1 and Task-2 where Task-1 where Task-2 is
+executing and there's a free processor for Task-1 there is no issue. (This
 issue w/ locks is something different, at least how I learned it [preemption
 having to do strictly with execution].)
 
@@ -1483,11 +1483,11 @@
 > necessarily has to be quite conservative and it wouldn't do to force many
 > things to be written as tasks -- which are even less structured.)
 
-I was really impressed by the Thesis that I referenced in an earlier email 
--- al-time software through a cyclic task 
-abstraction for Ada" -- I thought it did a great job with increasing the 
+I was really impressed by the Thesis that I referenced in an earlier email
+-- "Reducing the cost of real-time software through a cyclic task
+abstraction for Ada" -- I thought it did a great job with increasing the
 accuracy of schedulability and analysis, at least in the theoretical.
- 
+
 > Right. Tasking issues in general are impossible to find, because of that
 > fact -- even if you get them to happen, you can't reproduce them. I
 > seriously have no idea how people do that -- even debugging Janus/Ada's
@@ -1495,19 +1495,19 @@
 > get rid of any timing effects.
 
 Are they? In the very 'generalest' it may be like the halting-problem and thus
-impossible... but I don't know that that necessarily translates into some 
-usable subset. Just like how just because Ada's generics are not 
-turing-complete doesn't mean they're unusable. (Indeed, I'd argue that 
+impossible... but I don't know that that necessarily translates into some
+usable subset. Just like how just because Ada's generics are not
+turing-complete doesn't mean they're unusable. (Indeed, I'd argue that
 turing-complete in a generic- or template-system hurts usability.)
 
->> CAS and friends in the ISA use the synchronization of the 
->> memory bus over each memory access instruction to avoid the 
->> need for a lock to make the operation atomic, even in the 
+>> CAS and friends in the ISA use the synchronization of the
+>> memory bus over each memory access instruction to avoid the
+>> need for a lock to make the operation atomic, even in the
 >> case of multicore.
 
->> What makes them dangerous is when users apply them to build 
->> their own locks to protect some data, because these locks are 
->> then unknown to the scheduler. => severe risk of priority 
+>> What makes them dangerous is when users apply them to build
+>> their own locks to protect some data, because these locks are
+>> then unknown to the scheduler. => severe risk of priority
 >> inversions, if these löcks cause waits.
 
 > Makes sense. This suggests that you would prefer that anyone that needs
@@ -1516,9 +1516,9 @@
 > truly atomic -- if the compiler implementer is clueless to these issues you
 > have no hope anyway). Is that a fair conclusion??
 
-Seems a fair conclusion to me, but the reverse may be interesting: when the 
-synchronization constructs present enough information to the scheduler make 
-such guarantees -- this honestly seems right up Ada's alley or, if not, 
+Seems a fair conclusion to me, but the reverse may be interesting: when the
+synchronization constructs present enough information to the scheduler make
+such guarantees -- this honestly seems right up Ada's alley or, if not,
 certainly SPARK's.
 
 ****************************************************************
@@ -1526,17 +1526,17 @@
 From: Jean-Pierre Rosen
 Sent: Friday, March 30, 2018  11:50 PM
 
->> I also note that this doesn't happen if the lock is part of a 
->> protected object, as a protected action can't be preempted (caused 
+>> I also note that this doesn't happen if the lock is part of a
+>> protected object, as a protected action can't be preempted (caused
 >> via ceiling priority or whatever) unless no higher priority task can use it.
-> 
+>
 > True only under a scheduling based on ceiling protocols. Under "plain"
-> fixed-priority preemptive scheduling or even with priority 
+> fixed-priority preemptive scheduling or even with priority
 > inheritance, the preemption can happen.
-> 
+>
 More precisely: preemption can always happen on tasks in protected actions,
-but in the case of the priority ceiling protocol, a task can be preempted 
-only by a task that is not allowed to call the same PO, thus preventing 
+but in the case of the priority ceiling protocol, a task can be preempted
+only by a task that is not allowed to call the same PO, thus preventing
 priority inversion.
 
 ****************************************************************
@@ -1544,19 +1544,19 @@
 From: Erhard Ploedereder
 Sent: Saturday, March 31, 2018  11:57 AM
 
->> This is of course why I want checking on the introduction of parallel 
+>> This is of course why I want checking on the introduction of parallel
 >> execution.
 
 > But the issue here (preemption of execution) is purely a sequential
 > issue: this is to say, if you have Task-1 and Task-2 where Task-1 where
-> Task-2 is executing and there's a free processor for Task-1 there is 
-> no issue. (This issue w/ locks is something different, at least how I 
+> Task-2 is executing and there's a free processor for Task-1 there is
+> no issue. (This issue w/ locks is something different, at least how I
 > learned it [preemption having to do strictly with execution].)
 
-Yes and No. In your scenario, the inversion goes away. But what about 
+Yes and No. In your scenario, the inversion goes away. But what about
 T2 and T3?. They would preempt T1 if run on the same core. Welcome back
-to Priority inversion for T4. You can get rid of it only if you have as 
-many cores as tasks (not likely), or not do preemptive scheduling (not 
+to Priority inversion for T4. You can get rid of it only if you have as
+many cores as tasks (not likely), or not do preemptive scheduling (not
 real-time), or use the scheduling/lock protocol schemes talked about in
 the earlier mail.
 
@@ -1565,28 +1565,28 @@
 From: Brad Moore
 Sent: Saturday, March 31, 2018  6:58 PM
 
->> He sure would hate not to be told that his compare-and-swap is not 
->> mapped to such an operation. If the compiler is mum about this, there 
->> is a good chance that the issue is not discovered during porting of 
+>> He sure would hate not to be told that his compare-and-swap is not
+>> mapped to such an operation. If the compiler is mum about this, there
+>> is a good chance that the issue is not discovered during porting of
 >> the software.
-> 
-> Compilers that are mum violate the Standard. Unfortunately, there's no 
+>
+> Compilers that are mum violate the Standard. Unfortunately, there's no
 > good way to enforce that rule.
 
 This maybe sounds like another case where having a suppressable error might
 useful. A language mandated "soft" error sounds like a better way to enforce a
 compiler to not be mum.
 
->> So, I would have less problems with a set of procedures that 
->> encapsulated the particular primitives, combined with a mandate to 
->> support all that match a bus-synchronized operation and a mandate to 
+>> So, I would have less problems with a set of procedures that
+>> encapsulated the particular primitives, combined with a mandate to
+>> support all that match a bus-synchronized operation and a mandate to
 >> REJECT calls to any for which said operation does not exist.
-> 
-> The problem is I don't think we can do that in the Standard, since 
-> there is zero chance that we could formally define what a 
+>
+> The problem is I don't think we can do that in the Standard, since
+> there is zero chance that we could formally define what a
 > "bus-synchronized operation" is. And any Legality Rule requires that.
 
-If it were a soft error, would it still be considered a legality rule? If 
+If it were a soft error, would it still be considered a legality rule? If
 not, maybe it could be added without requiring definitions for such things
 as "bus-synchronized", and perhaps not require an ACATS test.
 
@@ -1595,11 +1595,11 @@
 From: Brad Moore
 Sent: Saturday, March 31, 2018  7:28 PM
 
-> operation when building lock-free data structures, and it is quite 
-> annoying that this cannot be done portably in Ada.  And yes, this 
+> operation when building lock-free data structures, and it is quite
+> annoying that this cannot be done portably in Ada.  And yes, this
 > operation is for experts only, but that doesn't mean such experts don't
 > want to write in Ada, while still achieving some level of portability.
-> 
+>
 > Below is the gcc API, extracted from:
 >   https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
 
@@ -1608,7 +1608,7 @@
 
 > I think we don't need all the options.
 
-By options, I'm not sure if you were referring to memory order options, or 
+By options, I'm not sure if you were referring to memory order options, or
 primitives.
 
 Here's a quick summary of what I've found so far;
@@ -1617,70 +1617,70 @@
 
 There are basically 3 main flavors of memory ordering supported.
 
-The most restrictive mode is Sequentially Consistent, which means updates are 
-synchronised across all threads, and all threads see the same order of update 
+The most restrictive mode is Sequentially Consistent, which means updates are
+synchronised across all threads, and all threads see the same order of update
 to atomic variables. I believe this corresponds closely to Ada's definition of
-Volatile and Atomic objects. This is the safest mode, but also the least 
-efficient since it requires a higher level of synchronisation. We could 
+Volatile and Atomic objects. This is the safest mode, but also the least
+efficient since it requires a higher level of synchronisation. We could
 probably support primitives that are in sequentially consistent mode most
 easily, since we mostly already have this, and it is the safest mode with the
 least amount of unexpected behaviours and pitfalls.
 
-The next level down in terms of synchronisation requirements is a mode where 
-only the threads involved in the access to a particular atomic variable are 
-synchronised with each other. This capability however effects which 
+The next level down in terms of synchronisation requirements is a mode where
+only the threads involved in the access to a particular atomic variable are
+synchronised with each other. This capability however effects which
 optimisations can be applied to the code.
 
 For example, hoisting or sinking of code across boundaries of access to atomic
-variables is disabled. To support this, the compiler needs to be intimately 
+variables is disabled. To support this, the compiler needs to be intimately
 aware and involved where this is used when it is applying optimisations.
-I am only guessing, but I suspect there may not be enough appetite to 
+I am only guessing, but I suspect there may not be enough appetite to
 introduce such a memory mode if it requires the compiler to mesh well with it.
 
-Below that is a relaxed mode where there is no synchronisation between 
+Below that is a relaxed mode where there is no synchronisation between
 threads, the only guarantee is that a thread wont see previous values of a
 variable if it has seen a newer value. This is the most efficient mode, but
 also the most dangerous.
 
-Someone who knows what they are doing could in theory use this to write more 
+Someone who knows what they are doing could in theory use this to write more
 efficient code. This mode might be easier to implement than the previous mode,
-since it doesn't enforce "happens-before" constraints.  Maybe we could create 
+since it doesn't enforce "happens-before" constraints.  Maybe we could create
 a new type of Volatile aspect, such as Relaxed_Volatile for this purpose?
 
-The other threads of this email chain seem to be suggesting however that the 
+The other threads of this email chain seem to be suggesting however that the
 use of atomic primitives in user code to create lock free abstractions should
-be discouraged, to avoid problems such as priority inversions when the 
+be discouraged, to avoid problems such as priority inversions when the
 implementation is in software instead of hardware.
 
-This has me thinking that the best option for Ada to add capability in this 
+This has me thinking that the best option for Ada to add capability in this
 area may be to go back to the Lock_Free aspect idea.
 
-That way, the implementation of the lock is provided by the compiler 
-implementation, and fits into the synchronisation model we already have for 
-protected objects. The implementation can choose between multiple 
-implementation techniques, such as transactional memory. A protected object 
+That way, the implementation of the lock is provided by the compiler
+implementation, and fits into the synchronisation model we already have for
+protected objects. The implementation can choose between multiple
+implementation techniques, such as transactional memory. A protected object
 also guides the programmer to write code inside the lock that is better formed
 such by disallowing potentially blocking operations.
 
 Here is a quote from the introduction of Geert's paper that seems relevant.
 
-"The use of atomic primitives, memory barriers or transactional memory are 
-implementation details after all, that should not appear in actual user 
+"The use of atomic primitives, memory barriers or transactional memory are
+implementation details after all, that should not appear in actual user
 code [1]."
 
 Where the reference is;
 
-H.-J. Boehm. Transactional memory should be an implementation technique, not 
+H.-J. Boehm. Transactional memory should be an implementation technique, not
 a programming interface.
-In Proceedings of the First USENIX conference on Hot topics in parallelism, 
+In Proceedings of the First USENIX conference on Hot topics in parallelism,
 HotPar’09, pages 15–15, Berkeley, CA, USA, 2009. USENIX Association.
 
 
 I did go through the exercise of creating an Ada package spec for the functions
-described in Tucker's link and came up with a generic package which I've 
+described in Tucker's link and came up with a generic package which I've
 attached if anyone is interested.
 
-Perhaps many of the primitives would not be needed, such as the arithmetic 
+Perhaps many of the primitives would not be needed, such as the arithmetic
 ones, and the basic load and store routines.
 
 ----
@@ -1996,26 +1996,26 @@
 From: Erhard Ploedereder
 Sent: Saturday, March 31, 2018  7:43 PM
 
->> So, I would have less problems with a set of procedures that 
->> encapsulated the particular primitives, combined with a mandate to 
->> support all that match a bus-synchronized operation and a mandate to 
+>> So, I would have less problems with a set of procedures that
+>> encapsulated the particular primitives, combined with a mandate to
+>> support all that match a bus-synchronized operation and a mandate to
 >> REJECT calls to any for which said operation does not exist.
-> The problem is I don't think we can do that in the Standard, since 
-> there is zero chance that we could formally define what a 
+> The problem is I don't think we can do that in the Standard, since
+> there is zero chance that we could formally define what a
 > "bus-synchronized operation" is. And any Legality Rule requires that.
 
 Not so difficult:
 
-"A call on xyz is illegal if the compiler does not map it to a single 
-atomic instruction of the target architecture." (or rewrite this an 
-implementation requirement, with an "otherwise  produce an 
+"A call on xyz is illegal if the compiler does not map it to a single
+atomic instruction of the target architecture." (or rewrite this an
+implementation requirement, with an "otherwise  produce an
 error/warning/diagnostic message ).
 
-Incidentally, C.1(11) already has the recommendation that intrinsic 
+Incidentally, C.1(11) already has the recommendation that intrinsic
 subprograms for the set of these atomic memory operations be provided.
-(Atomic increment is one of them - this was mentioned in another mail as 
-being useful when available.) The way C.1 is written, one would expect the 
-respective target-specific subset of atomic memory operations. This would be 
+(Atomic increment is one of them - this was mentioned in another mail as
+being useful when available.) The way C.1 is written, one would expect the
+respective target-specific subset of atomic memory operations. This would be
 a good place to standardize their signatures and be done with the AI.
 
 ****************************************************************
@@ -2023,16 +2023,16 @@
 From: Tucker Taft
 Sent: Sunday, April 1, 2018  4:39 PM
 
-I don't think we should delve into the various memory ordering options.  It 
-just seems like overkill given how rarely these will be used.  Remember C++ 
+I don't think we should delve into the various memory ordering options.  It
+just seems like overkill given how rarely these will be used.  Remember C++
 doesn't have an equivalent to the protected object (at least not yet! -- never
 say never in C++ ;-).  So we just need to address the main usage, I believe.
-So I would go with Sequentially Consistent, and those who are desperate for 
-some looser synchronization can write their own primitives, or pay their 
+So I would go with Sequentially Consistent, and those who are desperate for
+some looser synchronization can write their own primitives, or pay their
 vendor to provide it.
 
-Standardizing the Lock_Free aspect might be worth doing, but I don't believe 
-that addresses the main goal here, which is to provide atomic operations on 
+Standardizing the Lock_Free aspect might be worth doing, but I don't believe
+that addresses the main goal here, which is to provide atomic operations on
 atomic objects.
 
 ****************************************************************
@@ -2040,12 +2040,12 @@
 From: Brad Moore
 Sent: Saturday, May 5, 2018  5:30 PM
 
-Here is my first cut at AI12-0234-1, which provides better support for 
+Here is my first cut at AI12-0234-1, which provides better support for
 lock-free programming in Ada. [This is version /02 of the AI - Editor.]
 
 The original title of this AI was Compare and Swap for Atomic objects, which
-was generalized to also provide other atomic operations, such as being able 
-to add or subtract values to integer types, and apply bitwise operations to 
+was generalized to also provide other atomic operations, such as being able
+to add or subtract values to integer types, and apply bitwise operations to
 modular types atomically.
 
 The proposal has 4 new libraries.
@@ -2055,34 +2055,34 @@
 Atomic_Operations.Signed_Arithmetic,
 Atomic_Operations.Modular_Arithmetic
 
-The parent library is non-generic and includes some test and set based 
+The parent library is non-generic and includes some test and set based
 operations, which do not require any user types.
 
 The other 3 libraries are generic libraries.
 
-The Storage library has a generic formal discrete type, and provide the 
+The Storage library has a generic formal discrete type, and provide the
 Compare and Swap, Load, Store, and Exchange capabilities.
 
-The Signed_Arithmetic has a generic formal signed integer type, and provides 
+The Signed_Arithmetic has a generic formal signed integer type, and provides
 variants of add and subtract. A Constraint error can be raised as expected if
 the operation overflows.
 
-The Modular_Arithmetic has a generic formal modular type, and in addition to 
+The Modular_Arithmetic has a generic formal modular type, and in addition to
 Add and subtract, also provides various bit manipulation calls that one might
 expect to use with a modular type. Overflow has wrap around semantics, and
 does not raise constraint_error, as one might expect.
 
-To specify that the generic formals are atomic types, I needed to change the 
-rules to allow the Atomic aspect to be specified on a generic formal, which 
+To specify that the generic formals are atomic types, I needed to change the
+rules to allow the Atomic aspect to be specified on a generic formal, which
 previously was not allowed.
 
-Finally, in addition, since protected objects on a single processor are 
-considered to be lock-free and deadlock free with appropriate use of the 
+Finally, in addition, since protected objects on a single processor are
+considered to be lock-free and deadlock free with appropriate use of the
 ceiling priority protocol, this AI also extends the rules for the CPU aspect,
-so that it can be applied to protected type declarations. The compiler can 
-simplify the implementation for such protected types, since locking is not 
-needed, plus there is the added benefit of being deadlock free, which was 
-considered to be important by the attendees at the recent IRTAW, which 
+so that it can be applied to protected type declarations. The compiler can
+simplify the implementation for such protected types, since locking is not
+needed, plus there is the added benefit of being deadlock free, which was
+considered to be important by the attendees at the recent IRTAW, which
 unanimously felt it was worth adding to the standard.
 
 ****************************************************************
@@ -2090,14 +2090,14 @@
 From: Randy Brukardt
 Sent: Friday, May 11, 2018  12:06 AM
 
-> The parent library is non-generic and includes some test and set based 
+> The parent library is non-generic and includes some test and set based
 > operations, which do not require any user types.
 
 Humm.
 
 >   type Test_And_Set_Type is mod 2**8;
 
-(1) Shouldn't this type be declared atomic (or at least volatile)? It's 
+(1) Shouldn't this type be declared atomic (or at least volatile)? It's
 beyond weird to do atomic operations on non-atomic objects. (It's also a
 substantial optimizer problem - an Ada optimizer knows to leave atomic objects
 alone, but that certainly isn't the case for other objects.)
@@ -2107,68 +2107,68 @@
 this type be based on the storage unit in System?
 
 ...
-> To specify that the generic formals are atomic types, I needed to 
-> change the rules to allow the Atomic aspect to be specified on a 
+> To specify that the generic formals are atomic types, I needed to
+> change the rules to allow the Atomic aspect to be specified on a
 > generic formal, which previously was not allowed.
 
-I wonder if this should be done in a separate AI. It could get complex if 
+I wonder if this should be done in a separate AI. It could get complex if
 Steve discovers any more contract problems.
 
-> Modify C.6 (6.1/3)  to allow aspect Atomic to be applied to a generic 
+> Modify C.6 (6.1/3)  to allow aspect Atomic to be applied to a generic
 > formal type
 >
-> For an object_declaration, a component_declaration, or a {type 
-> (including a formal type)}[full_type_declaration], the following 
+> For an object_declaration, a component_declaration, or a {type
+> (including a formal type)}[full_type_declaration], the following
 > representation aspects may be specified:
 
-(1) This implies that Atomic can be specified in private types, extensions, 
-interfaces, incomplete types, yadda yadda yadda. The Legality Rules in 13.1 
-for representation aspects would prevent that, but those same rules also 
-would prevent use on formal types "unless otherwise specified". Seems 
-confused. I'd suggest just adding "formal_type_declaration" to the original 
+(1) This implies that Atomic can be specified in private types, extensions,
+interfaces, incomplete types, yadda yadda yadda. The Legality Rules in 13.1
+for representation aspects would prevent that, but those same rules also
+would prevent use on formal types "unless otherwise specified". Seems
+confused. I'd suggest just adding "formal_type_declaration" to the original
 list and then there is no confusion nor any need for a parenthetical remark.
 
   For an object_declaration, a component_declaration, {full_type_declartion},
   or a {formal}[full]_type_declaration, the following representation aspects
   may be specified:
 
-(2) This means all 6 aspects are getting allowed on formal types, even though 
-we only have need (and have rules!) for one. Is that really what we want? Do 
+(2) This means all 6 aspects are getting allowed on formal types, even though
+we only have need (and have rules!) for one. Is that really what we want? Do
 we really want to mess around with Independent_Components in generics? Etc.
 
 >Modify C.6 (12/3)
->If an atomic object is passed as a parameter, then the formal parameter 
->shall either have an atomic type or allow pass by copy. If an atomic 
->object is used as an actual for a generic formal object of mode in out, 
->then the type of the generic formal object shall be atomic. If the 
->prefix of an attribute_reference for an Access attribute denotes an 
->atomic object [(including a component)], then the designated type of 
->the resulting access type shall be atomic. {If a generic formal type is 
->atomic, then the actual shall be atomic.} If an atomic type is used as 
->an actual for a generic formal derived type, then the ancestor of the formal 
+>If an atomic object is passed as a parameter, then the formal parameter
+>shall either have an atomic type or allow pass by copy. If an atomic
+>object is used as an actual for a generic formal object of mode in out,
+>then the type of the generic formal object shall be atomic. If the
+>prefix of an attribute_reference for an Access attribute denotes an
+>atomic object [(including a component)], then the designated type of
+>the resulting access type shall be atomic. {If a generic formal type is
+>atomic, then the actual shall be atomic.} If an atomic type is used as
+>an actual for a generic formal derived type, then the ancestor of the formal
 >type shall be atomic. Corresponding rules apply to volatile objects and
 >types.
 >
->In a generic instantiation the actual type corresponding to an atomic 
->formal scalar, private, derived, array, or access-to-object type shall 
+>In a generic instantiation the actual type corresponding to an atomic
+>formal scalar, private, derived, array, or access-to-object type shall
 >be atomic;
 
-Could you explain why you are saying this twice, once with an added sentence 
+Could you explain why you are saying this twice, once with an added sentence
 in the original paragraph, and a second time with an added paragraph. It seems
-like the first added rule would be enough, but perhaps I missed some subtle 
+like the first added rule would be enough, but perhaps I missed some subtle
 issue.
 
-> Finally, in addition, since protected objects on a single processor 
-> are considered to be lock-free and deadlock free with appropriate use 
-> of the ceiling priority protocol, this AI also extends the rules for 
-> the CPU aspect, so that it can be applied to protected type 
-> declarations. The compiler can simplify the implementation for such 
-> protected types, since locking is not needed, plus there is the added 
-> benefit of being deadlock free, which was considered to be important 
-> by the attendees at the recent IRTAW, which unanimously felt it was 
+> Finally, in addition, since protected objects on a single processor
+> are considered to be lock-free and deadlock free with appropriate use
+> of the ceiling priority protocol, this AI also extends the rules for
+> the CPU aspect, so that it can be applied to protected type
+> declarations. The compiler can simplify the implementation for such
+> protected types, since locking is not needed, plus there is the added
+> benefit of being deadlock free, which was considered to be important
+> by the attendees at the recent IRTAW, which unanimously felt it was
 > worth adding to the standard.
 
-This also seems like it ought to have been a separate AI, even more so than 
+This also seems like it ought to have been a separate AI, even more so than
 the formal Atomic types. As you know, when AIs get too big, it's hard to make
 progress on them. And this topic is completely separate from the other issues.
 
@@ -2178,11 +2178,11 @@
 Sent: Friday, May 11, 2018  6:25 PM
 
 >>   type Test_And_Set_Type is mod 2**8;
-> 
-> (1) Shouldn't this type be declared atomic (or at least volatile)? 
-> It's beyond weird to do atomic operations on non-atomic objects. (It's 
-> also a substantial optimizer problem - an Ada optimizer knows to leave 
-> atomic objects alone, but that certainly isn't the case for other 
+>
+> (1) Shouldn't this type be declared atomic (or at least volatile)?
+> It's beyond weird to do atomic operations on non-atomic objects. (It's
+> also a substantial optimizer problem - an Ada optimizer knows to leave
+> atomic objects alone, but that certainly isn't the case for other
 > objects.)
 
 I agree, it should be atomic. When I originally started out, I was trying to
@@ -2192,68 +2192,68 @@
 operations just take an access to a memory location, and all updates to the
 memory location are via the API calls, so it works.
 
-However, I then realized that trying to describe this in the RM was going to 
+However, I then realized that trying to describe this in the RM was going to
 be messy, and that it would be better to say everything is atomic, then the
 definitions for atomic get applied for free, and found it fit much better to
-do that. 
+do that.
 
 I then added Atomic to all all the calls in the specs, but missed this one.
 
-> (2) 2**8 would be a very expensive type on the U2200 and various other 
+> (2) 2**8 would be a very expensive type on the U2200 and various other
 > unusual processors. Ada has never tied itself to 8-bit machines like Java.
 > Shouldn't this type be based on the storage unit in System?
 
-I agree that storage unit would be a more flexible definition. The GCC api 
-just has a void pointer, but the documentation says it updates a byte of 
+I agree that storage unit would be a more flexible definition. The GCC api
+just has a void pointer, but the documentation says it updates a byte of
 storage. I suppose one could alternatively say 2**implementation defined, like
 we do for Hash_Type in Ada.Containers, but in this case I think basing it on
 storage unit would be a better choice. I wonder if it could be a private type?
-I think I tried that, but found it harder to describe in the wording. This 
+I think I tried that, but found it harder to describe in the wording. This
 way, one can say that Clear sets the value to a zero value.
 
 > ...
->> To specify that the generic formals are atomic types, I needed to 
->> change the rules to allow the Atomic aspect to be specified on a 
+>> To specify that the generic formals are atomic types, I needed to
+>> change the rules to allow the Atomic aspect to be specified on a
 >> generic formal, which previously was not allowed.
-> 
-> I wonder if this should be done in a separate AI. It could get complex 
+>
+> I wonder if this should be done in a separate AI. It could get complex
 > if Steve discovers any more contract problems.
 
 I think a separate AI for this would be better also to separate concerns.
 
 >> Modify C.6 (6.1/3)  to allow aspect Atomic to be applied to a generic formal type
 >>
->> For an object_declaration, a component_declaration, or a {type 
->> (including a formal type)}[full_type_declaration], the following 
+>> For an object_declaration, a component_declaration, or a {type
+>> (including a formal type)}[full_type_declaration], the following
 >> representation aspects may be specified:
-> 
-> (1) This implies that Atomic can be specified in private types, 
-> extensions, interfaces, incomplete types, yadda yadda yadda. The 
-> Legality Rules in 13.1 for representation aspects would prevent that, 
-> but those same rules also would prevent use on formal types "unless 
-> otherwise specified". Seems confused. I'd suggest just adding 
+>
+> (1) This implies that Atomic can be specified in private types,
+> extensions, interfaces, incomplete types, yadda yadda yadda. The
+> Legality Rules in 13.1 for representation aspects would prevent that,
+> but those same rules also would prevent use on formal types "unless
+> otherwise specified". Seems confused. I'd suggest just adding
 > "formal_type_declaration" to the original list and then there is no
 > confusion nor any need for a parenthetical remark.
-> 
->  For an object_declaration, a component_declaration, 
-> {full_type_declartion}, or a  {formal}[full]_type_declaration, the 
+>
+>  For an object_declaration, a component_declaration,
+> {full_type_declartion}, or a  {formal}[full]_type_declaration, the
 > following representation aspects may be
 >  specified:
 
-I agree with your suggestion. I think I got the original wording idea by 
-looking at what was done for the Nonblocking aspect, since it can be 
+I agree with your suggestion. I think I got the original wording idea by
+looking at what was done for the Nonblocking aspect, since it can be
 applied to generic formals.
 
-> (2) This means all 6 aspects are getting allowed on formal types, even 
+> (2) This means all 6 aspects are getting allowed on formal types, even
 > though we only have need (and rules!) for one. Is that really what we want?
 > Do we really want to mess around with Independent_Components in generics?
 > Etc.
 
-I think I was under the impression that I was letting Volatile ride in on the 
-coattails of Atomic for this purpose, but didn't think the other ones were 
+I think I was under the impression that I was letting Volatile ride in on the
+coattails of Atomic for this purpose, but didn't think the other ones were
 being included. The thought was that it probably makes sense to allow Volatile
-on generic formal types, or weird not to, if we allow Atomic. But only if it 
-fits better with the wording. Otherwise restricting it to just Atomic is fine 
+on generic formal types, or weird not to, if we allow Atomic. But only if it
+fits better with the wording. Otherwise restricting it to just Atomic is fine
 by me.
 
 >>Modify C.6 (12/3)
@@ -2266,49 +2266,49 @@
 >>the designated type of the resulting access type shall be atomic. {If a
 >>generic formal type is atomic, then the actual shall be atomic.} If an
 >>atomic type is used as an actual for a generic formal derived type,
->>then the ancestor of the formal type shall be atomic. Corresponding rules 
+>>then the ancestor of the formal type shall be atomic. Corresponding rules
 >>apply to volatile objects and types.
 
 >>In a generic instantiation the actual type corresponding to an atomic
->>formal scalar, private, derived, array, or access-to-object type shall be 
+>>formal scalar, private, derived, array, or access-to-object type shall be
 >>atomic;
-> 
-> Could you explain why you are saying this twice, once with an added 
-> sentence in the original paragraph, and a second time with an added 
-> paragraph. It seems like the first added rule would be enough, but 
+>
+> Could you explain why you are saying this twice, once with an added
+> sentence in the original paragraph, and a second time with an added
+> paragraph. It seems like the first added rule would be enough, but
 > perhaps I missed some subtle issue.
 
 Sure. I said it the first time because that is what I thought was needed. Then
 I saw somewhere (probably nonblocking aspect) that needed to describe generic
-matching rules for instances and looked up an example of that (again, likely 
-from nonblocking aspect), which is where I got the second version of the 
+matching rules for instances and looked up an example of that (again, likely
+from nonblocking aspect), which is where I got the second version of the
 statement.  The intent was that we could get rid of one or the other, or merge
 into one. I wasn't sure if the second was more of a boilerplate that was
 needed for generic instances, and also if it had some subtlety not captured
-in the first time. Otherwise I dont have a real reason for stating it the 
+in the first time. Otherwise I dont have a real reason for stating it the
 second time. If you don't think it is needed, we can get rid of it.
 
->> Finally, in addition, since protected objects on a single processor 
->> are considered to be lock-free and deadlock free with appropriate use 
->> of the ceiling priority protocol, this AI also extends the rules for 
->> the CPU aspect, so that it can be applied to protected type 
->> declarations. The compiler can simplify the implementation for such 
->> protected types, since locking is not needed, plus there is the added 
->> benefit of being deadlock free, which was considered to be important 
->> by the attendees at the recent IRTAW, which unanimously felt it was 
+>> Finally, in addition, since protected objects on a single processor
+>> are considered to be lock-free and deadlock free with appropriate use
+>> of the ceiling priority protocol, this AI also extends the rules for
+>> the CPU aspect, so that it can be applied to protected type
+>> declarations. The compiler can simplify the implementation for such
+>> protected types, since locking is not needed, plus there is the added
+>> benefit of being deadlock free, which was considered to be important
+>> by the attendees at the recent IRTAW, which unanimously felt it was
 >> worth adding to the standard.
-> 
-> This also seems like it ought to have been a separate AI, even more so 
-> than the formal Atomic types. As you know, when AIs get too big, it's 
-> hard to make progress on them. And this topic is completely separate 
+>
+> This also seems like it ought to have been a separate AI, even more so
+> than the formal Atomic types. As you know, when AIs get too big, it's
+> hard to make progress on them. And this topic is completely separate
 > from the other issues.
 
-I agree that this really should be a separate AI. I think I was thinking at 
+I agree that this really should be a separate AI. I think I was thinking at
 the time that it would be more likely to be considered if part of an existing
 AI, and it is related to the topic of lock-free, so it kind of fits somewhat.
 I thought that adding a new AI at this stage might be been disallowed, but if
-that can be done, given that IRTAW was behind it, then I agree that is a 
-better way to go. 
+that can be done, given that IRTAW was behind it, then I agree that is a
+better way to go.
 
 Would you like me to resubmit this as 3 separate AI's?
 
@@ -2318,25 +2318,25 @@
 Sent: Friday, May 11, 2018  9:03 PM
 
 ...
-> >>In a generic instantiation the actual type corresponding to an 
-> >>atomic  formal scalar, private, derived, array, or access-to-object 
+> >>In a generic instantiation the actual type corresponding to an
+> >>atomic  formal scalar, private, derived, array, or access-to-object
 > >>type shall be atomic;
-> > 
-> > Could you explain why you are saying this twice, once with an added 
-> > sentence in the original paragraph, and a second time with an added 
-> > paragraph. It seems like the first added rule would be enough, but 
+> >
+> > Could you explain why you are saying this twice, once with an added
+> > sentence in the original paragraph, and a second time with an added
+> > paragraph. It seems like the first added rule would be enough, but
 > > perhaps I missed some subtle issue.
-> 
-> Sure. I said it the first time because that is what I thought was 
+>
+> Sure. I said it the first time because that is what I thought was
 > needed. Then I saw somewhere (probably nonblocking
-> aspect) that needed to describe generic matching rules for instances 
-> and looked up an example of that (again, likely from nonblocking 
+> aspect) that needed to describe generic matching rules for instances
+> and looked up an example of that (again, likely from nonblocking
 > aspect), which is where I got the second version of the statement.
-> The intent was that we could get rid of one or the other, or merge 
-> into one. I wasn't sure if the second was more of a boilerplate that 
-> was needed for generic instances, and also if it had some subtlety not 
+> The intent was that we could get rid of one or the other, or merge
+> into one. I wasn't sure if the second was more of a boilerplate that
+> was needed for generic instances, and also if it had some subtlety not
 > captured in the first time.
-> Otherwise I dont have a real reason for stating it the second time. If 
+> Otherwise I dont have a real reason for stating it the second time. If
 > you don't think it is needed, we can get rid of it.
 
 I believe the Nonblocking rule was written the way it was because it does
@@ -2345,21 +2345,21 @@
 If your rule applies to all types, it's just really long-winded for no reason.
 
 ...
-> I agree that this really should be a separate AI. I think I was 
-> thinking at the time that it would be more likely to be considered if 
-> part of an existing AI, and it is related to the topic of lock-free, 
-> so it kind of fits somewhat. I thought that adding a new AI at this 
-> stage might be been disallowed, but if that can be done, given that 
+> I agree that this really should be a separate AI. I think I was
+> thinking at the time that it would be more likely to be considered if
+> part of an existing AI, and it is related to the topic of lock-free,
+> so it kind of fits somewhat. I thought that adding a new AI at this
+> stage might be been disallowed, but if that can be done, given that
 > IRTAW was behind it, then I agree that is a better way to go.
 
-I haven't sent the list to WG 9 yet, so IRTAW can add new things until I get 
-caught up posting AIs. (Almost there, but not quite.) And you could probably 
+I haven't sent the list to WG 9 yet, so IRTAW can add new things until I get
+caught up posting AIs. (Almost there, but not quite.) And you could probably
 make a case for it to be related to our instructions, but even if not, a split
-of an already started AI is always in-bounds. 
- 
+of an already started AI is always in-bounds.
+
 > Would you like me to resubmit this as 3 separate AI's?
 
-Yes please. Remember to mention that in the existing AI12-0234-1 part (the 
+Yes please. Remember to mention that in the existing AI12-0234-1 part (the
 actual packages) that you're depending on AI12-028x-1. (I just finished 277,
 and I have four more to post/write, so the number should be in the 280s.)
 
@@ -2380,54 +2380,54 @@
 I didn't say anything about the first two items here, and I probably should have.
 
 ...
-> > (2) 2**8 would be a very expensive type on the U2200 and various 
-> > other unusual processors. Ada has never tied itself to 8-bit 
+> > (2) 2**8 would be a very expensive type on the U2200 and various
+> > other unusual processors. Ada has never tied itself to 8-bit
 > > machines like Java.
 > > Shouldn't this type be based on the storage unit in System?
-> 
-> I agree that storage unit would be a more flexible definition. The GCC 
-> api just has a void pointer, but the documentation says it updates a 
+>
+> I agree that storage unit would be a more flexible definition. The GCC
+> api just has a void pointer, but the documentation says it updates a
 > byte of storage.
-> I suppose one could alternatively say 2**implementation defined, like 
-> we do for Hash_Type in Ada.Containers, but in this case I think basing 
-> it on storage unit would be a better choice. I wonder if it could be a 
-> private type? I think I tried that, but found it harder to describe in 
+> I suppose one could alternatively say 2**implementation defined, like
+> we do for Hash_Type in Ada.Containers, but in this case I think basing
+> it on storage unit would be a better choice. I wonder if it could be a
+> private type? I think I tried that, but found it harder to describe in
 > the wording.
 > This way, one can say that Clear sets the value to a zero value.
 
-Perhaps you just want to copy (literally) the definition of Storage_Element 
+Perhaps you just want to copy (literally) the definition of Storage_Element
 (which is modular):
 
    type Test_And_Set_Type is mod System.Storage_Elements.Storage_Element'Modulus
       with Atomic;
 
-(We can't use Storage_Element directly because of the need to declare this 
+(We can't use Storage_Element directly because of the need to declare this
 atomic, but we can copy the modulus. Storage_Unit is defined to be
 Storage_Element'Size.)
 
 ...
-> > (2) This means all 6 aspects are getting allowed on formal types, 
-> > even though we only have need (and rules!) for one. Is that really 
+> > (2) This means all 6 aspects are getting allowed on formal types,
+> > even though we only have need (and rules!) for one. Is that really
 > > what we want?
 > > Do we really want to mess around with Independent_Components in generics?
 > > Etc.
-> 
-> I think I was under the impression that I was letting Volatile ride in 
-> on the coattails of Atomic for this purpose, but didn't think the 
+>
+> I think I was under the impression that I was letting Volatile ride in
+> on the coattails of Atomic for this purpose, but didn't think the
 > other ones were being included.
-> The thought was that it probably makes sense to allow Volatile on 
-> generic formal types, or weird not to, if we allow Atomic. But only if 
+> The thought was that it probably makes sense to allow Volatile on
+> generic formal types, or weird not to, if we allow Atomic. But only if
 > it fits better with the wording.
 > Otherwise restricting it to just Atomic is fine by me.
 
 That seemed OK to me, but what about Atomic_Components and Volatile_Components
-on formal array types? That seems like work :-) and I don't know if we have 
+on formal array types? That seems like work :-) and I don't know if we have
 any use for that work. And similarly for the Independent cases.
 
 >Would you like me to resubmit this as 3 separate AI's?
 
-Repeating myself, Yes. AI12-0234-1 would be the generic packages (since that 
-is the original question), the formal type one is needed to support that 
+Repeating myself, Yes. AI12-0234-1 would be the generic packages (since that
+is the original question), the formal type one is needed to support that
 original one, and the third is just a good idea on its own. Those will get
 numbers when I get them. All three will appear at the place of AI12-0234-1
 in our priority order (at least initially), since there isn't anything else
@@ -2439,30 +2439,30 @@
 Sent: Monday, May 14, 2018  11:40 PM
 
 > ...
-> > > (2) This means all 6 aspects are getting allowed on formal types, 
-> > > even though we only have need (and rules!) for one. Is that really 
+> > > (2) This means all 6 aspects are getting allowed on formal types,
+> > > even though we only have need (and rules!) for one. Is that really
 > > > what we want?
 > > > Do we really want to mess around with Independent_Components in generics?
 > > > Etc.
-> > 
-> > I think I was under the impression that I was letting Volatile ride 
-> > in on the coattails of Atomic for this purpose, but didn't think the 
+> >
+> > I think I was under the impression that I was letting Volatile ride
+> > in on the coattails of Atomic for this purpose, but didn't think the
 > > other ones were being included.
-> > The thought was that it probably makes sense to allow Volatile on 
-> > generic formal types, or weird not to, if we allow Atomic. But only 
+> > The thought was that it probably makes sense to allow Volatile on
+> > generic formal types, or weird not to, if we allow Atomic. But only
 > > if it fits better with the wording.
 > > Otherwise restricting it to just Atomic is fine by me.
-> 
-> That seemed OK to me, but what about Atomic_Components and 
-> Volatile_Components on formal array types? That seems like work :-) 
+>
+> That seemed OK to me, but what about Atomic_Components and
+> Volatile_Components on formal array types? That seems like work :-)
 > and I don't know if we have any use for that work.
 > And similarly for the Independent cases.
 
-Humm, I see that the actual wording only uses that heading for the three 
+Humm, I see that the actual wording only uses that heading for the three
 aspects Atomic, Volatile, and Independent. But the proposed wording literally
 only has rules for Atomic and Volatile. There's no wording for what it meaning
-to put Independent into a formal type, but the proposed wording allows it. We 
-need at a minimum to reconcile this (either have wording for generic matching 
+to put Independent into a formal type, but the proposed wording allows it. We
+need at a minimum to reconcile this (either have wording for generic matching
 for Independent, or only allow on formals for Atomic and Volatile).
 
 ****************************************************************
@@ -2471,29 +2471,29 @@
 Sent: Friday, May 18, 2018  4:36 PM
 
 > ...
->> > (2) 2**8 would be a very expensive type on the U2200 and various 
->> > other unusual processors. Ada has never tied itself to 8-bit 
+>> > (2) 2**8 would be a very expensive type on the U2200 and various
+>> > other unusual processors. Ada has never tied itself to 8-bit
 >> > machines like Java.
 >> > Shouldn't this type be based on the storage unit in System?
->> 
->> I agree that storage unit would be a more flexible definition. The 
->> GCC api just has a void pointer, but the documentation says it 
+>>
+>> I agree that storage unit would be a more flexible definition. The
+>> GCC api just has a void pointer, but the documentation says it
 >> updates a byte of storage.
->> I suppose one could alternatively say 2**implementation defined, like 
->> we do for Hash_Type in Ada.Containers, but in this case I think 
->> basing it on storage unit would be a better choice. I wonder if it 
->> could be a private type? I think I tried that, but found it harder to 
+>> I suppose one could alternatively say 2**implementation defined, like
+>> we do for Hash_Type in Ada.Containers, but in this case I think
+>> basing it on storage unit would be a better choice. I wonder if it
+>> could be a private type? I think I tried that, but found it harder to
 >> describe in the wording.
 >> This way, one can say that Clear sets the value to a zero value.
-> 
-> Perhaps you just want to copy (literally) the definition of 
+>
+> Perhaps you just want to copy (literally) the definition of
 > Storage_Element (which is modular):
-> 
+>
 >   type Test_And_Set_Type is
 >      mod System.Storage_Elements.Storage_Element'Modulus
 >      with Atomic;
-> 
-> (We can't use Storage_Element directly because of the need to declare 
+>
+> (We can't use Storage_Element directly because of the need to declare
 > this atomic, but we can copy the modulus. Storage_Unit is defined to be
 > Storage_Element'Size.)
 
@@ -2510,7 +2510,7 @@
    type Test_And_Set_Type is new System.Storage_Elements.Storage_Element
      with Atomic, Size => System.Storage_Elements.Storage_Element'Size;
 
-It's not clear to me which of these is better, or if it matters. 
+It's not clear to me which of these is better, or if it matters.
 Maybe the Size aspect for the derivation case isn't needed if Size is
 inherited.
 
@@ -2522,26 +2522,26 @@
 
 Another question I have is with regard to future-proofing these libraries.
 
-The real gcc library calls have an extra parameter for memory model, which 
+The real gcc library calls have an extra parameter for memory model, which
 defaults to the sequentially consistent memory model if not specified. We are
-saying right now that we want to go with a simpler approach and only support 
-the Sequentially_Consistent memory model, and therefore no parameter is 
+saying right now that we want to go with a simpler approach and only support
+the Sequentially_Consistent memory model, and therefore no parameter is
 needed.
 
 I am thinking it might be better future-proofing if we defined an enumeration
-for Memory_Model that for now only has one literal, Sequentially_Consistent, 
-and that parameter be added to the calls, defaulting to the 
+for Memory_Model that for now only has one literal, Sequentially_Consistent,
+and that parameter be added to the calls, defaulting to the
 Sequentially_Consistent value.
 
-That way, in the future, if we decide to support other memory models, adding 
-items to the Memory_Model enumeration is less likely to introduce backwards 
+That way, in the future, if we decide to support other memory models, adding
+items to the Memory_Model enumeration is less likely to introduce backwards
 compatibility than adding a new parameter.
 
 Is this suggestion worth worrying about? or is backwards compatibility not a
-significant problem here? I'm was originally thinking of cases such as 
-instantiating generics using these subprograms, which might expect a certain 
-profile signature. On the other hand, since these are intrinsic subprograms, 
-one cant instantiate generics with these as actuals, and maybe there are not 
+significant problem here? I'm was originally thinking of cases such as
+instantiating generics using these subprograms, which might expect a certain
+profile signature. On the other hand, since these are intrinsic subprograms,
+one cant instantiate generics with these as actuals, and maybe there are not
 any other real backwards compatibility concerns?
 
 ****************************************************************
@@ -2550,30 +2550,30 @@
 Sent: Friday, May 18, 2018  5:36 PM
 
 ...
-> I suppose it depends on whether we want to think of this type as a 
-> type that happens to look a lot like a Storage_Element, or instead as 
+> I suppose it depends on whether we want to think of this type as a
+> type that happens to look a lot like a Storage_Element, or instead as
 > a special type of Storage_Element.
-> 
+>
 > I think I am leaning towards the latter, using derivation.
 
-I was thinking it was the former, thus the formulation I suggested. Doesn't 
-really matter much either way, though. At least not until Steve finds some 
+I was thinking it was the former, thus the formulation I suggested. Doesn't
+really matter much either way, though. At least not until Steve finds some
 interesting way to use a formal derived type to cause a mess. ;-)
 
 ...
-> Is this suggestion worth worrying about? or is backwards compatibility 
-> not a significant problem here? I'm was originally thinking of cases 
-> such as instantiating generics using these subprograms, which might 
-> expect a certain profile signature. On the other hand, since these are 
-> intrinsic subprograms, one cant instantiate generics with these as 
-> actuals, and maybe there are not any other real backwards 
+> Is this suggestion worth worrying about? or is backwards compatibility
+> not a significant problem here? I'm was originally thinking of cases
+> such as instantiating generics using these subprograms, which might
+> expect a certain profile signature. On the other hand, since these are
+> intrinsic subprograms, one cant instantiate generics with these as
+> actuals, and maybe there are not any other real backwards
 > compatibility concerns?
 
 I tend to not want to worry about it. The C++ memory models seem to correspond
-roughly to "normal"/Volatile/Atomic objects -- Ada sets these models 
-per-object rather than per program. If we wanted (say) a volatile version of 
+roughly to "normal"/Volatile/Atomic objects -- Ada sets these models
+per-object rather than per program. If we wanted (say) a volatile version of
 these libraries, I'd expect that it would have to be separately defined (given
-the way you defined aspect matching). And I can't imagine adopting a C++ 
+the way you defined aspect matching). And I can't imagine adopting a C++
 memory model that essentially strips the guarantees of Atomic while still
 allowing objects to be declared that way.
 
@@ -2583,27 +2583,27 @@
 Sent: Friday, May 18, 2018  7:04 PM
 
 > ...
->> Is this suggestion worth worrying about? or is backwards 
->> compatibility not a significant problem here? I'm was originally 
->> thinking of cases such as instantiating generics using these 
->> subprograms, which might expect a certain profile signature. On the 
->> other hand, since these are intrinsic subprograms, one cant 
->> instantiate generics with these as actuals, and maybe there are not 
+>> Is this suggestion worth worrying about? or is backwards
+>> compatibility not a significant problem here? I'm was originally
+>> thinking of cases such as instantiating generics using these
+>> subprograms, which might expect a certain profile signature. On the
+>> other hand, since these are intrinsic subprograms, one cant
+>> instantiate generics with these as actuals, and maybe there are not
 >> any other real backwards compatibility concerns?
-> 
-> I tend to not want to worry about it. The C++ memory models seem to 
-> correspond roughly to "normal"/Volatile/Atomic objects -- Ada sets 
-> these models per-object rather than per program. If we wanted (say) a 
-> volatile version of these libraries, I'd expect that it would have to 
-> be separately defined (given the way you defined aspect matching). And 
-> I can't imagine adopting a C++ memory model that essentially strips 
+>
+> I tend to not want to worry about it. The C++ memory models seem to
+> correspond roughly to "normal"/Volatile/Atomic objects -- Ada sets
+> these models per-object rather than per program. If we wanted (say) a
+> volatile version of these libraries, I'd expect that it would have to
+> be separately defined (given the way you defined aspect matching). And
+> I can't imagine adopting a C++ memory model that essentially strips
 > the guarantees of Atomic while still allowing objects to be declared that
 > way.
 
-I think Ada's per object approach is a sensible one, but I think the memory 
+I think Ada's per object approach is a sensible one, but I think the memory
 model concept is someone independent of the volatile/atomic/normal semantics.
 
-Here is an example I found today, that actually looks very similar to the 
+Here is an example I found today, that actually looks very similar to the
 approach I was suggested for implementing the FIFO_Spinning Admission policy
 in AI12-0276.
 The idea there was a ticket abstraction where someone wanting a lock takes the
@@ -2614,10 +2614,10 @@
    https://github.com/pramalhe/ConcurrencyFreaks/blob/master/C11/locks/ticket_mutex.c
 
 The example uses the same primitive calls that we are considering for Ada.
-To obtain the lock, they do an atomic increment to get the next ticket number 
-using atomic_fetch_add, then keep calling atomic_load until they see their 
-ticket number come up. For these calls, I believe the default memory order, 
-Sequentially_Consistent is applied, which makes sense since there is 
+To obtain the lock, they do an atomic increment to get the next ticket number
+using atomic_fetch_add, then keep calling atomic_load until they see their
+ticket number come up. For these calls, I believe the default memory order,
+Sequentially_Consistent is applied, which makes sense since there is
 communication between threads.
 
 void ticket_mutex_lock(ticket_mutex_t * self) {
@@ -2627,12 +2627,12 @@
     }
     // This thread has acquired the lock on the mutex }
 
-When unlocking the mutex, they load the current ticket number locally, using 
+When unlocking the mutex, they load the current ticket number locally, using
 the relaxed memory order, because since the lock was held it is known that the
-value of the current ticket number would not have changed. This is more 
+value of the current ticket number would not have changed. This is more
 efficient than loading using the sequentially consistent memory model, as that
 requires synchronisations across all the threads. The store back to update the
-current ticket number uses sequentially consistent again since other threads 
+current ticket number uses sequentially consistent again since other threads
 need to see the update.
 
 
@@ -2654,18 +2654,18 @@
 }
 
 
-So, the memory order seems somewhat orthogonal to the atomicity class of the 
-object. In some cases, different orders might ideally be wanted to be applied 
+So, the memory order seems somewhat orthogonal to the atomicity class of the
+object. In some cases, different orders might ideally be wanted to be applied
 to the same object at different times to get better performance.
 
-Given this, do you still think that we'd not want to someday be able to 
+Given this, do you still think that we'd not want to someday be able to
 specify different memory orders using the same generic instantiation?
 
-I suppose we could add new overloaded calls to the libraries in the future 
-that accept a memory order parameter, and leave the current calls as is, 
+I suppose we could add new overloaded calls to the libraries in the future
+that accept a memory order parameter, and leave the current calls as is,
 without a parameter.
 
-Then there is no backwards compatibility issue. I think I just answered my own 
+Then there is no backwards compatibility issue. I think I just answered my own
 question... (with your help :))
 
 So I think we're OK not worrying about this.
@@ -2675,55 +2675,55 @@
 From: Brad Moore
 Sent: Friday, May 18, 2018  9:37 PM
 
->> > > (2) This means all 6 aspects are getting allowed on formal types, 
->> > > even though we only have need (and rules!) for one. Is that 
+>> > > (2) This means all 6 aspects are getting allowed on formal types,
+>> > > even though we only have need (and rules!) for one. Is that
 >> > > really what we want?
 >> > > Do we really want to mess around with Independent_Components in
 > generics?
 >> > > Etc.
->> > 
->> > I think I was under the impression that I was letting Volatile ride 
->> > in on the coattails of Atomic for this purpose, but didn't think 
+>> >
+>> > I think I was under the impression that I was letting Volatile ride
+>> > in on the coattails of Atomic for this purpose, but didn't think
 >> > the other ones were being included.
->> > The thought was that it probably makes sense to allow Volatile on 
->> > generic formal types, or weird not to, if we allow Atomic. But only 
+>> > The thought was that it probably makes sense to allow Volatile on
+>> > generic formal types, or weird not to, if we allow Atomic. But only
 >> > if it fits better with the wording.
 >> > Otherwise restricting it to just Atomic is fine by me.
->> 
->> That seemed OK to me, but what about Atomic_Components and 
->> Volatile_Components on formal array types? That seems like work :-) 
+>>
+>> That seemed OK to me, but what about Atomic_Components and
+>> Volatile_Components on formal array types? That seems like work :-)
 >> and I don't know if we have any use for that work.
 >> And similarly for the Independent cases.
-> 
-> Humm, I see that the actual wording only uses that heading for the 
-> three aspects Atomic, Volatile, and Independent. But the proposed 
-> wording literally only has rules for Atomic and Volatile. There's no 
-> wording for what it meaning to put Independent into a formal type, but 
-> the proposed wording allows it. We need at a minimum to reconcile this 
-> (either have wording for generic matching for Independent, or only 
+>
+> Humm, I see that the actual wording only uses that heading for the
+> three aspects Atomic, Volatile, and Independent. But the proposed
+> wording literally only has rules for Atomic and Volatile. There's no
+> wording for what it meaning to put Independent into a formal type, but
+> the proposed wording allows it. We need at a minimum to reconcile this
+> (either have wording for generic matching for Independent, or only
 > allow on formals for Atomic and Volatile).
 
-Humm indeed. I originally said it was weird to allow Atomic without Volatile, 
-but now it feels even weirder to have those two and not have Independent, 
+Humm indeed. I originally said it was weird to allow Atomic without Volatile,
+but now it feels even weirder to have those two and not have Independent,
 especially since C.6 (8.1/4) says that "All atomic objects and aliased objects
 are considered to be specified as independently addressable."
 
 And then more weird to be able to specify Atomic or Volatile on a formal array
 type, but not be able to specify Atomic_Components or Volatile_Components.
 
-Also, if there's a need to have Atomic on generic formals, it is not too hard 
-to imagine there being a need for Atomic_Components on a generic formal array 
+Also, if there's a need to have Atomic on generic formals, it is not too hard
+to imagine there being a need for Atomic_Components on a generic formal array
 type. An array of counters that gets atomically incremented is the first thing
 that comes to mind.
 
 I see quite a bit less of a use case for Volatile and Volatile components than
-Atomic and Atomic_Components, and even lesser a case for Independent and 
+Atomic and Atomic_Components, and even lesser a case for Independent and
 Independent_Components.
 
-So I am now thinking the way to go for now is to allow Atomic and 
+So I am now thinking the way to go for now is to allow Atomic and
 Atomic_Components only, and not allow any of the others.
 
-If we ever come up with a more concrete need for the others, they can be added 
+If we ever come up with a more concrete need for the others, they can be added
 in the future.
 
 Unless I hear otherwise, I will write the AI up this way....
@@ -2734,15 +2734,15 @@
 Sent: Friday, May 18, 2018  8:48 PM
 
 ...
-> So I am now thinking the way to go for now is to allow Atomic and 
+> So I am now thinking the way to go for now is to allow Atomic and
 > Atomic_Components only, and not allow any of the others.
-> 
-> If we ever come up with a more concrete need for the others, they can be 
+>
+> If we ever come up with a more concrete need for the others, they can be
 > added in the future.
-> 
+>
 > Unless I hear otherwise, I will write the AI up this way....
 
-Seems a reasonable starting point.  In the long run, supporting all of them 
+Seems a reasonable starting point.  In the long run, supporting all of them
 makes the most sense, but I can see starting with just Atomic.
 
 ****************************************************************
@@ -2753,19 +2753,19 @@
 Here is my updated AI for the lock free libraries. [This is version /03 of the
 AI - Editor.]
 
-Other than some minor changes addressing comments received so far, the big 
+Other than some minor changes addressing comments received so far, the big
 difference is that I split out the two other parts which will be appearing as
 new separate AI's.
 
-Specifically, I removed that part about pragma CPU being specifiable on 
+Specifically, I removed that part about pragma CPU being specifiable on
 protected object declarations, and I removed that part about allowing pragma
 Atomic to be specifiable on generic formal types, which this AI depends on.
 
-The discussion is simplified a lot, and the problem I think provides clearer 
+The discussion is simplified a lot, and the problem I think provides clearer
 and better motivation.
 
-I think the calls for Atomic_Thread_Fence and Atomic_Signal_Fence will 
-definitely need more wording to describe those concepts if we want to support 
+I think the calls for Atomic_Thread_Fence and Atomic_Signal_Fence will
+definitely need more wording to describe those concepts if we want to support
 those calls. I left those loosely and simply defined, in case we decide to drop
 those calls.
 
@@ -2776,18 +2776,18 @@
 
 > Here is my updated AI for the lock free libraries.
 
-For the record, I made a handful of editorial corrections to this AI when I 
+For the record, I made a handful of editorial corrections to this AI when I
 posted it.
 
-(1) Corrected the spelling of "synchronization" from "syncronisation" (Ada 
+(1) Corrected the spelling of "synchronization" from "syncronisation" (Ada
 uses American English spellings, thus a 'z' rather than an 's').
 
 (2) Inserted the actual number of the AI for atomic formal types
-(AI12-0282-1) and moved it's paragraph last in the !proposal section. (It 
-reads best giving the general solution first, then why the libraries are 
+(AI12-0282-1) and moved it's paragraph last in the !proposal section. (It
+reads best giving the general solution first, then why the libraries are
 generic, and finally that the libraries depend on another new AI.)
 
-(3) You had two A.19.2 subclauses in your proposal; I renumbered the 
+(3) You had two A.19.2 subclauses in your proposal; I renumbered the
 subclauses to eliminate this.
 
 ****************************************************************
@@ -2796,13 +2796,13 @@
 Sent: Wednesday, June 6, 2018  5:31 PM
 
 ...
-> I think the calls for Atomic_Thread_Fence and Atomic_Signal_Fence will 
-> definitely need more wording to describe those concepts if we want to 
-> support those calls. I left those loosely and simply defined, in case 
+> I think the calls for Atomic_Thread_Fence and Atomic_Signal_Fence will
+> definitely need more wording to describe those concepts if we want to
+> support those calls. I left those loosely and simply defined, in case
 > we decide to drop those calls.
 
 A bit too loosely to even quite understand what they do! It's hard to decide
-if these are useful without figuring out where they fit into the Ada 
+if these are useful without figuring out where they fit into the Ada
 synchronization model.
 
 Specifically:
@@ -2811,32 +2811,32 @@
 
 Ada doesn't have "threads", per se; it would be better in this AI to use the
 proper Ada terminology (even in the discussion). Probably you need to use the
-terminology that Tucker is coming up with for AI12-0119-1 (I forget the 
+terminology that Tucker is coming up with for AI12-0119-1 (I forget the
 details now; not sure if "tasklet" or something else is appropriate).
 
-And of course "synchronization fence" is also an undefined term. You need to 
-tie this to 9.10 in order to explain how this fits in with the Ada 
+And of course "synchronization fence" is also an undefined term. You need to
+tie this to 9.10 in order to explain how this fits in with the Ada
 synchronization model. (That also would be true when discussing the C "memory
-models"; it seems to me that one can only use weaker/stronger models on 
+models"; it seems to me that one can only use weaker/stronger models on
 individual operations lest the result violate the 9.10 model. And I doubt that
-9.10 requires completely sequentially consistent operations; it only requires 
+9.10 requires completely sequentially consistent operations; it only requires
 that of objects that you can see [anything being allowed for things that can't
-change the execution of the program]. Not sure how one would reconcile that - 
+change the execution of the program]. Not sure how one would reconcile that -
 to be discussed -- or possibly not.)
 
 The second one is worse:
 
-"This procedure acts as a synchronization fence between a thread and signal 
+"This procedure acts as a synchronization fence between a thread and signal
 handlers in the same thread."
 
-Ada has neither "threads" nor "signal handlers". It's unclear to me why a 
+Ada has neither "threads" nor "signal handlers". It's unclear to me why a
 protected object would need special synchronization in this case -- 9.10 seems
-to imply all protected actions need to be fenced (at least if the compiler 
+to imply all protected actions need to be fenced (at least if the compiler
 can't prove the absence of volatile/atomic objects in the action).
 (Alternatively, all atomic writes need to be fenced. Gotta have one or the
 other.)
 
-In any case, 9.10 implies that fencing is done implicitly, and it's not 
+In any case, 9.10 implies that fencing is done implicitly, and it's not
 obvious to me whether explicit fencing buys enough to try to define it (the
 AARM suggests defining an atomic object for synchronization, and that would
 carry a fence when needed).
@@ -2851,46 +2851,46 @@
 (Following up a bit on the previous "fence" comment...)
 
 ...
-> > I tend to not want to worry about it. The C++ memory models seem to 
-> > correspond roughly to "normal"/Volatile/Atomic objects -- Ada sets 
-> > these models per-object rather than per program. If we wanted (say) 
-> > a volatile version of these libraries, I'd expect that it would have 
-> > to be separately defined (given the way you defined aspect 
-> > matching). And I can't imagine adopting a C++ memory model that 
-> > essentially strips the guarantees of Atomic while still allowing 
+> > I tend to not want to worry about it. The C++ memory models seem to
+> > correspond roughly to "normal"/Volatile/Atomic objects -- Ada sets
+> > these models per-object rather than per program. If we wanted (say)
+> > a volatile version of these libraries, I'd expect that it would have
+> > to be separately defined (given the way you defined aspect
+> > matching). And I can't imagine adopting a C++ memory model that
+> > essentially strips the guarantees of Atomic while still allowing
 > > objects to be declared that way.
-> 
-> I think Ada's per object approach is a sensible one, but I think the 
-> memory model concept is someone independent of the 
+>
+> I think Ada's per object approach is a sensible one, but I think the
+> memory model concept is someone independent of the
 > volatile/atomic/normal semantics.
 
 ...
-> So, the memory order seems somewhat orthogonal to the atomicity class 
+> So, the memory order seems somewhat orthogonal to the atomicity class
 > of the object.
-> In some cases, different orders might ideally be wanted to be applied 
+> In some cases, different orders might ideally be wanted to be applied
 > to the same object at different times to get better performance.
 
-The C++ library seems to be applying synchronization per-operation rather 
+The C++ library seems to be applying synchronization per-operation rather
 than per-object as Ada does (this example shows that I was confused on that
 point in the past).
 
 I still contend that it is a bad idea to have operations that don't follow
 the usual guarentees provided by the language. In particular, Ada requires
 that atomic operations are handled "sequentially consistent" (at least WRT
-to the tasks that use those atomics). I think it would be a bad idea to 
+to the tasks that use those atomics). I think it would be a bad idea to
 define operations that violated that expectation.
 
 OTOH, it would make perfect sense to allow *stronger* operations to be applied
 to objects with a *weaker* categorization. Specifically, it would make perfect
 sense to have a volatile version of the library that provided some sequentially
 consistent operations on volatile-not-atomic objects. (Which implicitly answers
-your question: a weaker memory model would require a different package than 
+your question: a weaker memory model would require a different package than
 this one, which is only for atomic types - specifically, the formal parameter
 would have to allow volatile types.)
 
 If we had such a library (atomic operations for volatile-not-atomic), then the
-example above could be constructed, using normal volatile operations other 
-than when sequential consistency is required. That would give the intended 
+example above could be constructed, using normal volatile operations other
+than when sequential consistency is required. That would give the intended
 semantics.
 
 Of course, as a tool that only synchronization Jedis should consider using,
@@ -2904,31 +2904,31 @@
 From: Brad Moore
 Sent: Sunday, June 10, 2018  12:51 PM
 
-> The C++ library seems to be applying synchronization per-operation 
-> rather than per-object as Ada does (this example shows that I was 
+> The C++ library seems to be applying synchronization per-operation
+> rather than per-object as Ada does (this example shows that I was
 > confused on that point in the past).
-> 
-> I still contend that it is a bad idea to have operations that don't 
-> follow the usual guarentees provided by the language. In particular, 
-> Ada requires that atomic operations are handled "sequentially 
-> consistent" (at least WRT to the tasks that use those atomics). I 
+>
+> I still contend that it is a bad idea to have operations that don't
+> follow the usual guarentees provided by the language. In particular,
+> Ada requires that atomic operations are handled "sequentially
+> consistent" (at least WRT to the tasks that use those atomics). I
 > think it would be a bad idea to define operations that violated that expectation.
-> 
-> OTOH, it would make perfect sense to allow *stronger* operations to be 
-> applied to objects with a *weaker* categorization. Specifically, it 
-> would make perfect sense to have a volatile version of the library 
+>
+> OTOH, it would make perfect sense to allow *stronger* operations to be
+> applied to objects with a *weaker* categorization. Specifically, it
+> would make perfect sense to have a volatile version of the library
 > that provided some sequentially consistent operations on volatile-not-atomic objects.
-> (Which implicitly answers your question: a weaker memory model would 
-> require a different package than this one, which is only for atomic 
-> types - specifically, the formal parameter would have to allow 
+> (Which implicitly answers your question: a weaker memory model would
+> require a different package than this one, which is only for atomic
+> types - specifically, the formal parameter would have to allow
 > volatile types.)
-> 
-> If we had such a library (atomic operations for volatile-not-atomic), 
-> then the example above could be constructed, using normal volatile 
-> operations other than when sequential consistency is required. That 
+>
+> If we had such a library (atomic operations for volatile-not-atomic),
+> then the example above could be constructed, using normal volatile
+> operations other than when sequential consistency is required. That
 > would give the intended semantics.
 
-Except that I believe our definition of Volatile was intended to match C's 
+Except that I believe our definition of Volatile was intended to match C's
 definition of Volatile, and from what I can gather, the volatile keyword in
 C is not useful for sharing data between threads.
 
@@ -2938,69 +2938,69 @@
 
 The three apparent users are;
 
-- to mark local variables in the same scope as a setjmp whose value should 
+- to mark local variables in the same scope as a setjmp whose value should
   be preserved across a longjmp. (Not of interest to Ada, since setjmp and
   longjmp do not work well with Ada.)
 
-- when variables may be "externally modified", but the modification in fact 
+- when variables may be "externally modified", but the modification in fact
   is triggered synchronously by the thread itself (such as memory mapped I/O)
 
-- to communicate with a signal handler in the same thread, in a restricted 
+- to communicate with a signal handler in the same thread, in a restricted
   manner.
 
-Otherwise, volatile provides no other benefits other than slow code down by 
+Otherwise, volatile provides no other benefits other than slow code down by
 not eliminating redundant store and load operations, at least for portability
 considerations.
 
-I believe one of the main issues is with regard to reordering of instructions 
-either by the compiler or by the hardware. Reads and writes of the same 
+I believe one of the main issues is with regard to reordering of instructions
+either by the compiler or by the hardware. Reads and writes of the same
 volatile variable would be seen in the same order by different threads, but
-read/writes of other volatile variables could be moved past or before 
-read/writes of other volatile variables. With Atomic, the memory fences or 
+read/writes of other volatile variables could be moved past or before
+read/writes of other volatile variables. With Atomic, the memory fences or
 barriers prevent these sorts of moves.
 
 As such, I believe the volatile keyword in C (and presumably in Ada) have no
 mapping to the types of memory ordering semantics defined by C/C++.
 
-You might get the intended behaviour on certain targets such as Intel 
+You might get the intended behaviour on certain targets such as Intel
 processors, but when you try to port the code to other processors, you may get
-very subtle difficult to debug incorrect behaviour. 
+very subtle difficult to debug incorrect behaviour.
 
-So, I think if we wanted to someday support memory models other than the 
-sequentially consistent model, we'd probably need to end up defining new 
+So, I think if we wanted to someday support memory models other than the
+sequentially consistent model, we'd probably need to end up defining new
 keywords or aspects (e.g. atomic_acquire_release, atomic_relaxed) and either
 as you say have multiple versions of these libraries that can also work with
 stronger memory models. Or alternatively, I suppose expand the definition of
 atomic to encompass all of the memory models, and have the default flavour of
-atomic be sequentially consistent, but perhaps allow aspects to weaken the 
-memory model to one of the other flavours of atomic if desired. Then maybe 
+atomic be sequentially consistent, but perhaps allow aspects to weaken the
+memory model to one of the other flavours of atomic if desired. Then maybe
 you'd only need one version of the library. You could instantiate with say an
 atomic_acquire_release type, but could override a call with a stronger memory
-ordering if desired, perhaps by supplying an extra parameter to the call, 
+ordering if desired, perhaps by supplying an extra parameter to the call,
 like they do in C/C++.
 
-On an aside, I currently use Volatile in my paraffin parallelism libraries to 
-set a boolean flag that idle workers are interested in being assigned more 
+On an aside, I currently use Volatile in my paraffin parallelism libraries to
+set a boolean flag that idle workers are interested in being assigned more
 work by other threads. The code is written so that if another thread sees the
-flag set, it attempts use hand off work using a protected object to provide 
+flag set, it attempts use hand off work using a protected object to provide
 save synchronization. If multiple tasks see the same flag being set, only one
-will win, and others get told that the attempt to hand off via the protected 
+will win, and others get told that the attempt to hand off via the protected
 object failed.
 
-It is not clear if this very limited use of Volatile might be portably safe 
+It is not clear if this very limited use of Volatile might be portably safe
 enough to keep.
 
 This appears to work on the hardware I have tried including Intel/Android/ and
 ARM, and I have done a lot of testing and not seen any failures.
 I have tried replacing Volatile with Atomic, and seen significant slow downs.
 
-My suspicion is that if there is a problem, the optimal fix would be to 
+My suspicion is that if there is a problem, the optimal fix would be to
 replace with atomic calls using lower memory ordering models, if they were
 available in Ada. But I dont think calling out to a C library which has these
-calls would be worthwhile, since from Ada it likely involves at least 1 if 
-not two procedure calls to insert the instructions needed for the memory 
+calls would be worthwhile, since from Ada it likely involves at least 1 if
+not two procedure calls to insert the instructions needed for the memory
 barrier/fences, which can introduce enough overhead to eliminate benefits of
-making the call. 
+making the call.
 
 ****************************************************************
 
@@ -3011,15 +3011,15 @@
 > triggered synchronously by the thread itself (such as memory mapped I/O)
 
 
-This is the main usage for Ada.  It means the content of the object might 
+This is the main usage for Ada.  It means the content of the object might
 change at any time due to activity in other threads or hardware devices.
 
 ...
-> Otherwise, volatile provides no other benefits other than slow code down by 
-> not eliminating redundant store and load operations, at least for 
+> Otherwise, volatile provides no other benefits other than slow code down by
+> not eliminating redundant store and load operations, at least for
 > portability considerations.
 
-Volatile is not useful for synchronization, but it can be useful to indicate 
+Volatile is not useful for synchronization, but it can be useful to indicate
 that data is visible to other threads or other hardware devices.
 
 ****************************************************************
@@ -3028,24 +3028,24 @@
 Sent: Sunday, June 10, 2018  4:48 PM
 
 ...
-> Otherwise, volatile provides no other benefits other than slow code 
-> down by not eliminating redundant store and load operations, at least 
+> Otherwise, volatile provides no other benefits other than slow code
+> down by not eliminating redundant store and load operations, at least
 > for portability considerations.
 
 As Tucker noted, that's not really true. Volatile is very useful when
 *combined* with some other synchronization method, because it guarantees that
-the other tasks can see the changes as expected at a synchronization point. 
-Even that is not necessarily true for ordinary variables; there is no 
+the other tasks can see the changes as expected at a synchronization point.
+Even that is not necessarily true for ordinary variables; there is no
 guarantee as to what another task sees at any point for ordinary objects.
 
-Steve has noted that Volatile used for external devices really is subtly 
+Steve has noted that Volatile used for external devices really is subtly
 different than Volatile used for data to be safely usable as synchronization
 points. But that doesn't seem different enough for the complication.
 
 As I noted, there might be value to adding synchronization to Volatile objects
-on a per-operation basis. The rest of the C memory model stuff seems confused 
+on a per-operation basis. The rest of the C memory model stuff seems confused
 and unnecessary. (I'm not enough of an expert in these ideas to be certain.)
-It appears that they don't trust the compiler to do the right thing, so 
+It appears that they don't trust the compiler to do the right thing, so
 they're trying to do it manually. Ada usually takes the other approach of
 trusting the compiler more than the programmer.
 
@@ -3054,8 +3054,8 @@
 From: Erhard Ploedereder
 Sent: Sunday, June 10, 2018  7:35 PM
 
-> Except that I believe our definition of Volatile was intended to match 
-> C's definition of Volatile, and from what I can gather, the volatile 
+> Except that I believe our definition of Volatile was intended to match
+> C's definition of Volatile, and from what I can gather, the volatile
 > keyword in C is not useful for sharing data between threads.
 
 I can confirm that for C++, based on a discussion that we (OWG) had with
@@ -3070,20 +3070,20 @@
 Sent: Monday, June 11, 2018  9:14 PM
 
 That's my understand of how it works for Ada these days (Ada 2012) as well.
-The discussion and wording of AI05-0275-1 says as much. One needs a 
+The discussion and wording of AI05-0275-1 says as much. One needs a
 synchronization point in order to be able to reason about volatile objects
 in multiple tasks.
 
-But "not useful for synchronization of threads" is not the same as "not 
+But "not useful for synchronization of threads" is not the same as "not
 useful for sharing data between threads". It just has to be shared using
 some other method (including atomics) for synchronization.
 
-I note in passing that implies that a fence/barrier needs to be associated 
+I note in passing that implies that a fence/barrier needs to be associated
 with every synchronization event, whether or not atomic objects are involved
-(unless of course, the compiler can prove that nothing volatile could have 
+(unless of course, the compiler can prove that nothing volatile could have
 been read/written since the last such fence -- not very likely). That means
-(for instance) that a protected action needs a fence (somewhere) even in a 
-lock-free environment, otherwise any volatile objects won't be properly 
+(for instance) that a protected action needs a fence (somewhere) even in a
+lock-free environment, otherwise any volatile objects won't be properly
 synchronized afterwards. That seems necessary to keep the high-level view
 tractable, especially for high-level constructs like protected actions and
 rendezvous.
@@ -3093,8 +3093,8 @@
 From: Brad Moore
 Sent: Wednesday, June 13, 2018  7:28 AM
 
-> But "not useful for synchronization of threads" is not the same as 
-> "not useful for sharing data between threads". It just has to be 
+> But "not useful for synchronization of threads" is not the same as
+> "not useful for sharing data between threads". It just has to be
 > shared using some other method (including atomics) for synchronization.
 
 I believe that is how I am using the volatile keyword. Basically, I use it as
@@ -3106,16 +3106,16 @@
 From: Randy Brukardt
 Sent: Thursday, June 14, 2018  6:34 PM
 
-This sounds backwards to me (although I'm at the limits of my knowledge 
-here!). You can only trust a read of a volatile object *after* a 
-synchronization point, as to prevent erroneousness, the actions (the write 
-and the read) have to be sequential. The means either a protected action, 
-an atomic operation, or one of the "signaling" operations (rendezvous et. 
+This sounds backwards to me (although I'm at the limits of my knowledge
+here!). You can only trust a read of a volatile object *after* a
+synchronization point, as to prevent erroneousness, the actions (the write
+and the read) have to be sequential. The means either a protected action,
+an atomic operation, or one of the "signaling" operations (rendezvous et.
 al.).
 
 If the read and write are not separated by something making then sequential,
 then it isn't trustworthy (although practically I'd expect that eventually
-the change would get reflected, but not necessarily before several writes 
+the change would get reflected, but not necessarily before several writes
 happened).
 
 I remember Robert saying that there are things that are formally erroneous,
@@ -3124,6 +3124,254 @@
 in other tasks, but it's hard to imagine that it won't happen eventually
 (especially as it is highly likely that some synchronization will happen
 sooner or later).
+
+****************************************************************
+
+From: Brad Moore
+Sent: Sunday, March 3, 2019  12:10 PM
+
+IN relation to the discussion of AI 234, Compare and Swap, I think the following
+two sentences are confusing because they imply that two unrelated parts of the
+discussion are related.
+
+"The type Test_And_Set seems over-specified. Brad says that the C library has
+three such types, 1, 2, and 4 bytes."
+
+  and
+
+"It is suggested that test-and-set should be declared in one of the generics,
+not using a built-in-type. C doesn't have generics so it had to provide fixed
+size operations."
+
+When I was talking about 1, 2, and 4 bytes, I was attempting to explain why some
+of the packages were generic, and why the Test_And_Set subprograms were not
+generic. I was not saying that the test_and_set type can be 1, 2, or 4 bytes.
+The gcc documentation says this must always be 1 byte (a bool or char)
+
+In other words, the first sentence about being over-specified is unrelated to
+the second sentence about the number of bytes. So, I think it would help clarify
+if these are separated better in the minutes. Or alternatively delete the second
+sentence about the number of bytes.
+
+I'd suggest however that I'd like to see that the second sentence is moved
+after;
+
+"type Test_And_Set_Type is mod <implementation-defined>
+
+   with Atomic;"
+
+And then preceding the second sentence with something like, "In explaining why
+the other functions are in generic units, Brad says...."
+
+I think the sentence, "C doesn't have generics so it had to provide fixed size
+operations.", should probably be deleted, or moved to follow the "Brad says ..."
+sentence.
+
+For the record, the relevant gcc documentation for the test_and_set function is;
+
+  "Built-in Function: bool __atomic_test_and_set (void *ptr, int memorder) This
+  built-in function performs an atomic test-and-set operation on the byte at
+  *ptr. The byte is set to some implementation defined nonzero “set” value and
+  the return value is true if and only if the previous contents were “set”. It
+  should be only used for operands of type bool or char. "
+
+And for the record, the following quote from the manual shows in fact that in
+addition to 1,2, and 4 bytes, 8, and 16 bytes can be supported for the other
+atomic functions if the hardware supports it.
+
+"The ‘__atomic’ builtins can be used with any integral scalar or pointer type
+that is 1, 2, 4, or 8 bytes in length. 16-byte integral types are also allowed
+if ‘__int128’ (see __int128) is supported by the architecture."
+
+But I agree that the Test_And_Set subprograms could and should be moved into the
+generic packages, which would simplify things. But I don't see now the built-in
+type can by avoided, as the generic formal type used in all the other functions
+is not used in the test_and_set call.
+
+I think the suggestion to make it implementation defined however, helps.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Sunday, March 3, 2019  3:09 PM
+
+If test-and-set really is only supported on single-byte objects, then that is
+useful to know.  I would make it a separate generic, with an assertion that
+the formal type is a single storage unit.  This limitation to a single byte
+was not clear, as least to me, in the AI.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Sunday, March 3, 2019  7:43 PM
+
+> If test-and-set really is only supported on single-byte objects, then
+> that is useful to know.  I would make it a separate generic, with an
+> assertion that the formal type is a single storage unit.  This
+> limitation to a single byte was not clear, as least to me, in the AI.
+
+He had a size clause to require a single byte representation in the AI, that's what we were discussing at the point of the minutes. And when someone asked him what the C library supported in that case, he answered "1, 2, or 4 bytes". I am certain of this 
point, because I remember being quite surprised by that answer. If the facts are confused in the minutes, that's because they were presented that way.
+
+Thus, I think the best solution here for the minutes is to add some sort of square bracketed clarification. I'd prefer the minutes reflect what actually was discussed rather than what we *meant* to discuss. (I realize that I sometimes write what I meant t
o say, but that's because it's not separate in my mind. Hopefully reviewers will note such errors.)
+
+****************************************************************
+
+From: Erhard Ploedereder
+Sent: Monday, March 4, 2019  5:29 AM
+
+>> "The type Test_And_Set seems over-specified. Brad says that
+> the C library has three such types, 1, 2, and 4 bytes."
+
+Which library is that? I locked it up in the C11 standard and all I
+could find was section 7.17.8, which (very resonably) expects one
+implementation-dependently sized type:
+
+---- copied from the pre-standard ---
+7.17.8 Atomic flag type and operations
+
+1 The atomic_flag type provides the classic test-and-set functionality.
+It has two states, set and clear.
+
+2 Operations on an object of type atomic_flag shall be lock free.
+
+3 NOTE Hence the operations should also be address-free. No other type
+requires lock-free operations, so
+the atomic_flag type is the minimum hardware-implemented type needed to
+conform to this
+International standard. The remaining types can be emulated with
+atomic_flag, though with less than ideal properties.
+...
+
+7.17.8.1 The atomic_flag_test_and_set functions
+Synopsis
+1 #include <stdatomic.h>
+bool atomic_flag_test_and_set(
+volatile atomic_flag *object);
+bool atomic_flag_test_and_set_explicit(
+volatile atomic_flag *object, memory_order order);
+
+****************************************************************
+
+From: Brad Moore
+Sent: Monday, March 4, 2019  10:15 AM
+
+>> If test-and-set really is only supported on single-byte objects, then
+>> that is useful to know.  I would make it a separate generic, with an
+>> assertion that the formal type is a single storage unit.  This
+>> limitation to a single byte was not clear, as least to me, in the AI.
+
+What I'm thinking is to just have a single generic package for everything. I
+believe the test and set type can be a private type declared in that package,
+which solves the problem of trying to define its size in the visible part of the
+spec. I am thinking also of getting rid of the generic package with the generic
+formal;
+
+    type Atomic_Type is range <>;
+
+and just have one package with the formal;
+
+     type Atomic_Type is mod <>;
+
+for modular arithmetic.
+
+because I think perhaps that is the best fit for the gcc instrinsic functions.
+They dont actually provide signed and modular functions, everything is just
+integer types.
+
+in C, I believe you can use unsigned or signed arithmetic types, but they don't
+handle arithmetic overflow, which we would need to implement these in Ada.
+
+In my package implementation, for the signed arithmetic functions I had to do
+funny things like apply the atomic operation, but then also do do the
+calculation a second time using the previous value of the atomic, and the formal
+parameter value, so that the arithmetic overflow could be caught.
+
+With the modular arithmetic version of the package, it is much simpler, I just
+simply call the gcc function without having to jump through any hoops.
+
+Since there appears to be an appetite for simplifying these packages, I think it
+makes sense to drop the signed arithmetic support.
+
+So in summary, my plan is to create two AI's. One just has the compare and swap,
+and the second adds the other functions to the same package.
+
+Does that sound like a good approach?
+
+> He had a size clause to require a single byte representation in the
+> AI, that's what we were discussing at the point of the minutes. And
+> when someone asked him what the C library supported in that case, he
+> answered "1, 2, or 4 bytes". I am certain of this point, because I
+> remember being quite surprised by that answer. If the facts are
+> confused in the minutes, that's because they were presented that way.
+
+My recollection is that something funny happened at that point in the
+discussion. Possibly there were two different questions asked in quick
+succession, and while providing and answer for the first, it was taken as the
+answer for the second, or perhaps someone interrupted me before I could finish
+my explanation, or possibly both. I just remember being unsatisfied that somehow
+what I wanted to say wasn't communicated correctly, but the discussion moved on,
+from there, so I didn't say anything more on that. I tried to find the recorded
+audio session for the meeting to confirm my recollection/suspicion, but I guess
+it wasn't sent around. In any case, I think your suggestion for square bracketed
+clarification sounds fine by me.
+
+***************************************************************
+
+From: Brad Moore
+Sent: Monday, March 4, 2019  10:30 AM
+
+>>> "The type Test_And_Set seems over-specified. Brad says that
+>> the C library has three such types, 1, 2, and 4 bytes."
+>
+> Which library is that? I locked it up in the C11 standard and all I
+> could find was section 7.17.8, which (very resonably) expects one
+> implementation-dependently sized type:
+
+There is only one type. There are some other emails about my miscommunication leading to statements in the minutes, which do not reflect what I was intending to say.
+
+I believe Randy is planning to add some sort of clarification to the minutes.
+
+> ---- copied from the pre-standard ---
+> 7.17.8 Atomic flag type and operations
+>
+> 1 The atomic_flag type provides the classic test-and-set functionality.
+> It has two states, set and clear.
+>
+> 2 Operations on an object of type atomic_flag shall be lock free.
+>
+> 3 NOTE Hence the operations should also be address-free. No other type
+> requires lock-free operations, so
+> the atomic_flag type is the minimum hardware-implemented type needed to
+> conform to this
+> International standard. The remaining types can be emulated with
+> atomic_flag, though with less than ideal properties.
+> ...
+>
+> 7.17.8.1 The atomic_flag_test_and_set functions
+> Synopsis
+> 1 #include <stdatomic.h>
+> bool atomic_flag_test_and_set(
+> volatile atomic_flag *object);
+> bool atomic_flag_test_and_set_explicit(
+> volatile atomic_flag *object, memory_order order);
+
+Interesting that C11 has functions for this. I was looking at the gcc instrinsic
+functions
+
+see
+
+https://gcc.gnu.org/onlinedocs/gcc-8.3.0/gcc/_005f_005fatomic-Builtins.html#g_t_005f_005fatomic-Builtins
+
+Which are extensions to their support for C, and also supports the C++ memory
+models.
+
+Built-in Function: bool __atomic_test_and_set (void *ptr, int memorder)
+
+which essentially has the same profile. We are not planning to support the C++
+memory models, so the memorder parameter will not be present in the Ada calls.
+
+The ptr parameter is expected to be the address of a byte of storage, as only
+the one byte pointed to by that address is modified by the call.
 
 ****************************************************************
 

Questions? Ask the ACAA Technical Agent