Rationale for Ada 2012
5.5 Volatile
This is a curious topic and created much debate.
For the collector of statistics the real part of the AI is less than
two pages but the appendix has nearly twenty pages of chatter!
The problem is all about sharing variables and ensuring
that things happen in the correct order. Moreover, we need to avoid the
overhead of protected objects particularly on microprocessors where we
might be using low level features such as synchronous barriers discussed
in section
5.2 above.
Suppose we have two
tasks A and B which
access some shared data perhaps in a nice package Common
thus
package Common is
...
Data: Integer;
pragma Volatile(Data);
Flag: Boolean;
pragma Volatile(Flag);
...
end Common;
and in task A
we write
with Common; use Common;
task A is
...
Data := 42;
Flag := True;
...
end A;
whereas in task B
we have
with Common; use Common;
task B is
Copy: Integer;
begin
...
loop
exit when Flag; -- spin
end loop;
Copy := Data;
...
end B;
The idea is that task A
assigns some value to Data and then indicates
this to task B by setting Flag
to true. Meanwhile, task B loops checking
Flag and when it is found to be true, then
reads the Data.
Does this work in Ada 2005? Hmm. Nearly. There are
three things that need to be ensured. One is that Flag
gets changed in one lump. Another is that the new value of Data
assigned by task A truly is updated when task
B reads it. And the third is that the actions
happen sequentially. Well, we should have applied pragma Atomic
to Flag to ensure the first but since it is
of type Boolean we might get away with it.
And note that Atomic implies Volatile
anyway. Also Atomic ensures that the actions
are sequential.
So, with the pragma Volatile
changed to Atomic for Flag,
it does indeed work in Ada 2005 because Volatile
ensures that read and writes are to memory and so things do happen in
the correct order. However, this is overkill. It is not necessary that
all accesses are to memory; all that matters is that they happen in the
correct order so they could be to some intermediate cache. Indeed, there
might be nested caches and as hardware evolves it is becoming more difficult
to make general statements about its structure; hence we can really only
make statements about the effect.
The possibility of
introducing a new pragma Coherent was debated
for some time. However, it was ultimately concluded that the definition
of Volatile should be weakened. In Ada 2005
it says
For a volatile object all reads and updates of
the object as a whole are performed directly to memory.
In Ada 2012 it says
All tasks of the program (on all processors) that
read or write volatile variables see the same order of updates to the
variables.
Of course, in Ada 2012,
we use aspects so the package
Common becomes
package Common is
...
Data: Integer
with Volatile;
Flag: Boolean
with Atomic; -- Atomic implies Volatile
...
end Common;
where we have given Atomic
for Flag. As mentioned above, Atomic
implies Volatile so it is not necessary to
give both. However, if we do have to give two aspects, it is much neater
that the one aspect specification does this whereas two distinct pragmas
would be necessary.
It is said that this change brings the meaning of
volatile into line with that in C. However, it has also been said that
the definition of volatile in C is unclear.
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by: