Version 1.5 of ai12s/ai12-0363-1.txt

Unformatted version of ai12s/ai12-0363-1.txt version 1.5
Other versions for file ai12s/ai12-0363-1.txt

!standard 3.10.2(26/3)          20-06-15 AI12-0363-1/05
!standard 9.10(1/5)
!standard C.6(13.3/5)
!standard C.6(19.1/5)
!class Amendment 20-02-05
!status Amendment 1-2012 20-06-15
!status ARG Approved 10-0-2 20-06-13
!status work item 20-02-05
!status received 19-11-12
!priority Low
!difficulty Medium
!subject Fixes for Atomic and Volatile
!summary
We clarify the wording associated with AI12-0128-1 having to do with "rounding up" accesses to nonatomic subcomponents of atomic objects. We introduce a new boolean aspect "Full_Access_Only" which requires any access to any subcomponent to be "rounded up" to the enclosing Full_Access_Only object, and disallows having any "full access" subcomponents. We indicate that the default for Volatile(_Components) and Independent(_Components) is False only if their value is not already determined by a corresponding Atomic(_Components) specification. We try to clean up the places in the wording of C.6 where changes due to multiple partially overlapping AIs have led to inconsistent or unclear wording.
!problem
(1) C.6(13.3/5) disallows marking a type atomic if it has nonatomic aliased subcomponents, but says nothing about marking an object of such type as atomic. This doesn't make much sense, and we can instead solve the problem by preventing taking 'Access of a nonatomic subcomponent of an atomic object, rather than trying to disallow the existence of aliased subcomponents. C.6(13.3/5) also bans independently addressable components of nonatomic subcomponents of an atomic type. This seems unnecessary, and we can again address this by saying such subcomponents cannot be manipulated concurrently. (Net effect is we can eliminate the last two sentences of this paragraph, and handle these issues elsewhere.)
(2) We have said that nonatomic subcomponents of an atomic object, when read or written, will have their access "rounded up" to the nearest enclosing atomic object (with a "write" to such a subcomponent typically performed as an atomic read followed by an atomic write of the enclosing atomic object). However, what about atomic subcomponents of atomic objects? It would be incompatible to disallow them completely. Should we provide a separate aspect for specifying that no atomic subcomponents are permitted of a given atomic type? (Yes).
(3) It is not completely clear whether, in Ada 202X, an assignment to a nonatomic subcomponent of an atomic object is considered to be a single "action," or a sequence of two (sequential) actions, the first an atomic read and the second an atomic write. (It should be clarified that they are treated as two sequential actions.)
(4) We disallow having a volatile type used as an actual for a generic formal array type, unless the element type of the formal type is volatile. Why is that, and why doesn't it mention atomic? (We clarify and fix a hole in the rule.)
(5) The current wording implies that Volatile and Independent default to False if not specified. But if Atomic is specified True, we want Volatile and Independent to default to True (in fact, they are True, and that should only allow to be confirmed). We should similarly say that Volatile_Components is essentially equivalent to Volatile, and that we provide both merely to be consistent with Atomic_Components and Independent_Components. (We fix the wording.)
(6) Overall, C.6 has been updated by various different AIs. It would be good to scrub the wording to make sure it is consistent and clear. (We try to do that in this AI.)
!proposal
We move the check for not taking 'Access of an aliased subcomponents of an atomic object to 3.10.2. We move to 9.10 the rule that says independently addressable, but nonatomic subcomponents of an atomic object are not safely manipulatable concurrently.
We add a Full_Access_Only aspect which can be applied to atomic and volatile types and objects to indicate that no atomic (or full access) objects are permitted as subcomponents.
We refine the rule relating to generic formal array types, to clarify its purpose and fix a hole relating to formal array types with aliased components.
We fix the wording on Volatile and Independent so they properly are True if Atomic is specified True. Ditto for Volatile/Independent_Components. We make Volatile and Volatile_Components imply one another, since they are effectively equivalent (unlike Atomic_Components and Independent_Components).
!wording
Modify 3.10.2 (26/3):
* The view shall not be a subcomponent that depends on discriminants of an object unless the object is known to be constrained{;
* The view shall not be a nonatomic subcomponent of a full access object (see C.6)}.
Modify 9.10 (1/5):
If two different objects, including nonoverlapping parts of the same object, are independently addressable, they can be manipulated concurrently by two different logical threads of control without synchronization{, unless both are subcomponents of the same full access object, and either is nonatomic (see C.6)}.
Add after C.6(6.4/3):
Full_Access_Only The type of aspect Full_Access_Only is Boolean.
Modify C.6(6.10/3):
If any of these aspects are directly specified, the aspect_definition shall be a static expression. If not specified {for a type} (including by inheritance), [each of these]{the Atomic, Atomic_Components, and Full_Access_Only} aspects [is]{are} False. {If any of these aspects are specified True for a type, then the corresponding aspect is True for all objects of the type. If the Atomic aspect is specified True, then the aspects Volatile, Independent, and Volatile_Component (if defined) are True; if the Atomic_Components aspect is specified True, then the aspects Volatile, Volatile_Components, and Independent_Components are True. If the Volatile aspect is specified True, then the Volatile_Components aspect (if defined) is True, and vice versa. When not determined by one of the other aspects, or for an object by its type, the Volatile, Volatile_Components, Independent, and Independent_Components aspects are False.}
{AARM Ramification: Aspects Volatile and Volatile_Components (when defined) are equivalent. We provide the Volatile_Components aspect only to give symmetry with Atomic_Components and Independent_Components aspects.}
Add after C.6(8.1/4):
The Full_Access_Only aspect shall not be specified unless the associated type or object is volatile [Redundant:(or atomic)]. A /full access/ type is any atomic type, or a volatile type for which the aspect Full_Access_Only is True. A /full access/ object (including a component) is any atomic object, or a volatile object for which the aspect Full_Access_Only is True for the object [Redundant: or its type]. A Full_Access_Only aspect is illegal if any subcomponent of the object or type is a full access object or is of a generic formal type.
AARM Ramification: This last rule breaks privacy, but that is considered OK for representation clauses when there is no clear alternative. Note that atomic objects may be nested, so long as the outer atomic object does not have the Full_Access_Only aspect True.
AARM Reason: We disallow subcomponents of a generic formal type in a Full_Access_Only object or type as the actual to a formal type can be a full access type. We could have had a less restrictive rule, but such a use is unlikely as full access only objects are intended to be used to access memory-mapped devices with access restrictions, and those will need a concrete mapping not possible for generic formal types.
Modify C.6(12/5):
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 [Redundant: (including a component)], then the designated type of the resulting access type shall be atomic. Corresponding rules apply to volatile objects{ and to full access objects.}
Replace C.6(12.1/5):
If the Atomic, Atomic_Components, Volatile, Volatile_Components, Independent, or Independent_Components aspect is True for a generic formal type, then that aspect shall be True for the actual type. If a volatile type is used as an actual for a generic formal array type, then the element type of the formal type shall be volatile. 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. A corresponding rule applies to volatile types and similarly to full access types.
with:
If the Atomic, Atomic_Components, Volatile, Volatile_Components, Independent, Independent_Components, or Full_Access_Only aspect is True for a generic formal type, then that aspect shall be True for the actual type. 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. A corresponding rule applies to volatile types.
If a type with volatile components is used as an actual for a generic formal array type, then the components of the formal type shall be volatile. Furthermore, if the actual type has atomic components and the formal array type has aliased components, then the components of the formal array type shall also be atomic. A corresponding rule applies when the actual type has volatile full access components.
AARM Reason: The limitations on formal array types are separate for volatile and atomic because of the fact that only volatility is carried down to all subcomponents of a volatile object, while atomicity is not. The goal of both limitations is that we don't want 'Access for an access type to produce a value that designates an object whose atomicity and volatility don't agree with that of the designated type of the access type. The above rules ensure that the generic "sees" the relevant volatility and atomicity.
[Author's note: The rule on volatility could be relaxed somewhat, to require that only the aliased, tagged, or private subcomponents of the formal type are volatile, but the current rule has been in place since 2012, so we don't see the need to relax it at this point.]
Modify C.6(13.3/5):
If a nonatomic subcomponent of [an atomic]{a full access} object is passed as {an}[the] actual parameter in a call then the formal parameter shall allow pass by copy (and, at run time, the parameter shall be passed by copy). A nonatomic subcomponent of [an atomic]{a full access} object shall not be used as an actual for a generic formal of mode in out. [A nonatomic subcomponent of an atomic type shall not be aliased. A nonatomic subcomponent of an atomic type or object shall not have components that are specified to be independently addressable.]
Modify RM C.6(19.1/5):
All reads of or writes to any nonatomic subcomponent of [an atomic]{a full access} object are performed by reading and/or writing all of the nearest enclosing [atomic]{full access} object.
Add after AARM C.6(19.1.c/5):
AARM Discussion: The atomic reads and writes associated with accesses to nonatomic components of a full access object that is atomic are normal atomic operations -- all of the rules that apply to other atomic operations apply to these as well. In particular, these atomic reads and writes are sequential if they apply to the same object.
!discussion
(1) This can happen in cases like:
type R is record X : aliased Integer; end record;
Z : R with Atomic; -- Legal? (Yes.) P : access Integer := Z.X'access -- Legal? (No.)
We permit the type declaration, but disallow the 'Access. This is necessary in general to avoid breaking privacy, since we might actually have an aliased component of a component of R, where the component of R is of a private type.
For the issue of independent addressability, we remove the last sentence of (13.3/5), and change the rules associated with independent addressability in 9.10 to say that threads can safely manipulate independently addressable components, unless they are subcomponents of the same full access object, and either is nonatomic. This also prevents breaking privacy. The existing sentence could require breaking privacy in certain cases.
(2) We add the Full_Access_Only aspect to control whether nesting of atomic objects is permitted. The GNAT aspect Volatile_Full_Access is the inspiration for this, but it does not actually imply everything that "atomic" implies, so we allow it to be specified as an addition to either atomic or volatile. Volatile + Full_Access_Only is intended to match GNAT's existing pragma. Atomic + Full_Access_Only is essentially equivalent to simply "Atomic" but with the added legality rule that Full_Access_Only disallows having atomic (or full access) subcomponents. This does break privacy, but we could not figure out anyway to avoid it, and since it is a representation aspect, it is something that could be "bubbled up" and across private types.
(3) The AARM note C.6(19.1.c/5) describes the intent that a read-modify-write cycle is expected and that these are separate atomic reads and writes. As such, there are two operations and these are sequential with respect to any other operations on the same object.
(4) We went back to the original AI that introduced the restriction on generic formal array types, and discovered a hole having to do with formal arrays with aliased components, which only applies to atomic. So we move the formal array restriction into its own paragraph, handle both volatile and atomic special cases, and add an AARM note to explain what is behind the rules.
(5) There were words that indicated that all atomic objects are also volatile, but the defaulting to False of Volatile when not specified seemed to contradict that. Similar considerations apply to Independent, and the *_Components aspects. So we changed the rules and made the defaults match the semantics of atomic implying volatile and independent. Finally, Volatile and Volatile_Components are equivalent, so we make that explicit, and have one imply the other.
(6) We completely replace (12.1/5) because it had been edited so often that it didn't seem to end up in a logical sequence. Hopefully the new wording is a little clearer.
!ASIS
No changes needed.
!ACATS test
ACATS B-Tests for Annex C might need some changes to add or remove cases, but the changes aren't enough to need new tests.
!appendix

From: Tucker Taft
Sent: Tuesday, November 12, 2019  3:39 PM

It is not completely clear whether, in Ada 202X, an assignment to a nonatomic
subcomponent of an atomic object is considered to be a single "action," or a
sequence of two (sequential) actions, the first an atomic read and the second
an atomic write.   In other words, when two separate, concurrent tasks each
update a nonatomic subcomponent of the same object, is the execution erroneous?

Task1:  Atom.X := 1;
Task2:  Atom.Y := 3;

There is certainly a race condition, but a race condition between atomic
actions is not erroneous.  Another way to think about this, is should this be
treated as equivalent to:

Task1:  Atom2 := Atom2 + 3;
Task2:  Atom2 := Atom2 - 5;

The above is not erroneous, as it is a sequence of atomic (sequential) actions.

My instinct would be to consider an update to a nonatomic subcomponent of an
atomic object to be a sequence of two atomic actions, since we have now
defined the semantics that way.  As with the example of concurrent updates to
an atomic object, there are a well-defined set of possible outcomes, so the
situation is not unbounded.  We could declare it to be a bounded error, but we
haven't declared the second example to be a bounded error, so I would rather
not burden the programmer with a concern that a Program_Error might come
flying out some of the time.

Thoughts?

****************************************************************

From: Randy Brukardt
Sent: Tuesday, November 26, 2019  8:52 PM

> It is not completely clear whether, in Ada 202X, an assignment to a
> nonatomic subcomponent of an atomic object is considered to be a
> single "action," or a sequence of two
> (sequential) actions, the first an atomic read and the second
> an atomic write.   In other words, when two separate,
> concurrent tasks each update a nonatomic subcomponent of the same
> object, is the execution erroneous?

Could you explain why you say this?

...
> My instinct would be to consider an update to a nonatomic subcomponent
> of an atomic object to be a sequence of two atomic actions, since we
> have now defined the semantics that way.

This seems to me to be the answer: we have defined the semantics to be two
atomic actions. I can hardly imagine atomic actions that aren't sequential,
so I don't understand the question.

> As with the example of concurrent updates to an atomic object, there
> are a well-defined set of possible outcomes, so the situation is not
> unbounded.  We could declare it to be a bounded error, but we haven't
> declared the second example to be a bounded error, so I would rather
> not burden the programmer with a concern that a Program_Error might
> come flying out some of the time.
>
> Thoughts?

I don't know why you think the semantics aren't clear here. I don't know how
much clearer C.6(19.1/5) could be. The rewrite of C.6(20/5) and the associated
AARM note 20.j/5 make it clear that read-modify-write code is intended. And C.6
has no atomic update operations (that's the Brad library routines in Ada 202x).
What other semantics could there be?

As you noted, Atomic updates are never safe in Ada (outside of the new
libraries), and they need to be avoided if multiple writers are possible.
No reason for components to be different.

****************************************************************

From: Tucker Taft
Sent: Wednesday, November 27, 2019  7:55 AM

> This seems to me to be the answer: we have defined the semantics to be two
> atomic actions. I can hardly imagine atomic actions that aren't sequential,
> so I don't understand the question.

Fair enough.  I just think we should clarify this somewhere -- AARM note to
clarify the intent might be adequate.

****************************************************************

From: Tucker Taft
Sent: Thursday, November 14, 2019  10:22 AM

Eric Botcazou, the AdaCore engineer implementing AI12-0128, suggested some
refinements to the wording.  In particular, given this paragraph from
 C.6 (13.3/5):

"If a nonatomic subcomponent of an atomic object is passed as the actual
parameter in a call then the formal parameter shall allow pass by copy
(and, at run time, the parameter shall be passed by copy). A nonatomic
subcomponent of an atomic object shall not be used as an actual for a generic
formal of mode in out. A nonatomic subcomponent of an atomic type shall not
be aliased. A nonatomic subcomponent of an atomic type or object shall not
have components that are specified to be independently addressable."

He suggests the following additions (in {...}).

"If a nonatomic subcomponent of an atomic object is passed as the actual
parameter in a call then the formal parameter shall allow pass by copy (and,
at run time, the parameter shall be passed by copy). A nonatomic subcomponent
of an atomic object shall not be used as an actual for a generic formal of
mode in out. A nonatomic subcomponent of an atomic type {or object} shall not
be aliased. A nonatomic subcomponent of an atomic type or object shall not
have {nonatomic} {sub}components that are specified to be independently
addressable."

I am unsure why we didn't say "type or object" systematically in the above,
nor why we didn't say "subcomponents" rather than "components" systematically.
And in the last sentence, specifying something to be atomic is effectively
specifying it to be independently addressable, so it seems better to only
worry about nonatomic subcomponents.

Any comments or rationale for some of the subtle differences between the four
rules?

> Begin forwarded message:
>
> From: Eric Botcazou
> Subject: Re: [SB07-048] - Ada2020: AI12-0128 Exact size access to
> parts of composite atomic objects #999
> Date: November 14, 2019 at 8:09:14 AM EST
> To: "Tucker Taft @ adacore"
> Cc: Bob Duff
>
>> Interesting.  The author of the AI (I believe Steve Baird) was
>> clearly making a distinction, but I agree that if a type has a
>> (non-atomic) aliased (sub)component, you probably don't want to allow
>> an object of the type to be marked atomic.
>
> Right, so I'm going to implement this in the compiler:
>
> "A nonatomic subcomponent of an atomic type or object shall not be aliased."
>
>>> The fourth rule seems a bit too strong since, as per C.6 (8 1/3),
>>> atomic objects are considered to be specified as independently
>>> addressable, but atomic components of a nonatomic subcomponent of an
>>> atomic type or object don't seem to be problematic for the new semantics
>>> since nothing changes.
>>
>> Good point -- the fourth rule should probably say:
>>   A nonatomic subcomponent of an atomic type or object shall not have
>>  *nonatomic* components that are specified to be independently addressable.
>
> In the end, I think that it's essentially equivalent to:
>
> "A nonatomic subcomponent of an atomic type or object shall not be
> specified to be independently addressable."
>
> and I'm going to implement this in the compiler.

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 14, 2019  2:32 PM

A nonatomic subcomponent of an atomic object is necessarily Volatile (unlike
atomicity, volatility applies to components, and all atomic components), so
the rules in C.6(12/5) apply to such components. C.6(13.3/5) is just a
tightening of the rules for nonatomic subcomponents; not everything needs to
be covered.

Specific comments:

"A nonatomic subcomponent of an atomic type {or object} shall not be aliased."

How would a subcomponent of an atomic object be aliased if the type doesn't
declare it that way?? This is a check on a type definition, exclusively. (It
seems to be a privacy breaking check, however, which is annoying, but that
doesn't seem important given the unlikelyness of nonatomic components of a
private type -- these things tend to be integers or enumerations.)

"A nonatomic subcomponent of an atomic type or object shall not have
{nonatomic} {sub}components that are specified to be independently
addressable."

I think this rule is (implicitly) banning any atomic (sub)components of a
nonatomic subcomponent; how would that work? The nonatomic subcomponents would
prevent the inner things from being treated as atomic in some contexts, so
that is nonsense. If some component is atomic, then the enclosing type also
has to be atomic, and so on.

The proposed change would allow that sort of nonsense.

The AI discussion makes it clear that no nonatomic component of an atomic
object should *ever* be independently addressable. It makes no sense for some
subcomponent of a non-independently addressable object to be itself
independently addressable. Ergo, this second change is certainly a bad idea.

****************************************************************

From: Tucker Taft
Sent: Thursday, November 14, 2019  2:43 PM

...
> How would a subcomponent of an atomic object be aliased if the type
> doesn't declare it that way?? This is a check on a type definition,
> exclusively. (It seems to be a privacy breaking check, however, which
> is annoying, but that doesn't seem important given the unlikelyness of
> nonatomic components of a private type -- these things tend to be
> integers or enumerations.)

But what about:

    type R is record
       X : aliased Integer;
    end record;

    Z : R with Atomic;  -- Is this legal?

> "A nonatomic subcomponent of an atomic type or object shall not have
> {nonatomic} {sub}components that are specified to be independently
> addressable."
>
> I think this rule is (implicitly) banning any atomic (sub)components
> of a nonatomic subcomponent; how would that work?

I don't follow.  Perhaps the existing rule implied that, but with the addition
of "nonatomic" here, we are removing any restriction on atomic subcomponents.
Or am I missing your point?

> The nonatomic subcomponents
> would prevent the inner things from being treated as atomic in some
> contexts, so that is nonsense. If some component is atomic, then the
> enclosing type also has to be atomic, and so on.
>
> The proposed change would allow that sort of nonsense.

Sorry, I have lost you.  Can you give an example.

> The AI discussion makes it clear that no nonatomic component of an
> atomic object should *ever* be independently addressable. It makes no
> sense for some subcomponent of a non-independently addressable object
> to be itself independently addressable. Ergo, this second change is
> certainly a bad idea.

I have really lost you now.  Hopefully an example will clarify...

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 14, 2019  3:13 PM

> But what about:
>
>     type R is record
>        X : aliased Integer;
>     end record;
>
>     Z : R with Atomic;  -- Is this legal?

I forgot that is legal. (Not really sure *why* it should be legal to have
an atomic object of a nonatomic type, but never mind.)

The privacy breaking implied here bothers me in any case. No fix seems
possible, however (short of banning nonatomic components of partial views).

> > "A nonatomic subcomponent of an atomic type or object shall not have
> > {nonatomic} {sub}components that are specified to be independently
> > addressable."
> >
> > I think this rule is (implicitly) banning any atomic (sub)components
> > of a nonatomic subcomponent; how would that work?
>
> I don't follow.  Perhaps the existing rule implied that, but with the
> addition of "nonatomic" here, we are removing any restriction on
> atomic subcomponents.  Or am I missing your point?

My point is that we WANT to ban such components. They don't make any sense.

> > The nonatomic subcomponents
> > would prevent the inner things from being treated as atomic in some
> > contexts, so that is nonsense. If some component is atomic, then the
> > enclosing type also has to be atomic, and so on.
> >
> > The proposed change would allow that sort of nonsense.
>
> Sorry, I have lost you.  Can you give an example.

Sure. See below.

> > The AI discussion makes it clear that no nonatomic component of an
> > atomic object should *ever* be independently addressable. It makes
> > no sense for some subcomponent of a non-independently addressable
> > object to be itself independently addressable. Ergo, this second
> > change is certainly a bad idea.
>
> I have really lost you now.  Hopefully an example will clarify...

For something to be independently addressable, the thing it is a component
of has to be independently addressable. Otherwise, one runs into nonsense.

In this case, a nonatomic component is explicitly NOT independently
addressable. So consider the case you are trying to allow:

     type Byte_Array is (1..2) of Byte with Atomic_Components;

     -- Byte_Array is not atomic itself.

     type Dev_Reg is record
        Status : Flags;
        Data : Byte_Array;
        Padding : Byte;
     end record with Atomic;
     -- Rep. clause here, not relevant to the point.
     My_Reg : Dev_Reg;

Here, we've said that the nonatomic components Status, Data, and Padding of
an atomic type/object are not independently addressable. For instance,
     My_Reg.Status := Status;
does an atomic access to the entire My_Reg object.

That clearly applies to:
     My_Reg.Data := (2, 2);

But the declaration of Data implies that:
     My_Reg.Data(1) := 2;
     My_Reg.Data(2) := 2;
*is* independently addressable. That is, each of these components is written
atomically.

But for that to be the case, Data itself has to also be independently
addressable. We have a contradiction, and in particular the guarantee
provided by making the type Dev_Reg atomic is violated.

Again, it's nonsense to say that some component is independently addressable
when the enclosing type is not independently addressable. Usually, we simply
propagate that information upwards (the enclosing type is automatically
independently addressable if any components require that). But in this case,
we can't do that. So far as I'm aware, this is the only case where one can
turn *off* independent addressability, thus we need a special rule in that
case.

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 14, 2019  7:37 PM

Note that independent addressability itself is a guarantee; compilers are
usually free to provide it anywhere. But C.6(19.1/5) says not in this case,
so you get the contradiction.

I note that there also is a usability concern in allowing "deep" atomic
subcomponents. If someone is writing a type for which they are depending on
C.6(19.1/5) for correct operation, they don't want to have to check the entire
text of their program to ensure that it is true.

That is, any atomic components should be visible in the declaration of the
composite type, so that reading the type declaration and at most the
declarations of the component types (to see if any are declared Atomic) can
ensure that every read and write uses the entire hardware register. If one
allows Atomic subcomponents in nonatomic components of an atomic type, then
one has to read the details of every involved type to ensure this property.
That's a maintenance hazard waiting to happen (there's too many places that
would need a comment that "this type must not be declared atomic").

Note that you can still have atomic subcomponents, it's just necessary for
Byte_Array itself to be declared atomic in order for that to be allowed (in
which case C.6(19.1/5) clearly does not apply to the component, so no one
would be surprised when it does not apply to some part of the component).

****************************************************************

From: Tucker Taft
Sent: Thursday, November 14, 2019  10:13 PM

I'll admit to have lost track of what you are trying to say.  I had suggested
we alter the fourth rule from:

   A nonatomic subcomponent of an atomic type or object shall not have
   components that are specified to be independently addressable.

to:

   A nonatomic subcomponent of an atomic type or object shall not have
   nonatomic subcomponents that are specified to be independently
   addressable.

What are you proposing the rule should be?

****************************************************************

From: Randy Brukardt
Sent: Thursday, November 14, 2019  10:27 PM

Either the original wording, or perhaps better:

A nonatomic subcomponent of an atomic type or object shall not have
{sub}components that are specified to be independently addressable.

AARM Ramification: a subcomponent that is specified to be atomic is considered
to also specify that is independently addressable. [This follows from
C.6(8.1/4), which says this literally.]

A nonatomic component should not be allowed to have atomic or independently
addressable subcomponents, as that is a contradiction (the nonatomic component
is defined to be *not* independently addressable, and that has to apply to any
subparts as well).

If you do not believe the above, then you should simply suggest deleting the
rule entirely (whether something is declared atomic has no bearing on whether
it can be independently addressable).

Note that there is no problem having atomic components of atomic
types/objects; it just doesn't make sense to have nonatomic components
sandwiched in between.

****************************************************************

From: Brad Moore
Sent: Wednesday, March 11, 2020  1:12 PM

[Part of a larger message, just the relevant part here - Editor.]

Also, I had a typo in AI12-0363-1, that I didn't mention in our phone meeting.

AARM Ramification: 1st sentence,
"a subcomponent that is specified to be atomic is considered to also specify
that {it} is independently addressable."

****************************************************************

From: Tucker Taft
Sent: Wednesday, March 11, 2020  4:37 PM

[Part of a larger message, just the relevant part here - Editor.]

...
> Also, I had a typo in AI12-0363-1, that I didn't mention in our phone meeting.
>
> AARM Ramification: 1st sentence,
> "a subcomponent that is specified to be atomic is considered to also
> specify that {it} is independently addressable."

Good catch.

****************************************************************

From: Randy Brukardt
Sent: Monday, April 27, 2020  10:00 PM

AI12-0128-1 enhanced the rules for Atomic such that it can be used to
guarentee that only exact size access is used to access subcomponents of an
atomic composite object.

Recently, a request was made to eliminate some of the requirements of that AI
in order to allow more uses of atomic subcomponents. These can be seen in the
attached AI.

I believe that the changes suggested introduce a major maintenance hazard for
anyone that requires exact size access to some hardware. I'm posting here in
order to give people who are more likely to have that sort of requirement
than me to weigh in on this issue.

The problem as I see it is that to get exact size access to a hardware
register, one has to ensure that no subcomponent has an atomic subtype or is
directly declared atomic. If all of the types involved are declared together,
that's not hard to ensure, but anyone can change a declaration and break the
property. The compiler will not care, since there is no legality rule that is
broken -- just the generated code will change. But of course the generated
code will not work if some smaller access is generated.

If of course some of the types are declared in other units (even something as
simple as a status enumeration), then the verification gets even harder.

Even though the AI worries about breaking privacy, that is irrelevant here as
representation aspects always break privacy (and Atomic is a representation
aspect).

Of course, a need for exact size access is fairly rare, and having rules that
prevent certain types of subcomponents are likely to get in the way of
particular uses. Thus, it might be better to have an aspect to require only
exact size access, and reject any declaration that would violate that.
Otherwise, it seems to me that any exact size requirement is only going to be
followed until the first ham-handed maintainer.

Anyone have any informed thoughts on this topic?

P.S. The next ARG meeting is Wednesday, so a quick response would be
appreciated. If it needs more discussion we can remove it from the agenda of
that meeting.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, April 28, 2020  5:51 PM

>I am confused, Randy.  As far as I can tell this AI isn't relaxing the
>requirements. It is simply moving them to elsewhere in the standard.  Can you
clarify this?

Allowing atomic SUBcomponents makes the bad situation of AI12-0128-1 much worse
vis-a-vis the original problem of that AI. If one requires exact size access to
some external device, you have no way to guarantee that is the case short of
inspecting every subcomponent type to see if anything is declared atomic. Since
types can be declared atomic, and that can be added after the fact, one has a
substantial maintenance hazard.

Recall that the original problem occurs rarely but is critical when it happens.
What sometimes happens is that there is a memory-mapped device that only
responds to 32-bit read and write cycles (and not to 8-bit read/write cycles).
[I'm told this is a real problem in practice, I have no direct experience with
it myself, which is why I posted this here for public comment from those with
more experience.] We want to be able to use Ada bit-mapped records to access
this device, rather than have to do bit masking operations to get at the fields.
But if the Ada compiler generates an 8-bit atomic operation, the device will not
respond and the program will obviously fail.

We partially solved this problem in AI12-0128-1 by mandating that atomic objects
with nonatomic components are accessed exactly and one never reads/writes the
components individually. But this is a maintenance hazard, since if someone
declares one of the components atomic, the device will stop responding and the
code will presumably malfunction.

I went along with the original rules because there didn't seem to be a taste for
a separate aspect and because only the top-level components were allowed to be
atomic. That meant that one could pretty much inspect and heavily comment those
components, and maintenance problems would be fairly minimal (but not
eliminated, as shown below). However, with the elimination of that rule, now any
components that themselves are composite also would have to be inspected.

It would be best if a program that needs exact-size access but is not going to
get it gets rejected at compile-time. Otherwise, the code will silently fail as
the hardware restrictions are not followed and some reads and writes simply do
nothing (or even read bus noise). Avoiding that would pretty much mean that
every type used in such a register access has to be declared locally; there
can't be any reuse as that opens the danger of someone changing it in the future
and destroying code that they don't even know about.

For instance, imagine the following package exists somewhere in the system owned
by another group:

     package Register_Info is
          type Status is (Ready, Full, Empty, Unplugged, Error);
          for Status use (....);
          type Data is mod 2**8;
    end Register_Info;

We need to build access to a 32-bit memory mapped register, and the types above
are what we need. So we use them so we can better interface with the rest of the
system:

    with Register_Info; use Register_Info;

    package My_Device is
        type Device_Register is record
             Input_Status, Output_Status : Status;
             Input_Data, Output_Data : Data;
             Empty : Data;
       end record with Atomic;
       -- Record rep. clause here.

       The_Device : Device_Register with Address => ...;
   end My_Device;

With the rule changes of AI12-0128-1, this does what we want. However, it is
fragile, because a change in the declaration of either of the imported types
will break this declaration such that the uses of The_Device will silently
malfunction.

Remember that I suggested that the type package belongs to another group.
Perhaps that group decides that the data needs to be Atomic so that they can get
rid of some error messages from parallel. (Never mind that is a bad idea, people
do stuff like this all of the time.) If they do that, The_Device will no longer
work, but it still will compile. If this is maintenance in a long-running
system, it could take a long time before the maintainers will notice that the
size guarantee has been lost.

I realize that the rules as given in AI12-0128-1 are limiting for uses that
don't care about exact size sementics (which will be most of them). So my
suggestion is to allow the rules to be weakened back to almost no restrictions
on subcomponents (I don't see the point of distributing this Atomic annex
special case all over the Standard - it seems to violate our rules about keeping
the annexes separate from the core), but in addition to add an
Use_Exact_Size_Only aspect that can be given on an atomic type or object. If the
new aspect is True, there cannot be any atomic or aliased subcomponents (since
those would necessarily violate the needed behavior). This would more directly
meet the need and eliminate any maintenance hazards. (Note: We'd still require
any atomic object, even without the aspect, to write the exact bits if there are
no components that require otherwise. We do want to do that expected thing by
default; it's just that we can't allow some ham-handed maintainer to break that
if it is in fact an actual hardware requirement.)

Note that I don't see any reason to care about privacy for Atomic's rules. These
are representation aspects and those never care about privacy. Moreover, I don't
think people are using many private types in hardware interfacing. So the
concern is more theoretical than real. I'm suggesting using fewer restrictions
anyway, unless one gives the new aspect, and that should only be used in the
relatively rare case of memory mapped hardware that doesn't work with all sizes.

****************************************************************

From: Tucker Taft
Sent: Tuesday, April 28, 2020   7:41 PM

I think the fundamental question is what do you do when you have nested atomic
objects:

1) Make it illegal

2) Ignore the "atomic" on the components, and only obey atomicity on the
   outermost atomic object.  For everything else you "round up" the load/store
   size to match the *outermost* enclosing atomic object.

3) Obey atomicity at each level.  From a nonatomic subcomponent, round up to the
   *nearest* enclosing atomic object.

I think each of these are reasonable, depending on the application.
Unfortunately, we have to pick one.

I would argue (3) gives the programmer the most flexibility, since if they
actually have a hardware register that allows 32-bit reads, as well as 8-bit
reads, they can do it with (3) but not with any of the others.  If the hardware
doesn't allow 8-bit reads, then the programmer should not nest an atomic object
that is 8-bits in size inside the 32-bit atomic object.  And as you say private
types are not that common in such programming, so the programmer can see exactly
what they are doing.   Anyone who is writing a device driver is probably looking
very carefully at what types they are using.

So for me, (3) gives the programmer the most control, and is to some extent a
superset of the other capabilities.

I vaguely remember my days of directly addressing hardware registers, and I
believe there were some that allowed both word and byte access, though who knows
if that is a real memory, or whether it still applies now.

But the fundamental point is (3) gives the programmer the ability to choose what
they want to do.

It seems that either approach could introduce a bug if the programmer doesn't
know what they are doing, or if some change is made in maintenance.  But for
hardware device drivers, my sense is you want to give control, more than you
want to somehow protect the programmer from themself.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, April 28, 2020  9:24 PM

>I think the fundamental question is what do you do when you have nested atomic
>objects:
>
>1) Make it illegal
>
>2) Ignore the "atomic" on the components, and only obey atomicity on the
>   outermost atomic object.  For everything else you "round up" the load/store
>   size to match the *outermost* enclosing atomic object.
>
>3) Obey atomicity at each level.  From a nonatomic subcomponent, round up to
>   the *nearest* enclosing atomic object.
>
>I think each of these are reasonable, depending on the application.
>Unfortunately, we have to pick one.

Why do we have to pick only one? The usual case of atomic objects and this
particular hardware case are very different and there is a much different
requirement in the latter case. While in the normal case, the exact rule doesn't
matter and the flexibility seems valuable.

I think it is absolutely necessary for the programmer to tell the compiler when
this exact size case is required. Then the compiler can (and has to) reject
anything that doesn't meet the exact size requirements. Anything else is very
unsafe, since the code can silently get the wrong answer (since the hardware
will not be read).

>...
>I vaguely remember my days of directly addressing hardware registers, and I
>believe there were some that allowed both word and byte access, though who
>knows if that is a real memory, or whether it still applies now.

I made this point when the subject originally came up, and I was told by a
number of people that hardware with these sorts of limitations shows up rather
regularly. A lot of these registers are byte addressed anyway (no larger
access), so the problem probably doesn't really show up with those.

Anyway, the reason I posted here was to get some feedback from real embedded
practioners as to whether this is common enough to have a special aspect to
declare. Silence is a form of an answer, I guess, but we haven't given them
enough time.

>  It seems that either approach could introduce a bug if the programmer doesn't
> know what they are doing, or if some change is made in maintenance.  But for
> hardware device drivers, my sense is you want to give control, more than you
> want to somehow protect the programmer from themself.

It's not themself, it's the guy that comes along 5 years from now and knows
nothing about exact size accesses and little about atomics. You are essentially
saying that if there is any such exact size access required, you have to write
it completely self-contained, comment it heavily, and then use other types to
communicate the results to the rest of the program. There's no possibility of
reuse or sharing because to have those things greatly increases the chance of a
change. And the program will silently malfunction if it wrong -- no errors, no
traps, nothing. That to me is the C approach -- leave it up to the programmer to
do the right thing - and if they don't, too bad for them (and the people flying
on their airplane).

If we're not going to solve the original problem at all, then AI12-0128-1 was a
complete waste of time. Any reasonable compiler would have done the right thing
most of the time anyway, and since this stuff is untestable, it's highly likely
that will remain the case. At least having a testable aspect would clue
implementors into the importance of the issue.

Hopefully some embedded programmers will comment.

****************************************************************

From: Jeff Cousins
Sent: Wednesday, April 29, 2020  3:11 AM

...
>> I vaguely remember my days of directly addressing hardware registers, and I
>>believe there were some that allowed both word and byte access, though who
>>knows if that is a real memory, or whether it still applies now.

>I made this point when the subject originally came up, and I was told by a
>number of people that hardware with these sorts of limitations shows up
>rather regularly. A lot of these registers are byte addressed anyway (no
>larger access), so the problem probably doesn't really show up with those.

Stretching the memory cells here, but at one time I wrote most of the device
drivers in the company, and I think you’re correct (i.e. such fussy h/w can
exist) .

****************************************************************

From: Simon Wright
Sent: Wednesday, April 29, 2020  6:44 AM

I just checked briefly through the first few peripherals' register descriptions
in the STM32F4xxx Reference Manual issue 11. Some of them leave it open (I'd
guess at 32 bit-only), but the ADC says "The peripheral registers must be
written at word level (32 bits). Read accesses can be done by bytes (8 bits),
half-words (16 bits) or words (32 bits)." whereas the DAC says 32 bit only.

DCMI says "All DCMI registers have to be accessed as 32-bit words, otherwise a
bus error occurs." which would at least reduce the chance of missing a
programming error.

TIM1 & TIM8 say "The peripheral registers must be written by half-words (16
bits) or words (32 bits). Read accesses can be done by bytes (8 bits), half-word
(16 bits) or words (32 bits)."

****************************************************************

From: Tucker Taft
Sent: Wednesday, April 29, 2020  7:08 AM

Another issue worth considering is that Ada 2012 semantics correspond to (3) for
nested atomic objects.  Ada 2012 makes no requirement about "rounding up" of
nonatomic subcomponents of an atomic object.  But for nested atomic objects,
there is no rounding up in Ada 2012.  So we should think about whether
compatibility should be a relevant concern in this decision.

****************************************************************

From: Tucker Taft
Sent: Wednesday, April 29, 2020  7:25 AM

>>I think the fundamental question is what do you do when you have nested atomic
>>objects:
>>
>>1) Make it illegal
>>
>>2) Ignore the "atomic" on the components, and only obey atomicity on the
>>   outermost atomic object.  For everything else you "round up" the load/store size to match the *outermost* enclosing atomic object.
>>
>>3) Obey atomicity at each level.  From a nonatomic subcomponent, round up to
>>   the *nearest* enclosing atomic object.
>>
>>I think each of these are reasonable, depending on the application.
>>Unfortunately, we have to pick one.

>Why do we have to pick only one? The usual case of atomic objects and this
>particular hardware case are very different and there is a much different
>requirement in the latter case. While in the normal case, the exact rule
>doesn't matter and the flexibility seems valuable.
>
>I think it is absolutely necessary for the programmer to tell the compiler when
>this exact size case is required. Then the compiler can (and has to) reject
>anything that doesn't meet the exact size requirements. Anything else is very
>unsafe, since the code can silently get the wrong answer (since the hardware
>will not be read).  ...

AdaCore has a separate aspect (Volatile_Full_Access -- VFA) but I believe we
chose instead to make "atomic" work the "right way."  The reason is that you
still need to address what happens when Atomic objects occur inside of a VFA
object, and vice-versa.  So I don't think having a separate aspect really
addresses the concern.  And based on responses to this, it seems that both sort
of situations come up, and almost certainly all of them want rounding up of
*non* atomic subcomponents, so it all comes down to whether atomicity is lost if
you have an atomic object nested inside something that requires rounding-up.  I
am not seeing a real need to override the atomicicity of a nested object, at
least not in all cases.  What we could add is an aspect that *disallows* nested
atomic objects.  So we would could support both (1) and (3), depending on the
state of this additional aspect.  (2) seems like it is both more error prone and
less flexible.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, April 29, 2020  9:25 AM

That's what I've been suggesting all along.

****************************************************************

From: Richard Wai
Sent: Wednesday, April 29, 2020  9:04 AM

There is definitely a case these days for requiring atomic word/doubleword-sized
registers. Most architectures that I’m familiar with, particularly RISC-V and
ARM require the entire register to be accessed at once.

My two cents is that (2) seems to be the most sane in practice. Since most
architectures can’t support atomic operations larger than a (double)word
anyways, the programmer will be restricted to subcomponents that are smaller
than a (double)word. It wouldn’t make logical sense to have a record, ostensibly
targeting a single register, to have non-atomic components anyways. From the
top-down perspective, having a rule that says “if this record is atomic, all
it’s components are always atomic” makes the most sense. Its an easy rule to
understand. You’re not likely to have a large record capable of being atomic
anyways, so I don’t see much use in allowing complex atomic and non-atomic mixes
allowed by (3). Even huge architectures like the upcoming 128-bit RISC-V ISA,
one would probably not benefit much from having non-atomic components in your
128 bit atomic record.

****************************************************************

From: Tero Koskinen
Sent: Thursday, April 30, 2020  2:20 PM

Sorry, I am little late to this discussion, but I guess I can count as a real
embedded practitioner.

I usually work with 32-bit ARM Cortex-M{0,4,7,23,33} microcontrollers.

They are quite common and relatively simple 32-bit processors with 4GB flat
memory map and 16-bit & 32-bit instruction sets.

The 4GB memory map contains various different areas which are mapped to
different processor peripherals. Normal RAM is one area. GPIO pin control is
another area. Builtin flash (non-volatile memory) is yet another area, and so
on.

Some areas, like RAM, do not not have alignment or size requirements/limits for
access (8-bit, 16-bit, 32-bit read/write operation works - the address can even
be unaligned in many cases).

However, other areas, like flash, have much stricter alignment and size
requirements. Some ARM Cortex-M processors have 16-bit write size requirement.
Also the alignment must be 16-bit (even addresses). ARM Cortex-M processor from
another vendor on the other hand might have 32-bit write size and alignment
requirements for flash memory area.

It is also case dependent what happens if you don't follow the requirements. In
some cases the code fails silently. In other case, the processor goes into a
failure mode (special interrupt handler for example, or reboot in worst case).


In addition to above areas, ARM Cortex-M processors optionally can have so
called bit-banded memory area. In this kind of area, one 32-bit data access for
an address is mapped to a single bit in another address.

So, for example, let's assume that 1kB bit-band area starts from 16#0000_F000#
and is mapped to address 16#0010_0000#.

Writing 16#0000_0001# to address 16#0000_F004# sets the second lowest bit to 1
at address 16#0010_0000#. (=> 32-bit reading from 16#0010_0000# will get us
value 16#0000_0002# if the initial value was 0.)

This allows atomic bit operations for certain memory areas.

****************************************************************

From: Weston Pan
Sent: Wednesday, April 29, 2020  6:05 AM

There was a lot to read, so hopefully I understood it all.

I personally think if an object/type is atomic, there should not be any atomic
components/subcomponents within it. If a {sub}component is specified to be of an
atomic type (or is a type that contains some), either it should be rejected or
the atomicity ignored and a compiler warning is given. I'm agree with Randy that
to allow atomic {sub}components to be buried within can lead to undesirable
maintenance issues that would be hard to track. For register level programming,
I have only needed atomicity for the register as whole (i.e. never for fields
within a register). Outside of register level programming, I can't think of a
reason why you would apply Atomic aspect at a higher level and at the same time
at a piece-meal level too. Atomicity at the higher level is probably the only
level that matters. For any finer grain of control, I would think it probably
involves data that is large enough that it cannot be handled with simple CPU
word read/write access, and instead constructs such as protected types would be
needed instead. With that in mind, I think A-12-0128-1 should not have
distinguished between nonatomic/atomic {sub}components and kept it simply as
"{sub}components".

****************************************************************

From: Bill Wong
Sent: Wednesday, April 29, 2020  9:53 AM

> I just checked briefly through the first few peripherals' register
> descriptions in the STM32F4xxx Reference Manual issue 11. ...

I was also going to mention this as I have been trying to get a runtime working
for TI's chips and it has similar requirements. Hiding access behind a function
is currently what I was working with but developers often what direct access.

****************************************************************

From: Weston Pan
Sent: Wednesday, April 29, 2020  2:23 PM

I am surprised by Richard's comment. To me it does *not* make sense to have
atomic subcomponents in a register. The register as a whole is consider atomic
for a reason, specifically a hardware restriction. By allowing atomic operations
on a subcomponent, then the issue that Randy pointed out about violating the
proper memory access can occur (e.g. Randy's example of a byte read/write access
being performed on a register that requires a 32-bit read/write).

Regarding Simon's comment about ARM registers allowing different sized read
access but a 32-bit write restriction, doesn't mean that different sized read
operations need to be enforced/allowed on the register. I think the flexibility
on reads is because having multiple read access is safe (e.g. similar to
multiple readers of a protected object). However, that doesn't mean you have to
allow all the types of reads on an Ada object that overlays the register. I
think it makes more sense to go with the highest restriction, in Simon's case a
32-bit write access, and just apply that for reads as well (i.e. both read and
write are similar).

Granted, I can only go based on my limited experience at register programming,
but unless someone can provide a good example of why having atomic subcomponents
or even a mixture of non-atomic and atomic subcomponents for registers should be
allowed, I still think atomic objects should be forbidden or removed when
contained in an atomic object.

****************************************************************

From: Weston Pan
Sent: Wednesday, April 29, 2020  2:34 PM

Minor correction to my last sentence:

I still think atomic subcomponents at any deeper level should be forbidden or
the atomic aspect for them should be ignored when contained within an atomic
object.

****************************************************************

From: Tucker Taft
Sent: Thursday, May 14, 2020  1:05 PM

In C.6(6.10/3) the RM says:

If any of these aspects are directly specified, the aspect_definition shall be a
static expression. If not specified (including by inheritance), each of these
aspects is False.

It seems odd that Volatile and independent are False if not specified.  We say
that if you specify something is Atomic, then it is also Volatile.  So doesn't
that mean that specifying something as Atomic implicitly also specifies it to be
Volatile?  We certainly don't want to allow someone to specify Atomic => True,
Volatile => False.  It feels like the wording of this paragraph needs some work,
or we need to establish a stronger rule that specifying Atomic => True implies
both Volatile=>True and Independent=>True.

****************************************************************

From: Jeff Cousins
Sent: Thursday, May 14, 2020  1:34 PM

Seems a good point.

****************************************************************

From: Richard Wai
Sent: Thursday, May 14, 2020  7:28 PM

> It seems odd that Volatile and independent are False if not specified.
> We say that if you specify something is Atomic, then it is also Volatile.  So
> doesn't that mean that specifying something as Atomic implicitly also
> specifies it to be Volatile?

That was certainly my expectation of Atomic.. I'm actually stunned that C.6
doesn't make this explicit anywhere.

> We certainly don't want to allow someone to specify Atomic => True,
> Volatile => False.

I can imagine cases where you know that an atomic value is being changed
synchronously, but yet you want any actual writes or reads to be atomic.
For example, you are inside of an ISR that is reading some kind of buffer
register. That would allow the user to map an object directly to the address
of that register with Atomic => True, Volatile => False, and the compiler could "correctly" optimize-out multiple reads, thus avoiding the need to copy values. But this seems to be such a corner case, and such an insignificant advantage that it's hardly an
 argument to allow it. OTOH, this seems to create the potential for implementation-defined funny business. If we let users have Atomic => True, Volatile => False entities, then the user would need to make correct assumptions about how the compiler might op
timize reads and writes. That seems pretty dangerous and un-Ada-like. It's even worse if we look at the write-side of the equation, where you probably don't want the compiler deciding if multiple writes of the same value to a register should be "optimized"
.

Incidentally, I tested it and GNAT (GCC 9.2.0) accepts this:

type My_ATM is mod 2**8 with Atomic => True, Volatile => False;

It gave me no complaints.

> It feels like the wording of this paragraph needs some work, or we
> need to establish a stronger rule that specifying Atomic =>
> True implies both Volatile=>True and Independent=>True.

Agreed.

****************************************************************

From: Randy Brukardt
Sent: Thursday, May 14, 2020  8:00 PM

I think that the original pragmas were defined independently of each other, so
the wording was written such that only one was specified. We probably left the
wording that way.

Even so, I agree that keeping Volatile and Independent matching Atomic might
make more sense. However, in that case, I'd guess that some of the rules are
redundant when they say that the same rule applies to Atomic as to Volatile.
Especially the rule that says all atomic entities are volatile.

Are you proposing wording changes and an AI write-up? :-) [How are you going to
have time to do AdaCore work before the next meeting?? :-)]

****************************************************************

From: Tucker Taft
Sent: Thursday, May 14, 2020  8:07 PM

Yes, I'll take a shot at it.  Steve and I are debating the rule about formal
array types and volatility as well, which I might fold into yet another C.6
fix-up.  I think we still are debating the one having to do with atomicity and
nesting.  I wonder whether we ultimately need two aspects, Atomic which works
the way the current one does, which allows nesting, and "Atomic_Full_Access" or
equivalent which disallows any nested Atomic (or Atomic_Full_Access)
subcomponents.  Both of them would require rounding up of non-atomic
subcomponents, but one would disallow having nested atomic subcomponents.

****************************************************************

From: Randy Brukardt
Sent: Thursday, May 14, 2020  9:38 PM

I think Atomic_Full_Access would work; I've always viewed it as an option on the
existing Atomic (I'd expect the rules would require far less change that way)
but I don't think that it would be a problem to do it the other way (just more
change is needed).

****************************************************************

From: Tucker Taft
Sent: Friday, May 15, 2020  9:09 AM

We could have a separate "Full_Access_Only" or "No_Nested_Atomic" or something
like that, which would only be meaningful in conjunction with Atomic.

****************************************************************

From: Randy Brukardt
Sent: Friday, May 15, 2020  12:42 PM

Yup, that's what I was thinking. Didn't have a good name for it though.

****************************************************************

Questions? Ask the ACAA Technical Agent