C.6 Shared Variable Control
1
[This clause specifies representation pragmas that 
control the use of shared variables.] 
Syntax
2
The form for 
pragmas Atomic, Volatile, Atomic_Components, and Volatile_Components 
is as follows: 
3
  pragma Atomic(
local_name);
 
4
  pragma Volatile(
local_name);
 
5
  pragma Atomic_Components(
array_local_name);
 
6
  pragma Volatile_Components(
array_local_name);
 
7/2
{
AI95-00272-01} 
{atomic} An 
atomic type is one to which a pragma Atomic applies. An 
atomic 
object (including a component) is one to which a pragma Atomic applies, 
or a component of an array to which a pragma Atomic_Components applies, 
or any object of an atomic type
, other than objects 
obtained by evaluating a slice.
 
7.a/2
Ramification: {
AI95-00272-01} 
A slice of an atomic array object is not itself 
atomic. That's necessary as executing a read or write of a dynamic number 
of components in a single instruction is not possible on many targets. 
 
8
{volatile} 
A 
volatile type is one to which a pragma Volatile 
applies. A 
volatile object (including a component) is one to which 
a pragma Volatile applies, or a component of an array to which a pragma 
Volatile_Components applies, or any object of a volatile type. In addition, 
every atomic type or object is also defined to be volatile. Finally, 
if an object is volatile, then so are all of its subcomponents [(the 
same does not apply to atomic)]. 
 
Name Resolution Rules
9
The local_name in an Atomic 
or Volatile pragma shall resolve to denote either an object_declaration, 
a non-inherited component_declaration, or 
a full_type_declaration. The array_local_name 
in an Atomic_Components or Volatile_Components pragma shall resolve to 
denote the declaration of an array type or an array object of an anonymous 
type.
Legality Rules
10
{indivisible} 
It is illegal to apply either an Atomic or Atomic_Components 
pragma to an object or type if the implementation cannot support the 
indivisible reads and updates required by the pragma (see below).
 
11
It is illegal to specify the Size attribute of an 
atomic object, the Component_Size attribute for an array type with atomic 
components, or the layout attributes of an atomic component, in a way 
that prevents the implementation from performing the required indivisible 
reads and updates.
12
If an atomic object is passed as a parameter, then 
the type of the formal parameter shall either be atomic or allow pass 
by copy [(that is, not be a nonatomic by-reference type)]. 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 an atomic type is used as an actual for a generic formal derived type, 
then the ancestor of the formal type shall be atomic or allow pass by 
copy. Corresponding rules apply to volatile objects and types.
13
If a pragma Volatile, Volatile_Components, Atomic, 
or Atomic_Components applies to a stand-alone constant object, then a 
pragma Import shall also apply to it. 
13.a
Ramification: Hence, no initialization 
expression is allowed for such a constant. Note that a constant that 
is atomic or volatile because of its type is allowed. 
13.b
Reason: Stand-alone constants that are 
explicitly specified as Atomic or Volatile only make sense if they are 
being manipulated outside the Ada program. From the Ada perspective the 
object is read-only. Nevertheless, if imported and atomic or volatile, 
the implementation should presume it might be altered externally. For 
an imported stand-alone constant that is not atomic or volatile, the 
implementation can assume that it will not be altered. 
Static Semantics
14
{representation pragma 
(Atomic) [partial]} {pragma, 
representation (Atomic) [partial]} {representation 
pragma (Volatile) [partial]} {pragma, 
representation (Volatile) [partial]} {representation 
pragma (Atomic_Components) [partial]} {pragma, 
representation (Atomic_Components) [partial]} {representation 
pragma (Volatile_Components) [partial]} {pragma, 
representation (Volatile_Components) [partial]} These 
pragmas are representation pragmas (see 
13.1).
 
Dynamic Semantics
15
For an atomic object (including an atomic component) 
all reads and updates of the object as a whole are indivisible.
16
For a volatile object all reads and updates of the 
object as a whole are performed directly to memory. 
16.a
Implementation Note: This precludes any 
use of register temporaries, caches, and other similar optimizations 
for that object. 
17
{sequential (actions)} 
Two actions are sequential (see 
9.10) 
if each is the read or update of the same atomic object.
 
18
{by-reference type 
(atomic or volatile) [partial]} If a type 
is atomic or volatile and it is not a by-copy type, then the type is 
defined to be a by-reference type. If any subcomponent of a type is atomic 
or volatile, then the type is defined to be a by-reference type.
 
19
If an actual parameter is atomic or volatile, and 
the corresponding formal parameter is not, then the parameter is passed 
by copy. 
19.a
Implementation Note: Note that in the 
case where such a parameter is normally passed by reference, a copy of 
the actual will have to be produced at the call-site, and a pointer to 
the copy passed to the formal parameter. If the actual is atomic, any 
copying has to use indivisible read on the way in, and indivisible write 
on the way out. 
19.b
Reason: It has to be known at compile 
time whether an atomic or a volatile parameter is to be passed by copy 
or by reference. For some types, it is unspecified whether parameters 
are passed by copy or by reference. The above rules further specify the 
parameter passing rules involving atomic and volatile types and objects. 
Implementation Requirements
20
{external effect 
(volatile/atomic objects) [partial]} The 
external effect of a program (see 
1.1.3) 
is defined to include each read and update of a volatile or atomic object. 
The implementation shall not generate any memory reads or updates of 
atomic or volatile objects other than those specified by the program. 
 
20.a
Discussion: The presumption is that volatile 
or atomic objects might reside in an “active” part of the 
address space where each read has a potential side-effect, and at the 
very least might deliver a different value.
20.b
The rule above 
and the definition of external effect are intended to prevent (at least) 
the following incorrect optimizations, where V is a volatile variable: 
20.c
- X:= V; Y:=V; cannot be allowed 
to be translated as Y:=V; X:=V;
 
20.d
- Deleting redundant loads: X:= 
V; X:= V; shall read the value of V from memory twice.
 
20.e
- Deleting redundant stores: V:= 
X; V:= X; shall write into V twice.
 
20.f
- Extra stores: V:= X+Y; should 
not translate to something like V:= X; V:= V+Y;
 
20.g
- Extra loads: X:= V; Y:= X+Z; 
X:=X+B; should not translate to something like Y:= V+Z; X:= V+B;
 
20.h
- Reordering of loads from volatile 
variables: X:= V1; Y:= V2; (whether or not V1 = V2) should not translate 
to Y:= V2; X:= V1;
 
20.i
- Reordering of stores to volatile 
variables: V1:= X; V2:= X; should not translate to V2:=X; V1:= X; 
 
21
If a pragma Pack applies to a type any of whose subcomponents 
are atomic, the implementation shall not pack the atomic subcomponents 
more tightly than that for which it can support indivisible reads and 
updates. 
21.a
Implementation Note: A warning might 
be appropriate if no packing whatsoever can be achieved. 
Implementation Advice
22/2
 {
AI95-00259-01} 
A load or store of a volatile object whose size 
is a multiple of System.Storage_Unit and whose alignment is nonzero, 
should be implemented by accessing exactly the bits of the object and 
no others.  
22.a/2
Implementation Advice: 
A load or store of a volatile object 
whose size is a multiple of System.Storage_Unit and whose alignment is 
nonzero, should be implemented by accessing exactly the bits of the object 
and no others.
22.b/2
Reason: Since any 
object can be a volatile object, including packed array components and 
bit-mapped record components, we require the above only when it is reasonable 
to assume that the machine can avoid accessing bits outside of the object. 
22.c/2
Ramification: This 
implies that the load or store of a volatile object that meets the above 
requirement should not be combined with that of any other object, nor 
should it access any bits not belonging to any other object. This means 
that the suitability of the implementation for memory-mapped I/O can 
be determined from its documentation, as any cases where the implementation 
does not follow Implementation Advice must be documented. 
23/2
 {
AI95-00259-01} 
A load or store of an atomic object should, where 
possible, be implemented by a single load or store instruction. 
 
23.a/2
Implementation Advice: 
A load or store of an atomic object 
should be implemented by a single load or store instruction.
24
9  An imported volatile or atomic constant 
behaves as a constant (i.e. read-only) with respect to other parts of 
the Ada program, but can still be modified by an “external source.”
Incompatibilities With Ada 83
24.a
{
incompatibilities with Ada 83} 
Pragma 
Atomic replaces Ada 83's pragma Shared. The name “Shared” 
was confusing, because the pragma was not used to mark variables as shared. 
 
Wording Changes from Ada 95
24.b/2
{
AI95-00259-01} 
Added Implementation Advice to clarify the meaning 
of Atomic and Volatile in machine terms. The documentation that this 
advice applies will make the use of Ada implementations more predictable 
for low-level (such as device register) programming. 
24.c/2
{
AI95-00272-01} 
Added wording to clarify that a slice of an object 
of an atomic type is not atomic, just like a component of an atomic type 
is not (necessarily) atomic.