Henry Spencer on C's volatile
Henry Spencer sent me a reply to my previous entry
on volatile that corrects some of my (mis)information, and I am
putting it here with his permission:
I fear you've miscalled this one. ANSI C pre-dates aggressive memory
controllers in consumer CPUs, but it had extensive participation by
people in the supercomputer world as well, and such things were common
there long ago.
The key issue you've missed is that ANSI C doesn't really acknowledge the
existence of a "compiler". It's phrased almost completely in terms of an
"implementation", which takes in source code and spits out execution
results. It is the implementation's responsibility to ensure that
accesses to `volatile' variables happen in the order specified. If the
implementation consists of a compiler plus a CPU, it is the compiler's job
to make the CPU do the right thing, however difficult that may be.
There is some leeway here, because some aspects of the precise definition
of the "right thing" are up to the implementation... but ANSI C does
require that they be documented.
Compiler implementers -- except on supercomputers -- are notoriously
casual about these issues, but it is technically their responsibility to
establish exact rules and then force the hardware to live up to them.
It is unfortunately true that memory barriers etc. are a complicated
subject, and `volatile' is too simplistic (and has too many different
uses) to capture all of what people want done.
Henry
I suspect that the gcc people would counter-argue from two possible
positions:
- because threading and memory semantics are not defined in ANSI C,
no strictly conforming ANSI C program can have shared state issues
that require memory barriers, and so the compiler is not required to
implement them for
volatile accesses; the compiler-level actions
are good enough.
- almost all code (mis)uses
volatile in ways that do not require
memory barriers and which would slow down significantly if memory
barriers were introduced. Thus, regardless of the letter of ANSI
C, volatile accesses will not introduce memory barriers.
Especially if the first is correct, this reduces gcc's sins to at
most failing to document what volatile does and doesn't do (and I'm
not convinced that they're even failing at that; they do have a small
section about it in the info docs, which might be good enough in that
it doesn't say that they do do memory barriers et al).